/* =============================================================================
   mineblock.css - Mine screen (MineBlock).

   Reference: `js/UI/views/MineBlockView.js` (the screen) and
   `js/business/MiningManager.js` (the blocks, the allowance and the loot).

   What is here, top to bottom:
     `.mineblock__header-actions` the wandering-trader button, pushed to the reading end;
     `.mineblock__rock`           the block of the moment, with the CRACK texture laid over its
                                  picture (`.mineblock__crack`, chosen by the break percentage);
     `.mineblock__burst`          the layer the rewards fly into: one element per unit obtained,
                                  each sent in its own direction, its own distance, its own spin;
     `.mineblock__resources`      the chips of the harvested resources: an icon and a count, nothing
                                  else (the name is in the inventory, and in the accessible text);
     `.mineblock__inventory`      the chest under them: a picture, and the name of the dialog.

   Two rituals on `.mineblock__rock-inner`, so the crack follows its picture, plus the landing of
   the next block - the fourth name is the one the view writes on `.mineblock__rock` itself:
     `.is-hit`      the block flinches under a tap that did not break it (180ms);
     `.is-broken`   it blows up and disappears (240ms: the loot has just been spat out);
     `.is-arriving` the next block drops in (160ms, the pace the view waits for before taking the
                    class back off - the two numbers must stay in step).

   The mining must stay FAST: the view swaps the block after `mining.nextBlockDelayMs` of
   `settings/config.json` (100ms), whatever this file says - the break animation is cut short when
   it is longer, which the fade-in of `.is-arriving` hides.

   Colors come from `css/themes.css`. A player who asked for reduced motion keeps the game
   readable: the flying rewards simply appear and are removed (see the last block of this file).
   ============================================================================= */

.mineblock {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.mineblock__panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: center;
  text-align: center;
}

/* The wandering trader is the one action of the page: it sits at the reading end of the header,
   exactly like the statistics button of the profile. */
.mineblock__header-actions {
  justify-content: flex-end;
}

/* The mob is coloured pixel art, so it is NOT run through `--icon-filter` (which flips the black
   glyphs of the interface): `pixelated` keeps it crisp at any size. */
.mineblock__trader-icon {
  width: 1.5rem;
  height: 1.5rem;
  object-fit: contain;
  image-rendering: pixelated;
}

/* --- The block of the moment --------------------------------------------- */

.mineblock__name {
  font-size: var(--font-size-xl);
  font-weight: 700;
  color: var(--color-text);
}

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

.mineblock__countdown {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--font-size-sm);
  color: var(--color-warning);
}

.mineblock__countdown-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.mineblock__stage {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
}

.mineblock__rock {
  position: relative;
  display: grid;
  place-items: center;
  width: min(62vw, 16rem);
  aspect-ratio: 1 / 1;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  /* A press that moves the mouse must never select the picture nor drag it out of the button. */
  user-select: none;
  -webkit-user-select: none;
}

.mineblock__rock:disabled {
  cursor: default;
}

.mineblock__rock:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 6px;
  border-radius: var(--radius-md);
}

.mineblock__rock-inner {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
}

/* `image-rendering: pixelated` keeps the blocks and their crack as the pixel art they are, at any
   size; the crack is stretched over the very same box, so the two pictures stay aligned. */
.mineblock__texture,
.mineblock__crack {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}

.mineblock__texture {
  filter: drop-shadow(0 6px 16px var(--overlay));
}

/* The two pictures of the block are decoration of a button: WebKit would otherwise let the player
   drag the texture away instead of mining it. */
.mineblock__texture,
.mineblock__crack {
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
}

