/* =============================================================================
   collection.css - Collection grid, filters and detail modal.

   Reference: `.docs/steps/5.md` point 2. Missing cards are grey silhouettes
   (`grayscale + opacity` on the tile, never a `filter` on a 3D flip context).
   Colors come exclusively from `css/themes.css`.
   ============================================================================= */

.collection__filters {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.collection__field--search {
  grid-column: 1 / -1;
}

.field__input {
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
  color: var(--color-text);
  font: inherit;
  touch-action: manipulation;
}

.field__input:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.collection__count {
  grid-column: 1 / -1;
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* The bar of the filter panel: the button that opens the popup, the small badge of the active
   filter count and the line that names it. It spans every column, like the search does. */
.collection__toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  grid-column: 1 / -1;
}

.collection__filter-open {
  gap: var(--space-2);
}

.collection__filter-badge {
  display: inline-grid;
  place-items: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 var(--space-1);
  border-radius: var(--radius-pill);
  background-color: var(--color-accent);
  color: var(--color-accent-contrast);
  font-size: var(--font-size-xs);
  font-weight: 700;
}

/* `hidden` alone is not enough on an element that has a `display` of its own. */
.collection__filter-badge[hidden] {
  display: none;
}

.collection__summary {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* The binders button of the view header: the same icon as the header counter, at the size of the
   text next to it (it names the door, it does not count what is behind it). */
.collection__binders-open {
  flex: 0 0 auto;
  white-space: nowrap;
}

.collection__binders-icon {
  width: 1.1rem;
  height: 1.1rem;
  object-fit: contain;
}

.collection__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-3);
  margin-top: var(--space-4);
}

/* Grid item: wraps the tile and the favourite heart. The heart cannot live INSIDE the tile, which
   is itself a `<button>` (nested buttons are invalid HTML): it is overlaid as a sibling. */
.collection__cell {
  position: relative;
  display: flex;
  min-width: 0;
}

.collection__cell .collection__tile {
  flex: 1 1 auto;
  min-width: 0;
}

.collection__favorite {
  position: absolute;
  top: var(--space-1);
  left: var(--space-1);
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background-color: var(--color-surface-alt);
  color: var(--color-text-muted);
  cursor: pointer;
  touch-action: manipulation;
  transition: color var(--duration-fast) var(--easing-standard),
    background-color var(--duration-fast) var(--easing-standard),
    border-color var(--duration-fast) var(--easing-standard);
}

.collection__favorite svg,
.collection-favorite__toggle svg {
  width: 1rem;
  height: 1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

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

.collection__favorite:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* A pinned card is filled, so the state reads at a glance on a dense grid. */
.collection__favorite.is-active {
  border-color: var(--color-accent);
  background-color: var(--color-accent);
  color: var(--color-accent-contrast);
}

.collection__favorite.is-active svg,
.collection-favorite__toggle.is-active svg {
  fill: currentColor;
}

.collection__tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  touch-action: manipulation;
  animation: collection-pop var(--duration-base) var(--easing-standard backwards);
}

.collection__tile:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.collection__tile.is-missing {
  filter: grayscale(100%);
  opacity: 0.4;
}

.collection__image {
  width: 100%;
  aspect-ratio: var(--card-ratio);
  object-fit: contain;
  border-radius: var(--radius-sm);
  background-color: var(--color-surface-alt);
}

.collection__caption {
  font-size: var(--font-size-xs);
  text-align: center;
  color: var(--color-text-muted);
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.collection__badge {
  position: absolute;
  top: var(--space-1);
  right: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  background-color: var(--color-accent);
  color: var(--color-accent-contrast);
  font-size: var(--font-size-xs);
  font-weight: 700;
}

/* Promo chip: mirrors the quantity badge, on the opposite corner, in the "promo" tone. Same pill
   shape and weight, so a promo card reads as one more kind of card, not as a warning. */
.collection__promo {
  position: absolute;
  top: var(--space-1);
  left: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-pill);
  background-color: var(--color-promo);
  color: var(--color-accent-contrast);
  font-size: var(--font-size-xs);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* The artwork box is the window of the foil reflection (`css/components/card-shine.css`): it takes
   the exact shape of the card, so the highlight lines up with the illustration instead of the
   modal. The height is capped in viewport units, the width follows the ratio. */
.collection-modal__art {
  position: relative;
  height: min(46vh, 32rem);
  aspect-ratio: var(--card-reveal-art-ratio, var(--card-ratio));
  width: auto;
  margin-inline: auto;
}

.collection-modal__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
}

/* --- Developer block (detail modal) -------------------------------------- */

/* Only exists while "Mode développeur" is on (settings). It shows the exact key of the open card -
   the one the `collection` store is keyed on - and a button copying it, so an operator never has
   to guess it from the illustration file name. The key wraps instead of overflowing: it is long by
   nature ("SERIE-A1 _ W001_classic") and the dialog is 32rem wide at most. */
.collection-dev {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
}

.collection-dev__key {
  flex: 1 1 12rem;
  min-width: 0;
  overflow-wrap: anywhere;
  font-family: ui-monospace, 'Cascadia Code', Menlo, Consolas, monospace;
  font-size: var(--font-size-xs);
  color: var(--color-text);
}

