/* ==========================================================================
   Backlog page: header and shame stats, sticky filter bar, tabs, dense rows.
   Every theme shares this layout; the signatures at the end of the file restyle it.
   ========================================================================== */

/* The card clips instead of scrolling, so the filter bar can stick to the page. */
.backlog-card {
  overflow: clip;
}

.backlog-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
}

.backlog-heading {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: var(--space-2) var(--space-3);
}

.backlog-stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3) var(--space-6);
  margin: 0;
}

.backlog-stat {
  display: flex;
  flex-direction: column-reverse;
  align-items: center;
}

.backlog-stat dt {
  font-size: var(--text-xs);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.backlog-stat dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

.backlog-stat-main dd {
  color: var(--danger);
}

.backlog-pick {
  width: min(100%, 18rem);
}

.backlog-pick .randomizer-banner {
  max-height: 56px;
}

/* Filter bar: search, selects, the free-to-play toggle and the sort. */
.backlog-filters {
  position: sticky;
  top: var(--bar-h);
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-3) 0;
  margin-bottom: var(--space-3);
  background: var(--surface-card);
  border-bottom: 1px solid var(--border-subtle);
}

.backlog-filter-search {
  position: relative;
  flex: 1 1 12rem;
  max-width: 18rem;
}

.backlog-filter-search .search-icon {
  left: var(--space-3);
  color: var(--text-secondary);
}

.backlog-search-input {
  width: 100%;
  min-height: 36px;
  padding: var(--space-2) var(--space-3) var(--space-2) 2.25rem;
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-sm);
  background: var(--surface-chip);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.backlog-search-input:focus {
  border-color: rgb(var(--accent-rgb) / .5);
}

.backlog-filter-selects {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.backlog-free-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 36px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  cursor: pointer;
}

.backlog-free-toggle input {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--accent);
}

/* The sort and the tabs are one idiom: a segmented control. */
.backlog-sort,
.backlog-tabs {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  min-width: 0;
  padding: 2px;
  margin: 0;
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.backlog-sort {
  margin-left: auto;
}

.backlog-sort-option span,
.backlog-tab-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 32px;
  padding: 0 var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-decoration: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color .15s, color .15s;
}

.backlog-sort-option span:hover,
.backlog-tab-link:hover {
  color: var(--text-primary);
}

.backlog-sort-option input:checked + span,
.backlog-tab-link[aria-current] {
  color: var(--on-accent);
  background: var(--gradient-primary);
}