.mineblock__crack {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* --- The rituals --------------------------------------------------------- */

.mineblock__rock.is-hit .mineblock__rock-inner {
  animation: mineblock-hit 180ms var(--easing-standard);
}

.mineblock__rock.is-broken .mineblock__rock-inner {
  animation: mineblock-break 240ms var(--easing-standard) forwards;
}

.mineblock__rock.is-arriving .mineblock__rock-inner {
  animation: mineblock-arrive 160ms var(--easing-standard);
}

@keyframes mineblock-hit {
  0% {
    transform: none;
  }
  35% {
    transform: translateY(3px) scale(0.975);
  }
  100% {
    transform: none;
  }
}

@keyframes mineblock-break {
  0% {
    transform: none;
    opacity: 1;
  }
  40% {
    transform: scale(1.06);
  }
  100% {
    transform: scale(0.78) rotate(4deg);
    opacity: 0;
  }
}

@keyframes mineblock-arrive {
  from {
    opacity: 0;
    transform: translateY(-16px) scale(0.9);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* --- The loot flying out of the rock ------------------------------------- */

/* The layer covers the block, so a reward is spat out from its centre. `--burst-x`, `--burst-y`,
   `--burst-spin` and `--burst-delay` are written by the view on every element: the geometry of a
   burst is data, not five more classes. */
.mineblock__burst {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.mineblock__burst-item {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2.25rem;
  height: 2.25rem;
  object-fit: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 0 6px var(--color-accent));
  animation: mineblock-escape 900ms var(--easing-standard) var(--burst-delay, 0ms) forwards;
}

@keyframes mineblock-escape {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.5);
  }
  15% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1.15);
  }
  100% {
    opacity: 0;
    transform: translate(
        calc(-50% + var(--burst-x, 0px)),
        calc(-50% + var(--burst-y, 0px))
      )
      scale(0.85) rotate(var(--burst-spin, 0deg));
  }
}

/* --- Hint, empty state and resources ------------------------------------- */