.collection-dev__copy {
  flex: 0 0 auto;
}

/* Promo card: the trade block is replaced by the reason there is none. Purple, the tone of every
   promo mark (`--color-promo`, same as the chip on the tile), so the two read as one thing. */
.collection-trade__locked {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-promo);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
  color: var(--color-text);
  font-size: var(--font-size-sm);
}

@keyframes collection-pop {
  from {
    opacity: 0;
    transform: translateY(10px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (min-width: 768px) {
  .collection__filters {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .collection__field--search {
    grid-column: auto;
  }

  .collection__count {
    grid-column: 1 / -1;
  }

  .collection__grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* --- Favourite toggle (detail modal) ------------------------------------- */

.collection-favorite {
  display: flex;
  margin-top: var(--space-3);
}

.collection-favorite__toggle {
  flex: 1 1 auto;
}

.collection-favorite__toggle.is-active {
  border-color: var(--color-accent);
  color: var(--color-accent);
}

/* --- Sparks trade block (detail modal) ----------------------------------- */

.collection-trade {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

.collection-trade__wallet {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.collection-trade__icon {
  width: 1.1em;
  height: 1.1em;
  object-fit: contain;
}

.collection-trade__balance {
  font-size: var(--font-size-md);
  color: var(--color-text);
}

.collection-trade__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
}

.collection-trade__actions .btn {
  flex: 1 1 auto;
}

.collection-trade__label {
  white-space: nowrap;
}

/* Sparks delta of a trade button: green when credited (sale), red when charged (purchase). */
.collection-trade__delta {
  font-weight: 700;
  white-space: nowrap;
}

.collection-trade__delta[data-tone="gain"] {
  color: var(--color-success);
}

.collection-trade__delta[data-tone="cost"] {
  color: var(--color-error);
}

.collection-trade__delta-icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  object-fit: contain;
}

/* --- Filter & sort popup -------------------------------------------------- */

/* The popup is one scrolling column of sections: extensions (the long one), then the single-choice
   rows, then the live count. Every section is a title and a row of pills that wrap. */
.collection-filter {
  gap: var(--space-4);
}

.collection-filter__group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.collection-filter__options {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.collection-filter__option {
  min-height: var(--touch-target);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background-color: var(--color-surface-alt);
  color: var(--color-text);
  font: inherit;
  font-size: var(--font-size-sm);
  cursor: pointer;
  touch-action: manipulation;
  transition: border-color var(--duration-fast) var(--easing-standard),
    background-color var(--duration-fast) var(--easing-standard),
    color var(--duration-fast) var(--easing-standard);
}

.collection-filter__option:hover {
  border-color: var(--color-accent);
}

.collection-filter__option:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* An active toggle is FILLED: in a popup full of pills, an outline alone does not read. */
.collection-filter__option.is-active {
  border-color: var(--color-accent);
  background-color: var(--color-accent);
  color: var(--color-accent-contrast);
  font-weight: 700;
}

.collection-filter__count {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

@media (prefers-reduced-motion: reduce) {
  .collection__tile {
    animation: none;
  }
}

/* --- Progression page (`#view-progression`, `js/UI/views/ProgressionView.js`) - */

/* ONE extension at a time: a stack of sets would be a long scroll for a page whose content is two
   numbers per extension. The strip mirrors the one of the settings - it scrolls sideways instead of
   wrapping - and only the selected button is reachable with Tab (roving tabindex). */
.progression__tabs {
  display: flex;
  gap: var(--space-2);
  padding: var(--space-2);
  overflow-x: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
  scrollbar-width: thin;
}

.progression__tab {
  flex: 0 0 auto;
  padding: var(--space-2) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--color-text-muted);
  font: inherit;
  font-size: var(--font-size-sm);
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
}

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

.progression__tab.is-active {
  border-color: var(--color-accent);
  background-color: var(--color-accent);
  color: var(--color-accent-contrast);
}

.progression__tab:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.progression__panels {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* `hidden` needs its own rule: a class selector would otherwise beat the `display: none` the
   attribute carries in the user agent stylesheet. */
.progression__panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.progression__panel[hidden] {
  display: none;
}

.progression__set {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
}

.progression__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.progression__name {
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-text);
}

.progression__code {
  font-size: var(--font-size-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
}

.progression__row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1, 0.25rem);
}

.progression__row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
}

.progression__label {
  font-size: var(--font-size-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* Tabular figures: the two values stay aligned while the bars grow. */
.progression__value {
  font-variant-numeric: tabular-nums;
  font-size: var(--font-size-xs);
  color: var(--color-text);
}

.progression__bar {
  height: 0.5rem;
  overflow: hidden;
  border-radius: var(--radius-pill);
  background-color: var(--color-border);
}

.progression__fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  background-color: var(--color-accent);
  transition: width 220ms ease;
}

/* A finished extension is announced by the bar itself: nothing else is needed to read it. */
.progression__row[data-complete="true"] .progression__value {
  color: var(--color-accent);
  font-weight: 700;
}

@media (prefers-reduced-motion: reduce) {
  .progression__fill {
    transition: none;
  }
}