.backlog-sort-option input:focus-visible + span {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

.backlog-tab-count {
  font-variant-numeric: tabular-nums;
  opacity: .85;
}

/* The list */
.backlog-list-frame {
  display: block;
}

.backlog-tabs {
  margin-bottom: var(--space-3);
}

.backlog-guest {
  margin: 0 0 var(--space-3);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  background: rgb(var(--accent-rgb) / .06);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

/* Netrunner's command line; the other themes leave it out. */
.backlog-prompt {
  display: none;
}

.backlog-list-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.backlog-status {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.backlog-bulk,
.backlog-bulk-actions:not([hidden]) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.backlog-bulk-count {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.backlog-bulk-btn {
  min-height: 32px;
  padding: 0 var(--space-3);
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-sm);
  background: var(--surface-chip);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.backlog-bulk-btn:disabled {
  opacity: .5;
  cursor: not-allowed;
}

.backlog-list-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* About 64px a row: image, title and details, score, actions. The title link stretches over the
   row; the checkbox and the buttons sit above it. Rows off screen skip layout and paint. */
.backlog-item-row {
  position: relative;
  display: grid;
  text-align: start;
  grid-template-columns: 120px minmax(0, 1fr) 44px 84px;
  align-items: center;
  gap: var(--space-3);
  min-height: 64px;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-subtle);
  content-visibility: auto;
  contain-intrinsic-size: auto 72px;
  transition: background-color .15s;
}

.backlog-item-row:is(:hover, :focus-within) {
  background: var(--surface-row-hover);
}

.backlog-row-perms {
  display: none;
}

.backlog-row-image {
  position: relative;
  grid-column: 1;
  grid-row: 1;
  width: 120px;
  aspect-ratio: 460 / 215;
  overflow: hidden;
  background: var(--surface-inset);
  border-radius: var(--radius-sm);
}

.backlog-row-image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.backlog-row-info {
  grid-column: 2;
  min-width: 0;
}

.backlog-row-title {
  margin: 0;
  overflow: hidden;
  font-size: var(--text-md);
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.backlog-row-link {
  color: inherit;
  text-decoration: none;
}

.backlog-row-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.backlog-row-link:hover {
  text-decoration: underline;
}

.backlog-row-link:focus-visible {
  outline: none;
}

.backlog-item-row:has(.backlog-row-link:focus-visible) {
  outline: 2px solid var(--focus-ring);
  outline-offset: -2px;
}

.backlog-row-details {
  margin: 2px 0 0;
  overflow: hidden;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.backlog-row-score {
  grid-column: 3;
  grid-row: 1;
  display: grid;
  place-items: center;
  width: 40px;
  height: 30px;
  font-size: var(--text-sm);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  border-radius: var(--radius-sm);
}

.meta-none {
  color: var(--text-secondary);
}

.backlog-row-actions {
  position: relative;
  z-index: 2;
  grid-column: 4;
  grid-row: 1;
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}

.backlog-row-form {
  display: flex;
  margin: 0;
}

.backlog-row-action {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  color: var(--text-secondary);
  background: var(--surface-chip);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  cursor: pointer;
  opacity: .7;
  transition: opacity .15s, color .15s, border-color .15s;
}

.backlog-item-row:is(:hover, :focus-within) .backlog-row-action {
  opacity: 1;
}

.backlog-row-action:hover {
  color: var(--accent);
  border-color: rgb(var(--accent-rgb) / .5);
}

.backlog-row-check {
  position: absolute;
  z-index: 2;
  top: 50%;
  left: var(--space-2);
  display: none;
  width: 22px;
  height: 22px;
  margin: 0;
  translate: 0 -50%;
  accent-color: var(--accent);
}

.is-selecting .backlog-row-check {
  display: block;
}

/* Hidden and snoozed rows: a faded image and a bar on the left. */
.backlog-item-row:is(.is-hidden, .is-snoozed) {
  box-shadow: inset 3px 0 0 var(--text-secondary);
}

.backlog-item-row.is-snoozed {
  box-shadow: inset 3px 0 0 var(--accent);
}

.is-hidden .backlog-row-image img {
  filter: grayscale(1);
  opacity: .6;
}

.is-snoozed .backlog-row-image img {
  filter: saturate(.3);
}

.backlog-next-page {
  display: block;
  padding: var(--space-3) 0;
  text-align: center;
}

.btn-load-more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--space-6);
  color: var(--text-primary);
  text-decoration: none;
  background: var(--surface-chip);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.backlog-end {
  margin: var(--space-4) 0 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-align: center;
}

.backlog-empty-state {
  padding: var(--space-8) var(--space-4);
  color: var(--text-secondary);
  text-align: center;
}

.backlog-empty-title {
  display: block;
  margin-bottom: var(--space-1);
  font-weight: 700;
  color: var(--text-primary);
}

.backlog-empty-action {
  display: inline-block;
  margin-top: var(--space-3);
}

/* Phones: the page scrolls (no inner scroller), rows become an 88px thumbnail grid, every target is 44px. */
@media (max-width: 767px) {
  .backlog-filters {
    position: static;
  }

  .backlog-stats {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-2);
    width: 100%;
  }

  .backlog-stat dt {
    font-size: .625rem;
    letter-spacing: 0;
    text-align: center;
  }

  .backlog-stat dd {
    font-size: var(--text-md);
  }

  .backlog-filter-search {
    flex-basis: 100%;
    max-width: none;
  }

  .backlog-filter-selects {
    width: 100%;
  }

  .backlog-filter-field {
    flex: 1 1 40%;
  }

  .backlog-filter-field select,
  .backlog-search-input,
  .backlog-free-toggle,
  .backlog-sort-option span,
  .backlog-tab-link,
  .backlog-bulk-btn {
    width: 100%;
    min-height: 44px;
  }

  .backlog-sort,
  .backlog-tabs {
    display: flex;
    width: 100%;
    margin-left: 0;
  }

  .backlog-sort-option,
  .backlog-tab-link {
    flex: 1 1 auto;
  }

  .backlog-item-row {
    grid-template-columns: 88px minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    gap: var(--space-1) var(--space-3);
    contain-intrinsic-size: auto 104px;
  }

  .backlog-row-image {
    grid-row: 1 / span 2;
    width: 88px;
  }

  .backlog-row-info {
    grid-row: 1 / span 2;
  }

  .backlog-row-score {
    grid-column: 3;
    justify-self: end;
  }

  .backlog-row-actions {
    grid-column: 3;
    grid-row: 2;
  }

  .backlog-row-action {
    width: 44px;
    height: 44px;
    opacity: 1;
  }

  .backlog-row-check {
    width: 44px;
    height: 44px;
  }
}

/* ==========================================================================
   Backlog list signatures. CSS only, and every animation stops under reduced motion.
   ========================================================================== */

/* Goshboard OS: a shelf-edge gradient under each row and a holographic sweep over the capsule. */
:root:not([data-theme="beige"]):not([data-theme="hacker"]) .backlog-item-row {
  border-bottom-color: transparent;
  border-image: linear-gradient(90deg, transparent, rgb(var(--accent-rgb) / .5), transparent) 1;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .backlog-item-row:is(:hover, :focus-within) .backlog-row-image::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 30%, rgb(var(--accent-rgb) / .35) 50%, transparent 70%) 100% 0 / 250% 100% no-repeat;
  animation: backlog-holo-sweep .8s ease-out both;
}

@keyframes backlog-holo-sweep {
  to { background-position: 0 0; }
}

/* Retro Desk: index cards with a red margin line, divider tabs, and a rubber stamp on rows filed
   away. Soft shadows only. The ruling sits under the written lines (title and details), never across
   the image, score or buttons: a full-card stripe pattern struck through the text. */
:root[data-theme="beige"] .backlog-item-row {
  margin-bottom: var(--space-2);
  padding-inline: var(--space-3);
  background: var(--surface-row);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--index-margin);
}

:root[data-theme="beige"] .backlog-item-row :is(.backlog-row-title, .backlog-row-details) {
  padding-bottom: 2px;
  border-bottom: 1px solid rgb(var(--accent-rgb) / .22);
}

:root[data-theme="beige"] .backlog-tabs {
  display: flex;
  padding: 0;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border-subtle);
}