.mineblock__hint,
.mineblock__empty {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__resources {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.mineblock__resource {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background-color: var(--color-surface-alt);
}

.mineblock__resource-icon {
  width: 1.25rem;
  height: 1.25rem;
  object-fit: contain;
  image-rendering: pixelated;
}

.mineblock__resource-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}

/* --- The inventory (a chest, and nothing else) --------------------------- */

/* The chest IS the button: no border, no background, nothing but the picture. Its size is decided
   here rather than by the file (150px), and the still frame the view paints over the animation is
   drawn in the very same box. */
.mineblock__inventory {
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.mineblock__inventory-icon {
  display: block;
  width: 3.5rem;
  height: 3.5rem;
  aspect-ratio: 1;
  image-rendering: pixelated;
  transition: transform var(--duration-fast) var(--easing-standard);
}

/* The chest leans forward under the finger and settles back: the opening frames drawn on its
   canvas are the reward, this is only the acknowledgement of the tap. */
.mineblock__inventory:hover .mineblock__inventory-icon,
.mineblock__inventory:focus-visible .mineblock__inventory-icon {
  transform: scale(1.06);
}

.mineblock__inventory:active .mineblock__inventory-icon {
  transform: scale(0.95);
}

/* A broken block sends its loot to the chest: one short shake, then back to rest. The duration
   must stay equal to `CHEST_SHAKE_MS` of `MineBlockView.js`. */
.mineblock__inventory.is-shaking .mineblock__inventory-icon {
  animation: mineblock-chest-shake 460ms var(--easing-standard);
}

@keyframes mineblock-chest-shake {
  0%,
  100% {
    transform: none;
  }
  15% {
    transform: translateY(-6px) rotate(-7deg);
  }
  35% {
    transform: translateY(1px) rotate(6deg);
  }
  55% {
    transform: translateY(-3px) rotate(-4deg);
  }
  75% {
    transform: translateY(1px) rotate(3deg);
  }
}

.mineblock__inventory:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: var(--radius-md);
}

/* --- The inventory dialog ------------------------------------------------ */

.mineblock__inventory-list {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Icon, name, then the count pushed to the reading end: the quantities line up in a column. */
.mineblock__inventory-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
}

.mineblock__inventory-item-icon {
  width: 1.75rem;
  height: 1.75rem;
  object-fit: contain;
  image-rendering: pixelated;
}

.mineblock__inventory-item-name {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__inventory-item-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}

.mineblock__inventory-empty {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

/* --- The shop of the wandering trader ------------------------------------ */

/* The card on the left, everything that is read and touched on the right: the offers of a week are
   a LIST inside a dialog, so each one has to stay compact enough to be scanned. */
.mineblock__trader-intro,
.mineblock__trader-empty {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__trader-week {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text);
}

.mineblock__trader-week-value {
  font-weight: 700;
}

/* --- The cards of the merchant ------------------------------------------- */

/* The cards come first: the pinned offer opens the shop, so it must never sit below the daily
   sections. */
.mineblock__offers {
  margin-top: var(--space-3);
}

.mineblock__offers-title {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-md);
}

/* --- The daily Sparks offer ---------------------------------------------- */

/* One resource drawn for the day, sold once. It sits between the cards and the trades: a purchase
   in Sparks, not an exchange of resources. */
.mineblock__spark-offer {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

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

.mineblock__spark-help {
  margin: var(--space-2) 0 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__spark-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
}

.mineblock__spark-card[data-state="ready"] {
  border-color: var(--color-accent);
}

.mineblock__spark-card[data-state="used"] {
  opacity: 0.6;
}

.mineblock__spark-icon {
  width: 2.5rem;
  height: 2.5rem;
  object-fit: contain;
  image-rendering: pixelated;
}

.mineblock__spark-details {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}

.mineblock__spark-name {
  margin: 0;
  font-weight: 700;
  color: var(--color-text);
}

.mineblock__spark-value,
.mineblock__spark-price {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__spark-buy {
  white-space: nowrap;
}

.mineblock__spark-body.is-busy {
  pointer-events: none;
  opacity: 0.7;
}

/* On a phone the buy button takes its own row: three columns leave too little width for the name,
   the value and the price, and the button would overlap the text it is meant to follow. */
@media (max-width: 560px) {
  .mineblock__spark-card {
    grid-template-columns: auto 1fr;
  }

  .mineblock__spark-buy {
    grid-column: 1 / -1;
    width: 100%;
  }
}

/* --- The trades of the day ------------------------------------------------ */

/* They sit under the cards and the Sparks offer, separated by a rule: an exchange is not a purchase,
   and the two must never be read as one list. */
.mineblock__trades {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

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

.mineblock__trades-title {
  margin: 0;
  font-size: var(--font-size-md);
}

.mineblock__trades-reset {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__trades-reset-value {
  color: var(--color-accent);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.mineblock__trades-empty {
  margin: var(--space-2) 0 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__trade-list {
  display: grid;
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

/* An exchange in flight freezes the whole list, for the same reason as a purchase: a second tap
   would spend a resource the first one already took. */
.mineblock__trade-list.is-busy {
  pointer-events: none;
  opacity: 0.7;
}

.mineblock__trade {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
}

/* Ready to be taken, out of reach, already taken: three states, three borders. */
.mineblock__trade[data-state="ready"] {
  border-color: var(--color-accent);
}

.mineblock__trade[data-state="used"] {
  opacity: 0.6;
}

.mineblock__trade-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.mineblock__trade-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  background-color: var(--color-surface);
  font-size: var(--font-size-sm);
}

.mineblock__trade-chip-icon {
  width: 1.5rem;
  height: 1.5rem;
  object-fit: contain;
}

.mineblock__trade-chip-text {
  font-weight: 700;
}

/* What the player holds of that resource, next to its name: the reason a button is disabled. */
.mineblock__trade-chip-have {
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
}

.mineblock__trade-sign {
  color: var(--color-text-muted);
  font-size: var(--font-size-lg);
}

.mineblock__trade-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* The two directions share the row: either half of the equation can be given. */
.mineblock__trade-action {
  flex: 1 1 10rem;
}

.mineblock__trader-list {
  display: grid;
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

/* A purchase in flight freezes the whole list: a second tap on another offer while the first one is
   being written would spend resources the player no longer has. */
.mineblock__trader-list.is-busy {
  pointer-events: none;
  opacity: 0.7;
}

.mineblock__offer {
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
}

/* A pinned offer is written by hand, it is rare and it is finite: it gets the accent border, a
   halo and a badge, so it is never mistaken for one of the five drawn ones. */
.mineblock__offer[data-source="pinned"] {
  position: relative;
  border: 2px solid var(--color-accent);
  background-color: var(--color-surface);
  box-shadow: 0 0 0 3px rgba(96, 200, 255, 0.08), var(--shadow-md);
}

.mineblock__offer-badge {
  align-self: flex-start;
  padding: 0 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;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* The picture is a button: it opens the card. It brings no chrome of its own, so the offer keeps
   its layout whatever the platform's default button styling is. */
.mineblock__offer-open {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  touch-action: manipulation;
}

.mineblock__offer-open:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.mineblock__offer-footer {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.mineblock__offer-countdown {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0;
  font-size: var(--font-size-xs);
  color: var(--color-accent);
  font-weight: 700;
}

.mineblock__offer-countdown-value {
  font-variant-numeric: tabular-nums;
}

/* An offer that cannot be bought right now stays readable: it is a goal, not a dead end. */
.mineblock__offer[data-state="exhausted"] {
  opacity: 0.6;
}

.mineblock__offer-image {
  width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}

/* An illustration that did not ship keeps its room: the offers stay aligned. */
.mineblock__offer-image.is-missing {
  visibility: hidden;
}

.mineblock__offer-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}

.mineblock__offer-name {
  margin: 0;
  font-weight: 700;
  color: var(--color-text);
}

.mineblock__offer-meta,
.mineblock__offer-stock {
  margin: 0;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

.mineblock__offer-price {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.mineblock__price {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-pill);
  background-color: var(--color-surface);
  font-size: var(--font-size-xs);
}

/* The line the player cannot pay for yet: the price of an offer is a shopping list, so what is
   missing has to be visible without reading the shop twice. */
.mineblock__price.is-missing {
  border-color: var(--color-error);
  color: var(--color-error);
}

.mineblock__price-icon {
  width: 1rem;
  height: 1rem;
  object-fit: contain;
  image-rendering: pixelated;
}

.mineblock__price-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: inherit;
}

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

.mineblock__price.is-missing .mineblock__price-name {
  color: inherit;
}

.mineblock__offer-buy {
  align-self: flex-start;
}

/* The clock of the reroll, in the header of the dialog. */
.mineblock__trader-restock {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__trader-restock-value {
  color: var(--color-accent);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* --- One offer in detail -------------------------------------------------- */

.mineblock__detail-figure {
  margin: 0;
  display: grid;
  place-items: center;
}

.mineblock__detail-image {
  width: min(100%, 15rem);
  height: auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}

.mineblock__detail-image.is-missing {
  visibility: hidden;
}

.mineblock__detail-meta {
  margin: 0;
  text-align: center;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.mineblock__detail-desc {
  margin: 0;
  font-size: var(--font-size-sm);
  line-height: 1.55;
  color: var(--color-text);
}

.mineblock__detail-subtitle {
  margin: 0;
  font-size: var(--font-size-sm);
  font-weight: 700;
  color: var(--color-text);
}

.mineblock__detail-price {
  margin: 0;
}

.mineblock__detail-stock {
  margin: 0;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

/* The detail sits ON TOP of the shop (two classes, so it wins over the shared `.modal` rule whatever
   the order of the stylesheets is). */
.modal.mineblock__offer-modal {
  z-index: calc(var(--z-overlay) + 1);
}

/* --- A player who asked for less motion ---------------------------------- */

/* The base rituals of the mine do not belong to an animation mode, so the reduced-motion guard
   lives here: the block still cracks (that IS the game) but nothing flies around it. */
@media (prefers-reduced-motion: reduce) {
  .mineblock__rock.is-hit .mineblock__rock-inner,
  .mineblock__rock.is-broken .mineblock__rock-inner,
  .mineblock__rock.is-arriving .mineblock__rock-inner {
    animation: none;
  }

  /* The rewards still exist and are still announced (the toasts carry the numbers); they simply do
     not fly: leaving them on screen would pile them up in the middle of the block. */
  .mineblock__burst-item {
    display: none;
  }

  .mineblock__inventory.is-shaking .mineblock__inventory-icon {
    animation: none;
  }
}

/* --- The Illager Shop ---------------------------------------------------- */

/* The second merchant of the mine. Its palette is its own (ash, blood and ember) instead of the blue
   accent of the game, so it is never mistaken for the Wandering Trader, and the tokens are scoped to
   the dialog rather than added to the theme: it is a place, not a setting. */
.illager-shop {
  --illager-ash: #16110e;
  --illager-ember: #ff7a45;
  --illager-blood: #b3261e;
  --illager-ink: #f2dfc4;
  --illager-muted: #c9b49a;
  border: 1px solid #3d2a1f;
  background-color: var(--illager-ash);
  background-image: radial-gradient(circle at 50% -10%, rgba(179, 38, 30, 0.35), transparent 62%);
  color: var(--illager-ink);
}

.illager-shop__title {
  color: var(--illager-ember);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-shadow: 0 0 18px rgba(179, 38, 30, 0.55);
}

.illager-shop__intro,
.illager-shop__empty,
.illager-shop__patrol-text {
  margin: 0;
  font-size: var(--font-size-sm);
  color: var(--illager-muted);
}

.mineblock__illager-button {
  position: relative;
}

/* No set is open today: the button is greyed, but it stays clickable - the dialog is what says
   when the patrol comes back. */
.mineblock__illager-button.is-quiet {
  filter: grayscale(1);
  opacity: 0.55;
}

/* The wallet: the currency of the open set and what the player owns of it, in one line. */
.illager-shop__wallet {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid #3d2a1f;
  border-radius: var(--radius-md);
  background-color: rgba(255, 255, 255, 0.04);
}

.illager-shop__wallet-icon {
  width: 1.75rem;
  height: 1.75rem;
  image-rendering: pixelated;
}

.illager-shop__wallet-name {
  flex: 1 1 auto;
  font-size: var(--font-size-sm);
}

.illager-shop__wallet-amount {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--illager-ember);
}

.illager-shop__window {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  margin: var(--space-2) 0 0;
  font-size: var(--font-size-sm);
  color: var(--illager-muted);
}

.illager-shop__window-value,
.illager-shop__patrol-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--illager-ember);
}

.illager-shop__offers {
  margin-top: var(--space-4);
}

.illager-shop__offers-title {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-md);
  color: var(--illager-ink);
}

.illager-shop__list {
  display: grid;
  gap: var(--space-3);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

/* A purchase in flight freezes the list: a second tap would spend a balance that no longer covers
   it. */
.illager-shop__list.is-busy {
  pointer-events: none;
  opacity: 0.7;
}

.illager-shop__offer {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-3);
  align-items: center;
  padding: var(--space-3);
  border: 1px solid #3d2a1f;
  border-radius: var(--radius-md);
  background-color: rgba(255, 255, 255, 0.03);
}

.illager-shop__offer[data-state="expensive"] {
  border-color: rgba(179, 38, 30, 0.65);
}

.illager-shop__offer[data-state="exhausted"] {
  opacity: 0.55;
}

.illager-shop__offer-rewards {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.illager-shop__reward {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: var(--font-size-sm);
}

.illager-shop__reward-icon,
.illager-shop__price-icon {
  width: 1.25rem;
  height: 1.25rem;
  image-rendering: pixelated;
}

/* A pack and a card are pictures, not glyphs: they keep their own proportions and are drawn tall
   enough to be recognised before their name is read. */
.illager-shop__reward-icon[data-kind="booster"],
.illager-shop__reward-icon[data-kind="card"] {
  width: auto;
  height: 3.25rem;
  object-fit: contain;
}

/* The card of an offer is the one reward worth opening: its line is a button, and it says so on
   hover and on focus. */
.illager-shop__reward-open {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: var(--space-1) var(--space-2);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background-color: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--font-size-sm);
  text-align: left;
  cursor: pointer;
  touch-action: manipulation;
}

.illager-shop__reward-open:hover,
.illager-shop__reward-open:focus-visible {
  border-color: rgba(255, 122, 69, 0.55);
  background-color: rgba(255, 122, 69, 0.12);
}

.illager-shop__reward-open:focus-visible {
  outline: 2px solid var(--illager-ember);
  outline-offset: 2px;
}

.illager-shop__offer-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.illager-shop__price {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-weight: 700;
  color: var(--illager-ember);
}

.illager-shop__flag {
  font-size: var(--font-size-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #a08a72;
}

/* The patrol: nobody is here. The next set is counted down, never revealed. */
.illager-shop__patrol {
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  text-align: center;
}

.illager-shop__patrol-image {
  width: min(100%, 20rem);
  border-radius: var(--radius-md);
}

.illager-shop__patrol-timer {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: 0;
  font-weight: 700;
}

.illager-shop__feedback {
  margin-top: var(--space-3);
}

.illager-shop .btn--primary {
  border-color: #7e1a15;
  background-color: var(--illager-blood);
  color: #fff3e4;
}

.illager-shop .btn--primary:disabled {
  opacity: 0.5;
}