:root[data-theme="beige"] .backlog-tab-link {
  margin-bottom: -1px;
  background: var(--surface-page);
  border: 1px solid var(--border-subtle);
  border-bottom: 0;
}

:root[data-theme="beige"] .backlog-tab-link[aria-current] {
  color: var(--text-primary);
  background: var(--surface-card);
}

:root[data-theme="beige"] .backlog-item-row:is(.is-hidden, .is-snoozed)::after {
  position: absolute;
  top: 50%;
  /* Left of the score and action columns. */
  right: calc(var(--space-3) + 84px + 44px + 2 * var(--space-3) + var(--space-2));
  z-index: 1;
  padding: 0 .35rem;
  font-family: var(--font-display);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .1em;
  color: var(--stamp-red);
  border: 1.5px solid currentColor;
  rotate: -6deg;
  translate: 0 -50%;
  pointer-events: none;
}

:root[data-theme="beige"] .backlog-item-row.is-hidden::after {
  content: "FILED";
}

:root[data-theme="beige"] .backlog-item-row.is-snoozed::after {
  content: "LATER";
  color: var(--stamp-green);
}

/* Netrunner: an ls -la listing. Permission bits instead of capsules, an inverted cursor bar on the
   row under the pointer or focus, and the command line above with the current sort. */
:root[data-theme="hacker"] .backlog-prompt {
  display: block;
  margin: 0 0 var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

:root[data-theme="hacker"] .backlog-item-row {
  grid-template-columns: 10ch minmax(0, 1fr) 44px 84px;
  min-height: 0;
  padding: 2px var(--space-2);
  font-family: var(--font-mono);
  border-bottom: 0;
  contain-intrinsic-size: auto 44px;
}

:root[data-theme="hacker"] .backlog-row-image {
  display: none;
}

:root[data-theme="hacker"] .backlog-row-perms {
  display: block;
  grid-column: 1;
  grid-row: 1;
  color: var(--text-secondary);
}

:root[data-theme="hacker"] .backlog-row-perms::before {
  content: "-rw-r--r--";
}

:root[data-theme="hacker"] .is-snoozed .backlog-row-perms::before {
  content: "-r--r--r--";
}

:root[data-theme="hacker"] .is-hidden .backlog-row-perms::before {
  content: "----------";
}

:root[data-theme="hacker"] .backlog-row-info {
  display: flex;
  align-items: baseline;
  gap: 2ch;
}

:root[data-theme="hacker"] .backlog-row-details {
  flex-shrink: 1;
  margin: 0;
}

:root[data-theme="hacker"] .backlog-row-score {
  height: 24px;
  border: 1px solid currentColor;
  box-shadow: none;
}

:root[data-theme="hacker"] .backlog-item-row:is(:hover, :focus-within) {
  background: var(--accent);
}

:root[data-theme="hacker"] .backlog-item-row:is(:hover, :focus-within) :is(.backlog-row-title, .backlog-row-details, .backlog-row-perms, .backlog-row-score) {
  color: var(--on-accent);
}

:root[data-theme="hacker"] .backlog-item-row:is(:hover, :focus-within) .backlog-row-action {
  color: var(--on-accent);
  background: transparent;
  border-color: var(--on-accent);
}

:root[data-theme="hacker"] .backlog-item-row:is(:hover, :focus-within) .backlog-row-title::after {
  content: "_";
  animation: backlog-cursor 1s steps(1) infinite;
}

/* The phosphor focus ring would vanish on the green bar. */
:root[data-theme="hacker"] .backlog-item-row:is(:hover, :focus-within) :focus-visible,
:root[data-theme="hacker"] .backlog-item-row:has(.backlog-row-link:focus-visible) {
  outline-color: var(--on-accent);
}

@keyframes backlog-cursor {
  50% { opacity: 0; }
}

@media (max-width: 767px) {
  :root[data-theme="hacker"] .backlog-item-row {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  :root[data-theme="hacker"] .backlog-row-perms {
    display: none;
  }

  :root[data-theme="hacker"] .backlog-row-info {
    grid-column: 1;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  :root[data-theme="hacker"] .backlog-row-score,
  :root[data-theme="hacker"] .backlog-row-actions {
    grid-column: 2;
  }

  :root[data-theme="beige"] .backlog-item-row:is(.is-hidden, .is-snoozed)::after {
    /* Stamped on the thumbnail, clear of the score and the buttons. */
    top: auto;
    right: auto;
    bottom: var(--space-2);
    left: var(--space-2);
    translate: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .backlog-item-row .backlog-row-image::after,
  .backlog-item-row .backlog-row-title::after {
    animation: none !important;
  }

  .backlog-item-row,
  .backlog-row-action,
  .backlog-sort-option span,
  .backlog-tab-link {
    transition: none;
  }
}

/* The Pile of Shame card on the Playtime page. Its padding comes from the stat tile. */
.backlog-summary-card-wide {
  grid-column: 1 / -1;
  cursor: pointer;
  transition: all 0.2s;
}

/* Both panels sit in one grid cell, so the card is as tall as the taller one in every state and
   nothing below it moves when it unlocks. The hidden panel is only see-through: the pile-card
   controller makes it inert, which keeps it out of the tab order and the accessibility tree. */
.pile-stage {
  display: grid;
  grid-template: "pile" auto / minmax(0, 1fr);
  align-items: center;
  width: 100%;
}

.combined-locked,
.combined-unlocked {
  grid-area: pile;
}

.combined-unlocked { opacity: 0; width: 100%; }

.icon-unlocked { display: none; transform: rotate(-45deg); width: 24px; height: 24px; fill: currentColor; }

.icon-locked { transform: rotate(-45deg); width: 24px; height: 24px; fill: currentColor; }

/* --------------------------------------------------------------------------
   Pile of Shame lock. Each theme has its own locked look and unlock sequence.
   The pile-card controller adds .pile-unlocking for the sequence and waits for the
   stage's pile-unlock-clock animation to end, so that animation sets its length.
   Everything decorative is aria-hidden in the view.
   -------------------------------------------------------------------------- */
.pile-lock {
  position: relative;
  display: grid;
  grid-template-areas: "art" "word" "hint";
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) 0;
  overflow: hidden;
}

.pile-lock-art {
  grid-area: art;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  color: var(--accent);
  perspective: 120px;
}

.pile-lock-shackle {
  width: 22px;
  height: 16px;
  margin-bottom: -3px;
  border: 3px solid currentColor;
  border-bottom: 0;
  border-radius: 11px 11px 0 0;
  transform-origin: calc(100% - 1.5px) 100%;
}

/* The body of the padlock, with a keyhole. */
.pile-lock-body {
  width: 34px;
  height: 26px;
  border: 2px solid currentColor;
  border-radius: 5px;
  background:
    radial-gradient(circle at 50% 38%, currentColor 0 3px, transparent 3.5px),
    linear-gradient(currentColor, currentColor) 50% 72% / 2px 8px no-repeat,
    rgb(var(--accent-rgb) / .12);
}

.pile-lock-sheet,
.pile-lock-clip,
.pile-cipher,
.pile-crack {
  display: none;
}

.pile-lock-word,
.pile-cipher {
  grid-area: word;
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 700;
  letter-spacing: .12em;
  line-height: var(--leading-tight);
  white-space: nowrap;
  color: var(--danger);
}

.pile-lock-hint {
  grid-area: hint;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  letter-spacing: .12em;
  color: var(--text-secondary);
}

/* The themed words come from flavour_text, whose own small-label look must not apply here. */
.pile-lock-word > *,
.pile-lock-hint > * {
  display: inline;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
}

/* The stage's clock: when it ends, the controller shows the count. */
.pile-unlocking .pile-stage {
  animation: pile-unlock-clock 2s linear;
}

@keyframes pile-unlock-clock {
  to { opacity: 1; }
}

/* Goshboard OS: a flickering holographic padlock, a chromatic glitch on the word, a slow scan sweep.
   Unlocking decrypts the word, swings the shackle open and hands over in a glitch burst. */
:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-lock::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 35%;
  border-bottom: 1px solid rgb(var(--accent-rgb) / .45);
  background: linear-gradient(to bottom, transparent, rgb(var(--accent-rgb) / .14));
  transform: translateY(-100%);
  animation: pile-sweep 4s cubic-bezier(.45, 0, .55, 1) infinite;
  pointer-events: none;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-lock-art {
  filter: drop-shadow(0 0 6px rgb(var(--accent-rgb) / .7));
  animation: pile-holo 5s linear infinite;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-lock-word {
  animation: pile-chroma 3s linear infinite;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-lock-hint {
  color: var(--accent);
  animation: pile-holo 5s linear 1.3s infinite;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-unlocking .pile-lock-word {
  visibility: hidden;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-unlocking .pile-cipher {
  display: block;
  color: var(--accent);
  animation: pile-chroma .4s linear infinite;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-unlocking .pile-lock-body {
  animation: pile-rattle .12s linear 8;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-unlocking .pile-lock-shackle {
  animation: pile-shackle-open .45s cubic-bezier(.3, 1.4, .5, 1) 1s both;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-unlocking .pile-lock-art {
  animation: pile-art-open .3s ease-out 1s both;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .pile-unlocking .pile-lock {
  animation: pile-burst .6s linear 1.4s both;
}

@keyframes pile-sweep {
  0% { transform: translateY(-100%); }
  70%, 100% { transform: translateY(300%); }
}

@keyframes pile-holo {
  0%, 46%, 50%, 54%, 100% { opacity: 1; }
  48% { opacity: .55; }
  52% { opacity: .8; }
}

@keyframes pile-chroma {
  0%, 82%, 100% {
    text-shadow: -1px 0 rgb(var(--accent-rgb) / .6), 1px 0 color-mix(in srgb, var(--chart-2) 70%, transparent);
    transform: none;
    clip-path: none;
  }
  84% {
    text-shadow: -5px 0 rgb(var(--accent-rgb) / .85), 4px 0 color-mix(in srgb, var(--chart-2) 85%, transparent);
    transform: translateX(3px) skewX(-12deg);
    clip-path: inset(10% 0 45% 0);
  }
  87% {
    text-shadow: 4px 0 rgb(var(--accent-rgb) / .85), -5px 0 color-mix(in srgb, var(--chart-2) 85%, transparent);
    transform: translateX(-4px) skewX(10deg);
    clip-path: inset(50% 0 5% 0);
  }
  90% {
    text-shadow: -3px 0 rgb(var(--accent-rgb) / .7), 3px 0 color-mix(in srgb, var(--chart-2) 70%, transparent);
    transform: translateX(2px);
    clip-path: inset(0 0 65% 0);
  }
  93% {
    text-shadow: -2px 0 rgb(var(--accent-rgb) / .6), 2px 0 color-mix(in srgb, var(--chart-2) 70%, transparent);
    transform: none;
    clip-path: none;
  }
}

@keyframes pile-rattle {
  25% { transform: translateX(-1.5px) rotate(-3deg); }
  75% { transform: translateX(1.5px) rotate(3deg); }
}

@keyframes pile-shackle-open {
  45% { transform: translateY(-7px); }
  to { transform: translateY(-7px) rotateY(180deg); }
}

@keyframes pile-art-open {
  to { color: var(--success); }
}

@keyframes pile-burst {
  0%, 48% { clip-path: none; transform: none; filter: none; opacity: 1; }
  12% { clip-path: inset(20% 0 50% 0); transform: translateX(-8px); filter: hue-rotate(90deg) brightness(1.5); }
  24% { clip-path: inset(60% 0 10% 0); transform: translateX(10px); }
  36% { clip-path: inset(0 0 72% 0); transform: translateX(-4px); filter: hue-rotate(-60deg); }
  60% { clip-path: inset(35% 0 30% 0); transform: translateX(6px); filter: hue-rotate(140deg) brightness(1.8); }
  72% { clip-path: none; transform: none; filter: brightness(2); opacity: 1; }
  100% { clip-path: none; transform: scaleY(.03); filter: brightness(3); opacity: 0; }
}

/* Retro Desk: a sealed manila case file with a paper clip and a red CONFIDENTIAL stamp, and a typed note.
   Unlocking strikes the stamp out and lifts it, opens the cover and slides the sheet out. Flat paper, no deep shadows. */
:root[data-theme="beige"] .pile-unlocking .pile-stage {
  animation-duration: 2.4s;
}

:root[data-theme="beige"] .pile-lock {
  grid-template-areas: "art" "hint";
  gap: var(--space-3);
  padding-top: var(--space-4);
  overflow: visible;
}

:root[data-theme="beige"] .pile-lock-art {
  display: block;
  width: 156px;
  height: 92px;
  background: var(--folder-back);
  border: 1px solid var(--folder-edge);
  perspective: 500px;
}

/* The folder tab. */
:root[data-theme="beige"] .pile-lock-art::before {
  content: "";
  position: absolute;
  bottom: 100%;
  left: 12px;
  width: 54px;
  height: 10px;
  background: var(--folder-back);
  border: 1px solid var(--folder-edge);
  border-bottom: 0;
  border-radius: 3px 3px 0 0;
}

:root[data-theme="beige"] .pile-lock-sheet {
  display: block;
  position: absolute;
  top: 6px;
  left: 14px;
  right: 14px;
  height: 78px;
  background:
    repeating-linear-gradient(to bottom, transparent 0 9px, var(--folder-rule) 9px 10px) 10px 14px / calc(100% - 20px) 50px no-repeat,
    var(--surface-raised);
  border: 1px solid var(--folder-edge);
}

/* The front cover, hinged on its left edge, with a blank label. */
:root[data-theme="beige"] .pile-lock-body {
  position: absolute;
  inset: 16px -1px -1px;
  width: auto;
  height: auto;
  border: 1px solid var(--folder-edge);
  border-radius: 0;
  background:
    linear-gradient(var(--surface-raised), var(--surface-raised)) 12px 10px / 62px 12px no-repeat,
    var(--folder-front);
  transform-origin: left center;
  backface-visibility: hidden;
}

/* A metal paper clip over the top edge, tilted a little, right of the tab and clear of the stamp:
   a grey wire with a light edge along its upper side, and a soft shadow on the folder. */
:root[data-theme="beige"] .pile-lock-shackle {
  display: none;
}

:root[data-theme="beige"] .pile-lock-clip {
  display: block;
  position: absolute;
  top: -17px;
  right: 22px;
  z-index: 2;
  width: 15px;
  height: 42px;
  overflow: visible;
  filter: drop-shadow(1px 1px 0 var(--clip-shade));
  rotate: 9deg;
}

:root[data-theme="beige"] .pile-lock-clip-wire {
  stroke: var(--clip-metal);
  stroke-width: 1.7;
}

:root[data-theme="beige"] .pile-lock-clip-shine {
  stroke: var(--clip-shine);
  stroke-width: .6;
  opacity: .85;
  translate: -.45px -.45px;
}

/* The stamp sits on the cover. */
:root[data-theme="beige"] .pile-lock-word {
  grid-area: art;
  align-self: center;
  position: relative;
  z-index: 3;
  margin-top: 16px;
  padding: 3px 8px;
  font-size: .8rem;
  letter-spacing: .12em;
  border: 3px double var(--danger);
  opacity: .9;
  mix-blend-mode: multiply;
  transform: rotate(-8deg);
  animation: pile-stamp-down .3s cubic-bezier(.2, 1.6, .4, 1) .4s both;
}

/* The strike-out line, drawn when the case opens. */
:root[data-theme="beige"] .pile-lock-word::after {
  content: "";
  position: absolute;
  inset: 50% -4px auto;
  border-top: 2px solid var(--danger);
  transform: scaleX(0);
  transform-origin: left;
}

/* Typed out once, one step per character of the hint (the pile lock test checks it), then the caret blinks. */
:root[data-theme="beige"] .pile-lock-hint {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  letter-spacing: 0;
  color: var(--text-primary);
}

:root[data-theme="beige"] .pile-lock-hint > * {
  display: inline-block;
  width: 32ch;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
  animation: pile-typewriter 1.6s steps(32) .8s both;
}

:root[data-theme="beige"] .pile-lock-hint::after {
  content: "|";
  content: "|" / "";
  animation: pile-caret 1s step-end infinite;
}

:root[data-theme="beige"] .pile-unlocking .pile-lock-word {
  animation: pile-stamp-lift .4s ease-in .6s both;
}

:root[data-theme="beige"] .pile-unlocking .pile-lock-word::after {
  animation: pile-strike .3s ease-out .1s both;
}

:root[data-theme="beige"] .pile-unlocking .pile-lock-clip {
  animation: pile-clip-off .5s ease-in .6s both;
}

:root[data-theme="beige"] .pile-unlocking .pile-lock-body {
  animation: pile-cover-open .55s ease-in-out 1s both;
}

:root[data-theme="beige"] .pile-unlocking .pile-lock-sheet {
  animation: pile-sheet-out .6s cubic-bezier(.3, .7, .4, 1) 1.5s both;
}

:root[data-theme="beige"] .pile-unlocking .pile-lock {
  animation: pile-fade-out .3s ease-in 2.1s both;
}

@keyframes pile-stamp-down {
  from { opacity: 0; transform: rotate(-8deg) scale(2); }
}

@keyframes pile-strike {
  to { transform: scaleX(1); }
}

@keyframes pile-stamp-lift {
  to { opacity: 0; transform: translateY(-18px) rotate(-14deg) scale(1.08); }
}

/* The clip slides up off the edge, then drops away past the folder's right side, clear of the stamp. */
@keyframes pile-clip-off {
  30% { translate: 0 -10px; rotate: 4deg; }
  60% { opacity: 1; }
  to { opacity: 0; translate: 44px 56px; rotate: 80deg; }
}

@keyframes pile-cover-open {
  to { transform: rotateY(-180deg); }
}

@keyframes pile-sheet-out {
  to { transform: translateY(-30px) rotate(-2deg); }
}

@keyframes pile-fade-out {
  to { opacity: 0; transform: translateY(-6px); }
}

@keyframes pile-typewriter {
  from { width: 0; }
}

/* Netrunner: a terminal panel with ACCESS DENIED, a blinking prompt and the counter's scanlines.
   Unlocking types out a password crack with a progress bar, then ACCESS GRANTED. */
:root[data-theme="hacker"] .pile-unlocking .pile-stage {
  animation-duration: 2.4s;
}

:root[data-theme="hacker"] .pile-lock {
  grid-template-areas: "title" "word" "hint";
  justify-items: start;
  max-width: 30rem;
  margin-inline: auto;
  padding: 0 var(--space-3) var(--space-3);
  font-family: var(--font-mono);
  text-align: left;
  background: var(--surface-sunken);
  border: 1px solid var(--border-subtle);
}

:root[data-theme="hacker"] .pile-lock::before {
  content: "root@goshboard:~/backlog";
  content: "root@goshboard:~/backlog" / "";
  grid-area: title;
  justify-self: stretch;
  margin-inline: calc(-1 * var(--space-3));
  padding: 2px var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-faint);
  border-bottom: 1px solid var(--border-subtle);
}

:root[data-theme="hacker"] .pile-lock::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(to bottom, rgb(0 0 0 / .35) 0 1px, transparent 1px 3px);
  animation: pile-scan 10s linear infinite;
  pointer-events: none;
}

:root[data-theme="hacker"] .pile-lock-art {
  display: none;
}

:root[data-theme="hacker"] .pile-lock-word {
  font-family: var(--font-mono);
  font-size: var(--text-xl);
  letter-spacing: .08em;
  text-shadow: 0 0 8px rgb(var(--danger-rgb) / .6);
  animation: pile-denied 3s steps(1) infinite;
}

:root[data-theme="hacker"] .pile-lock-hint {
  font-family: var(--font-mono);
  letter-spacing: 0;
  color: var(--text-primary);
}

:root[data-theme="hacker"] .pile-lock-hint::before {
  content: "> ";
  content: "> " / "";
}

:root[data-theme="hacker"] .pile-lock-hint::after {
  content: "\2588";
  content: "\2588" / "";
  margin-left: 2px;
  animation: pile-caret 1s step-end infinite;
}

:root[data-theme="hacker"] .pile-unlocking .pile-lock-word,
:root[data-theme="hacker"] .pile-unlocking .pile-lock-hint {
  visibility: hidden;
}

/* The crack takes the rows of the word and the hint, so the panel keeps its height. */
:root[data-theme="hacker"] .pile-unlocking .pile-crack {
  display: grid;
  grid-row: 2 / 4;
  grid-column: 1;
  align-content: start;
  font-size: var(--text-xs);
  line-height: 1.3;
  color: var(--text-primary);
}

/* The crack only displays in Netrunner, so its lines need no theme prefix. Each steps() count
   matches the characters of its line (the pile lock test checks it). */
.pile-crack-line {
  white-space: nowrap;
}

.pile-crack-cmd {
  animation: pile-type .5s steps(29) .1s both;
}

.pile-crack-bar {
  animation: pile-appear .7s both;
}

.pile-crack-fill {
  display: inline-block;
  animation: pile-type .9s steps(10) .7s both;
}

/* The percentage counts up beside the bar. */
.pile-crack-bar::after {
  content: " " counter(pile-pct) "%";
  counter-reset: pile-pct var(--pile-pct);
  animation: pile-pct .9s steps(10) .7s both;
}

.pile-crack-granted {
  font-weight: 700;
  color: var(--success);
  text-shadow: 0 0 8px rgb(var(--accent-rgb) / .7);
  animation: pile-appear 1.7s both, pile-blink-in .6s linear 1.7s both;
}

@property --pile-pct {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}

@keyframes pile-pct {
  to { --pile-pct: 100; }
}

/* Hidden until the animation ends: pair it with a delay-free duration as long as the wait. */
@keyframes pile-appear {
  from, 99% { visibility: hidden; }
}

@keyframes pile-blink-in {
  45%, 65% { opacity: 0; }
}

@keyframes pile-denied {
  0%, 78%, 86%, 100% { color: var(--danger); background: none; }
  80%, 84% { color: var(--surface-page); background: var(--danger); }
}

/* Every lock effect has a still state. The controller skips the sequence for reduced motion. */
@media (prefers-reduced-motion: reduce) {
  .pile-lock,
  .pile-lock::before,
  .pile-lock::after,
  .pile-lock *,
  .pile-lock *::before,
  .pile-lock *::after {
    animation: none !important;
  }
}

.backlog-divider {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--surface-chip);
  transform: translateX(-50%);
  z-index: 1;
}

.backlog-content-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 0;
  position: relative;
  z-index: 2;
}

.backlog-stats-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: relative;
  isolation: isolate;
  padding-right: 1.5rem;
  text-decoration: none;
  color: inherit;
}

.backlog-stats-col.interactive {
  cursor: pointer;
  transition: background 0.2s;
  border-radius: 8px;
  padding: 0.5rem;
}

.backlog-stats-col.interactive:hover {
  background: var(--surface-chip);
}

.backlog-count {
  position: relative;
  color: var(--success);
  text-shadow: 0 0 10px color-mix(in srgb, var(--success) 40%, transparent);
  text-align: center;
}

/* Pile of Shame: one effect per theme. Decoration sits behind the text or is faint, so the
   token contrast holds, and every effect has a still end state for reduced motion. */

/* Goshboard OS: a slow holographic sheen passes behind the count now and then. */
:root:not([data-theme="beige"]):not([data-theme="hacker"]) .backlog-stats-col {
  overflow: hidden;
}

:root:not([data-theme="beige"]):not([data-theme="hacker"]) .backlog-stats-col::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(105deg, transparent 35%, rgb(var(--accent-rgb) / .16) 45%,
    rgb(255 255 255 / .10) 50%, rgb(var(--accent-rgb) / .16) 55%, transparent 65%);
  background-size: 300% 100%;
  background-position: 100% 0;
  animation: pile-sheen 7s ease-in-out .4s infinite;
  pointer-events: none;
}

@keyframes pile-sheen {
  0% { background-position: 100% 0; }
  40%, 100% { background-position: 0 0; }
}

/* Retro Desk: the count sits on the top sheet of a paper stack, with a rubber stamp on it.
   Both sheets are pseudo-elements, because negative z-index children paint over the column's own background. */
:root[data-theme="beige"] .backlog-stats-col {
  margin: var(--space-2) var(--space-4) var(--space-3) var(--space-2);
  padding: var(--space-2) var(--space-6);
  transition: transform var(--dur-fast) ease-out;
}

:root[data-theme="beige"] .backlog-stats-col::before,
:root[data-theme="beige"] .backlog-stats-col::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px solid var(--border-strong);
  transition: transform var(--dur-fast) ease-out;
  pointer-events: none;
}

:root[data-theme="beige"] .backlog-stats-col::before {
  z-index: -1;
  background: var(--surface-raised);
}

:root[data-theme="beige"] .backlog-stats-col::after {
  z-index: -2;
  background: var(--surface-sunken);
  transform: translate(6px, 6px) rotate(1.5deg);
}

/* The top sheet lifts off the pile, and the sheet below stays put and fans out a little. */
:root[data-theme="beige"] .backlog-stats-col.interactive:hover {
  background: none;
  transform: translateY(-3px);
}

:root[data-theme="beige"] .backlog-stats-col.interactive:hover::after {
  transform: translate(7px, 9px) rotate(2.5deg);
}

:root[data-theme="beige"] .backlog-count::after {
  content: "SHAME";
  content: "SHAME" / "";
  position: absolute;
  top: 50%;
  left: calc(100% + var(--space-3));
  padding: 2px 6px;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .15em;
  line-height: 1;
  color: var(--danger);
  border: 3px double var(--danger);
  opacity: .85;
  mix-blend-mode: multiply;
  transform: translateY(-20%) rotate(-14deg);
  animation: pile-stamp .3s cubic-bezier(.2, 1.6, .4, 1) .35s both;
}

@keyframes pile-stamp {
  from { opacity: 0; transform: translateY(-20%) rotate(-14deg) scale(2.2); }
}

/* Netrunner: scanlines over the block, a counter typed out with a caret, a rare flicker. */
:root[data-theme="hacker"] .backlog-stats-col {
  overflow: hidden;
}

:root[data-theme="hacker"] .backlog-stats-col::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(to bottom, rgb(0 0 0 / .35) 0 1px, transparent 1px 3px);
  animation: pile-scan 10s linear infinite;
  pointer-events: none;
}

:root[data-theme="hacker"] .backlog-count {
  animation: pile-type .8s steps(var(--type-steps, 4), end) .2s both, pile-flicker 9s 2s infinite;
}

:root[data-theme="hacker"] .backlog-count::after {
  content: "_";
  content: "_" / "";
  animation: pile-caret 1s step-end infinite;
}

.backlog-count[data-digits="1"] { --type-steps: 2; }
.backlog-count[data-digits="2"] { --type-steps: 3; }
.backlog-count[data-digits="3"] { --type-steps: 4; }
.backlog-count[data-digits="4"] { --type-steps: 5; }
.backlog-count[data-digits="5"] { --type-steps: 6; }

@keyframes pile-type {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}

@keyframes pile-flicker {
  0%, 93%, 95%, 97%, 100% { opacity: 1; }
  94% { opacity: .75; }
  96% { opacity: .85; }
}

@keyframes pile-caret {
  50% { opacity: 0; }
}

@keyframes pile-scan {
  to { background-position: 0 30px; }
}

/* !important beats the theme rules above, whose :root[data-theme] prefix outranks these selectors. */
@media (prefers-reduced-motion: reduce) {
  .backlog-stats-col::before,
  .backlog-stats-col::after,
  .backlog-count,
  .backlog-count::after {
    animation: none !important;
  }
}

.backlog-roll-col {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  padding-left: 1.5rem;
}

/* Pile card: the lock is a real button */
.pile-unlock {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: 0;
  color: inherit;
  font: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

.pile-result-open {
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--accent);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  background: none;
  border: none;
  cursor: pointer;
}

.backlog-roll-col {
  position: relative;
  flex-direction: column;
  width: 100%;
  min-width: 150px;
}

/* Before .btn-reroll, whose smaller size must win. */
.btn-random-roll {
  white-space: normal;
  line-height: 1.4;
  text-align: center;
  font-size: 0.85rem;
  padding: 0.5rem 1rem;
}

:root[data-theme="beige"] .btn-random-roll {
  background-color: var(--surface-page);
  border: 3px outset;
  border-color: var(--bevel-light) var(--bevel-dark) var(--bevel-dark) var(--bevel-light);
  color: var(--surface-header);
  clip-path: none;
}

:root[data-theme="beige"] .btn-random-roll:active {
  border-style: inset;
  border-color: var(--bevel-dark) var(--bevel-light) var(--bevel-light) var(--bevel-dark);
}

:root[data-theme="hacker"] .btn-random-roll {
  background-color: var(--surface-page);
  border: 1px solid var(--accent);
  color: var(--accent);
  clip-path: none;
  box-shadow: var(--shadow-card);
}

.randomizer-banner {
  width: 100%;
  max-height: 70px;
  margin-bottom: var(--space-2);
  object-fit: cover;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
}

.btn-reroll {
  width: 100%;
  min-height: 24px;
  margin-top: var(--space-2);
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-xs);
}

.btn-roll-icon {
  display: block;
  margin: 0 auto 5px;
}

@media (max-width: 767px) {
  .backlog-content-grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }

  .backlog-divider {
    display: none;
  }

  .backlog-stats-col,
  .backlog-roll-col {
    padding: 0;
  }
}

/* Locks the Pile of Shame again. Small and explicit, under the unlocked content. */
.pile-relock {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  inline-size: fit-content;
  min-block-size: 32px;
  margin: var(--space-3) 0 0 auto;
  padding: 0 var(--space-3);
  font: inherit;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-secondary);
  background: var(--surface-chip);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.pile-relock:hover {
  color: var(--accent);
  border-color: var(--accent);
}
