/* =====================================================================
   FIRST-RUN WALKTHROUGH
   ---------------------------------------------------------------------
   The whole page is darkened by ONE element. .tut-hole is positioned
   over the control being explained and carries a 9999px box-shadow
   spread — so the shadow covers everything except the hole itself. No
   seams, no four-panel geometry chasing the target's edges, and it
   redraws with a single style write per step.
   ===================================================================== */

.tut[hidden] { display: none; }
.tut {
  position: fixed;
  inset: 0;
  z-index: 9600;
  /* The layer itself must not swallow clicks anywhere except its own
     card — the hole is meant to look reachable. */
  pointer-events: none;
}

.tut-hole {
  position: fixed;
  border-radius: var(--radius-md);
  box-shadow: 0 0 0 9999px rgba(2, 1, 8, 0.82);
  transition: left 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
              top 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
              width 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
              height 380ms cubic-bezier(0.22, 0.61, 0.36, 1);
  pointer-events: none;
}

/* A ring around the cutout so the edge reads as deliberate rather than
   as a gap in the dark. */
.tut-ring {
  position: fixed;
  border-radius: var(--radius-md);
  border: 2px solid var(--gold-bright, #ffd94d);
  box-shadow: 0 0 22px rgba(255, 217, 77, 0.55);
  pointer-events: none;
  animation: tutRingPulse 2200ms ease-in-out infinite;
  transition: left 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
              top 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
              width 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
              height 380ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
@keyframes tutRingPulse {
  0%, 100% { box-shadow: 0 0 18px rgba(255, 217, 77, 0.4); }
  50%      { box-shadow: 0 0 30px rgba(255, 217, 77, 0.75); }
}

.tut-card {
  position: fixed;
  width: min(340px, calc(100vw - 24px));
  padding: 16px 18px 14px;
  border-radius: var(--radius-md);
  border: 1px solid rgba(255, 214, 138, 0.45);
  background: linear-gradient(180deg, #1b1130, #0a0614);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.7);
  pointer-events: auto;          /* the one thing that IS clickable */
  transition: left 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
              top 380ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.tut-step {
  font-family: 'Orbitron', sans-serif;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  color: rgba(255, 255, 255, 0.45);
}
.tut-title {
  margin: 4px 0 6px;
  font-family: 'Orbitron', sans-serif;
  font-size: 0.98rem;
  letter-spacing: 0.08em;
  color: var(--gold-bright, #ffd94d);
}
.tut-body {
  margin: 0 0 14px;
  font-size: 0.86rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.84);
}

.tut-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.tut-nav { display: flex; gap: 8px; }

.tut-skip {
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.5);
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px 2px;
  transition: color 160ms ease;
}
.tut-skip:hover { color: #fff; text-decoration: underline; }

.tut-back, .tut-next {
  padding: 7px 14px;
  border-radius: var(--radius-sm);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: transparent;
  color: rgba(255, 255, 255, 0.8);
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.tut-back:hover:not(:disabled) { background: rgba(255, 255, 255, 0.08); color: #fff; }
.tut-back:disabled { opacity: 0.35; cursor: not-allowed; }
.tut-next {
  border-color: var(--gold-bright, #ffd94d);
  background: linear-gradient(180deg, rgba(255, 214, 138, 0.28), rgba(255, 184, 0, 0.12));
  color: #fff;
}
.tut-next:hover { background: linear-gradient(180deg, rgba(255, 214, 138, 0.42), rgba(255, 184, 0, 0.2)); }

@media (prefers-reduced-motion: reduce) {
  .tut-hole, .tut-ring, .tut-card { transition: none; }
  .tut-ring { animation: none; }
}
@media (max-width: 720px) {
  .tut-ring { animation: none; }
  .tut-card { padding: 13px 14px 12px; }
  .tut-body { font-size: 0.8rem; }
}

/* The modal became a flex column (to pin COLLECT), and the chest's
   `margin: 0 auto` no longer reliably centres it there. Explicit. */
.gift-chest { align-self: center; }

/* Matches the chest overlay's scroller rather than a 15px system bar. */
.daily-gift-modal { scrollbar-width: thin; }

/* =====================================================================
   SHOP — sub-menus, search, and the info button that was being clipped
   ===================================================================== */

/* --- THE CLIPPED INFO BUTTON ---
   It sat at top:-9px; right:-9px, i.e. OUTSIDE the card. #shopScreen
   scrolls (overflow: auto), so anything poking past the grid's top edge
   was cut — measured at 8px above it on the whole first row, which is
   why only "some of them" looked wrong.

   Moved inside the card. Nothing that lives outside its own box can be
   made safe here; the card's corner is somewhere it can always sit. */
.shop-card-info,
.shop-card-info.info-btn {
  top: 8px;
  right: 8px;
  width: 24px;
  height: 24px;
  font-size: 0.74rem;
}
/* The icon now overlaps the card's own padding, so the label and blurb
   need to keep clear of it. */
.shop-card-label { padding-right: 26px; }

/* --- SEARCH --- */
.shop-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px auto 4px;
  padding: 0 12px;
  width: min(420px, 100%);
  height: 38px;
  border-radius: var(--radius-pill);
  background: rgba(4, 10, 18, 0.72);
  border: 1px solid rgba(34, 227, 255, 0.32);
  transition: border-color 200ms ease, box-shadow 200ms ease;
}
.shop-search:focus-within {
  border-color: var(--cyan, #22e3ff);
  box-shadow: 0 0 16px rgba(34, 227, 255, 0.34);
}
.shop-search-icon {
  width: 16px;
  height: 16px;
  flex: none;
  color: rgba(255, 255, 255, 0.45);
}
.shop-search-input {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: none;
  background: none;
  outline: none;
  color: #fff;
  font-family: inherit;
  font-size: 0.9rem;
}
.shop-search-input::placeholder { color: rgba(255, 255, 255, 0.38); }
/* Safari draws its own clear affordance; there is one in the markup. */
.shop-search-input::-webkit-search-cancel-button { -webkit-appearance: none; }
.shop-search-clear {
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  transition: background 160ms ease;
}
.shop-search-clear:hover { background: rgba(255, 255, 255, 0.24); }
.shop-search-clear[hidden] { display: none; }

/* The category row steps back while a search is running, because the
   results cross every category and highlighting one would be a lie. */
.shop-tabs.is-searching { opacity: 0.45; }
.shop-tabs.is-searching .shop-tab.active {
  border-color: rgba(255, 255, 255, 0.14);
  box-shadow: none;
}

/* --- SUB-TABS --- */
.shop-subtabs[hidden] { display: none; }
.shop-subtabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin: 8px auto 2px;
  padding: 0 8px;
}
.shop-subtab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.04);
  color: rgba(255, 255, 255, 0.66);
  font-size: 0.76rem;
  letter-spacing: 0.03em;
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
}
.shop-subtab:hover { background: rgba(255, 255, 255, 0.1); color: #fff; }
.shop-subtab.active {
  border-color: var(--cyan, #22e3ff);
  background: linear-gradient(180deg, rgba(34, 227, 255, 0.24), rgba(34, 227, 255, 0.08));
  color: #fff;
}
.shop-subtab-count {
  min-width: 18px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: rgba(0, 0, 0, 0.4);
  font-size: 0.66rem;
  font-variant-numeric: tabular-nums;
}

/* --- nothing found --- */
.shop-empty[hidden] { display: none; }
.shop-empty {
  margin: 28px auto;
  text-align: center;
  font-size: 0.92rem;
  color: rgba(255, 255, 255, 0.55);
}

@media (max-width: 720px) {
  .shop-search { height: 34px; margin-top: 8px; }
  .shop-search-input { font-size: 0.84rem; }
  .shop-subtab { padding: 4px 10px; font-size: 0.7rem; }
}

/* --- profile picture, in the account panel --- */
.account-me {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 12px;
}
.account-me-body { flex: 1; min-width: 0; }

.account-avatar {
  position: relative;
  flex: none;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  overflow: hidden;
  cursor: pointer;
  border: 2px solid rgba(255, 214, 138, 0.5);
  background: linear-gradient(180deg, #1b1130, #0a0614);
  display: grid;
  place-items: center;
  transition: border-color 200ms ease, transform 200ms ease;
}
.account-avatar:hover { border-color: var(--gold-bright, #ffd94d); transform: scale(1.04); }
.account-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.account-avatar-empty {
  font-family: 'Orbitron', sans-serif;
  font-size: 1.8rem;
  font-weight: 700;
  color: var(--gold-bright, #ffd94d);
}
/* The affordance only appears on hover, so the picture is the picture
   the rest of the time. */
.account-avatar-edit {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 3px 0;
  background: rgba(0, 0, 0, 0.72);
  color: #fff;
  font-size: 0.54rem;
  letter-spacing: 0.12em;
  text-align: center;
  opacity: 0;
  transition: opacity 180ms ease;
}
.account-avatar:hover .account-avatar-edit { opacity: 1; }

.account-link {
  margin-top: 6px;
  padding: 0;
  border: none;
  background: none;
  color: rgba(255, 255, 255, 0.5);
  font-size: 0.74rem;
  text-decoration: underline;
  cursor: pointer;
}
.account-link:hover { color: #fff; }

.account-avatar-hint[hidden] { display: none; }
.account-avatar-hint { margin: 0 0 10px; font-size: 0.76rem; }
.account-avatar-hint.is-error { color: #ff8a8a; }

@media (prefers-reduced-motion: reduce) {
  .account-avatar:hover { transform: none; }
}

/* A gifted chest names its sender. The ordinary chest stays wordless. */
.chest-hint.is-gift {
  font-family: 'Orbitron', sans-serif;
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--gold-bright, #ffd94d);
  text-shadow: 0 0 18px rgba(255, 217, 77, 0.6);
  margin-bottom: 10px;
}

/* =====================================================================
   PHONE — stop the things that run forever
   ---------------------------------------------------------------------
   The reel GIFs were the bulk of it (400 instances, fixed in JS), but a
   handful of CSS animations also run continuously whether or not
   anything is happening. On a phone each one is a composite every frame,
   for the whole session, while the reels are trying to stay smooth.

   These are the ones with no state to convey — decoration that idles.
   Anything that TELLS the player something (a live boost timer going
   red, the daily gift being ready) keeps moving.
   ===================================================================== */
@media (max-width: 820px) {
  /* The frame's conic sweep repaints a border around the biggest box on
     screen every frame, forever. The border still shows which machine
     you are on; it just stops turning. */
  .cabinet .machine-frame::after,
  body.jk1x-active .cabinet .machine-frame::after { animation: none; }

  /* Idle button shine and breathing. The button is obviously a button. */
  .spin-btn-shine, .shop-cta-shine { animation: none; opacity: 0; }
  .spin-btn { animation: none; }

  /* Ambient scene motes and sparkles. */
  .room-mote, .chest-mote, .shop-sparkles, .curtain-spark, .refill-spark { display: none; }

  /* Full-screen backdrop-filters: the single most expensive thing here,
     and every one sits behind an already-opaque panel. */
  .shop-screen, .chest-overlay, .levelup-overlay, .stats-overlay,
  .paytable-overlay, .odds-overlay, .account-overlay, .bag-overlay,
  .nospins-overlay, .wheel-overlay {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  /* Decorative pulses on things that are not currently doing anything. */
  .prize-grand, .boosts-btn.is-live, .hud-icon-badge { animation: none; }

  /* The reel blur is a per-frame filter on five tall elements. */
  .reel-track.blurring { filter: blur(0.7px); }

  /* Layered shadows read as one glow at this size. */
  .spin-btn, .spin-btn:hover:not(:disabled) {
    filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.6));
  }
}

/* Very small screens: drop the machine backdrop's animated speckle too.
   The static gradients underneath are what make it look built, and they
   cost one paint rather than one per frame. */
@media (max-width: 560px) {
  .machine-frame::before { animation: none; }
  .vx-medium, .vx-scanlines { display: none; }
  .terror-backdrop::after { animation: none; }
}


/* =====================================================================
   PHONE DECK OVERFLOW
   ---------------------------------------------------------------------
   Two things ran off the screen at 375px, both from the same cause:
   a fixed layout being handed more content than it has room for.

   1. REFILL. The deck is a three-column grid holding five children, so
      the pill auto-placed into row two, column one — a track sized to
      the BET meter at 23px. Its 101px of content overflowed the track
      and spilled 60px past the left edge of the screen, with the label
      clipped. Spanning the full row gives it the 335px that exists.

   2. HOLD. The rail is 359px wide and spends 56px of it on the jackpot
      widget, leaving ~303px for a cluster that wants 337px of buttons
      plus 24px of gaps. With nowrap it simply kept going, and HOLD
      ended up entirely off-screen — not clipped, not small: absent.
      Wrapping puts it on a second line instead of nowhere.

   The 480px breakpoint is measured, not guessed: the cluster needs
   ~417px including the jackpot widget, and the rail is the viewport
   less 16px of margin, so it stops fitting below about 433px — which
   includes a Pro Max in portrait at 430pt.
   ===================================================================== */
@media (max-width: 720px) {
  section.control-bar > .refill-pill {
    grid-column: 1 / -1;
    justify-self: stretch;
  }
}

@media (max-width: 480px) {
  .spin-cluster {
    flex-wrap: wrap;
    justify-content: center;
    row-gap: 6px;
  }
  /* min-width:auto is the flexbox default and is what stopped these
     shrinking to fit. It is needed on the cluster ITSELF as well as on
     its children: the cluster is a flex item of .rail, and without this
     it refuses to shrink below its own min-content width, so its box
     kept running past the screen edge even once the buttons inside had
     wrapped neatly. */
  .spin-cluster, .spin-cluster > * { min-width: 0; }
  /* And the cluster is declared flex: 0 0 auto — flex-shrink ZERO — so
     min-width alone could never make it fit: it had been told outright
     never to give up width. This is what actually lets it come inside
     the screen edge. */
  .spin-cluster { flex-shrink: 1; }
}

/* =====================================================================
   SHOP: THE PURCHASE ANIMATION AND THE LEVEL LOCK
   ---------------------------------------------------------------------
   Both live here, at the end of the cascade, because the shop card is
   styled across three earlier sheets and these have to win.
   ===================================================================== */

/* The flash panel is inert until the class lands, so thirty of them
   sitting in the grid cost nothing. */
.shop-card { position: relative; overflow: hidden; }
.shop-card-flash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  border-radius: inherit;
  background: linear-gradient(115deg, transparent 30%, rgba(255, 217, 77, 0.55) 50%, transparent 70%);
  transform: translateX(-120%);
}

.shop-card.is-purchased {
  animation: shopBuyPop 620ms cubic-bezier(0.2, 0.9, 0.3, 1.3);
  border-color: var(--gold-bright);
}
.shop-card.is-purchased .shop-card-flash {
  opacity: 1;
  animation: shopBuySweep 620ms cubic-bezier(0.3, 0.7, 0.3, 1) forwards;
}
/* A tick, drawn rather than shipped as an asset. */
.shop-card.is-purchased::after {
  content: '✓';
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 2.6rem;
  color: var(--gold-bright);
  text-shadow: 0 0 18px rgba(255, 217, 77, 0.9), 0 2px 0 #000;
  pointer-events: none;
  animation: shopBuyTick 620ms cubic-bezier(0.2, 0.9, 0.3, 1.4) both;
}

@keyframes shopBuyPop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.045); }
  100% { transform: scale(1); }
}
@keyframes shopBuySweep {
  0%   { transform: translateX(-120%); }
  100% { transform: translateX(120%); }
}
@keyframes shopBuyTick {
  0%   { opacity: 0; transform: scale(0.4); }
  40%  { opacity: 1; transform: scale(1.15); }
  70%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1); }
}

/* ---------------------------------------------------------------------
   LOCKED CARDS
   Dimmed and unbuyable, but still legible and still THERE — the point of
   showing it is that the player can see what the next few levels are
   worth. A hidden card cannot tempt anyone.
   --------------------------------------------------------------------- */
.shop-card.is-level-locked { opacity: 0.62; }
.shop-card.is-level-locked .shop-card-icon { filter: grayscale(0.75); }
.shop-card.is-level-locked .shop-card-buy {
  background: rgba(255, 217, 77, 0.14);
  color: var(--gold-bright);
  border-color: rgba(255, 217, 77, 0.45);
  cursor: not-allowed;
}

.shop-card-lock {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  background: rgba(0, 0, 0, 0.78);
  border: 1px solid rgba(255, 217, 77, 0.55);
  color: var(--gold-bright);
  font-family: 'Orbitron', sans-serif;
  font-size: 0.58rem;
  letter-spacing: 0.09em;
  white-space: nowrap;
}
.shop-card-lock-icon { font-size: 0.62rem; line-height: 1; }

@media (prefers-reduced-motion: reduce) {
  .shop-card.is-purchased,
  .shop-card.is-purchased .shop-card-flash,
  .shop-card.is-purchased::after { animation-duration: 1ms; }
}

/* =====================================================================
   NOTIFICATION BADGES, THE ALWAYS-ON BAG, "NEW" FLAGS AND THE RECEIPT
   ---------------------------------------------------------------------
   All at the end of the cascade so they beat the per-control styling
   these attach to.
   ===================================================================== */

/* One badge, used on the bag button and on the shop's LEAVE button. Red
   and small, because everyone already knows what that means — inventing
   a bespoke shape for "you have unread things" would only make it need
   explaining. */
.count-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  z-index: 3;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-pill);
  background: #e2372f;
  color: #fff;
  border: 2px solid rgba(0, 0, 0, 0.65);
  font-family: 'Orbitron', sans-serif;
  font-size: 0.58rem;
  line-height: 14px;
  text-align: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
  pointer-events: none;
  animation: badgePop 320ms cubic-bezier(0.2, 0.9, 0.3, 1.6) both;
}
.count-badge[hidden] { display: none; }
@keyframes badgePop {
  0%   { transform: scale(0.3); opacity: 0; }
  60%  { transform: scale(1.2); opacity: 1; }
  100% { transform: scale(1); }
}

/* The badges are absolutely positioned against their button. */
.btn.bag, .shop-close { position: relative; overflow: visible; }

/* THE BAG, WHILE IT HAS SOMETHING IN IT
   The button is always on screen now, so it needs to say the difference
   between empty and not from across the room. A slow breath rather than
   a flash: it has to survive being looked at for a whole session. */
.btn.bag.has-items {
  border-color: var(--gold-bright);
  animation: bagWaiting 2.4s ease-in-out infinite;
}
@keyframes bagWaiting {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 217, 77, 0); }
  50%      { box-shadow: 0 0 14px 2px rgba(255, 217, 77, 0.45); }
}

/* "NEW" — until it has been used
   Sits on the control the level just handed over. Two layers: the flag
   itself, and a soft halo on the control so it catches the eye before
   the word is read. */
.new-flag {
  position: absolute;
  top: -8px;
  left: -8px;
  z-index: 4;
  padding: 2px 6px;
  border-radius: 4px;
  background: linear-gradient(180deg, #ffd94d, #c9962f);
  color: #1a1206;
  font-family: 'Orbitron', sans-serif;
  font-size: 0.5rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  border: 1px solid rgba(0, 0, 0, 0.55);
  pointer-events: none;
  animation: newFlagFloat 1.8s ease-in-out infinite;
}
@keyframes newFlagFloat {
  0%, 100% { transform: translateY(0) rotate(-6deg); }
  50%      { transform: translateY(-3px) rotate(-6deg); }
}

.has-new {
  position: relative;
  overflow: visible;
  animation: newHalo 1.8s ease-in-out infinite;
}
@keyframes newHalo {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 217, 77, 0.0); }
  50%      { box-shadow: 0 0 16px 3px rgba(255, 217, 77, 0.55); }
}

/* THE PURCHASE RECEIPT
   Slides in from the top, holds, and leaves on its own. Not a dialog:
   it appears while the player is still shopping. */
.purchase-popup {
  position: fixed;
  top: 18px;
  left: 50%;
  z-index: 12000;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 18px 10px 12px;
  border-radius: var(--radius-pill);
  background: rgba(10, 10, 14, 0.94);
  border: 1px solid rgba(255, 217, 77, 0.45);
  box-shadow: 0 14px 44px -12px rgba(0, 0, 0, 0.9);
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -24px);
  transition: opacity 240ms ease, transform 240ms cubic-bezier(0.2, 0.9, 0.3, 1.3);
}
.purchase-popup.is-open {
  opacity: 1;
  transform: translate(-50%, 0);
}
.purchase-popup-art {
  flex: none;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
}
/* shopIconFor returns a bare <img>, which arrives at its natural size
   without this — the same trap the gain chips hit. */
.purchase-popup-art img { max-width: 100%; max-height: 100%; object-fit: contain; }
.purchase-popup-body { display: flex; flex-direction: column; gap: 2px; text-align: left; }
.purchase-popup-label {
  font-family: 'Orbitron', sans-serif;
  font-size: 0.8rem;
  color: var(--gold-bright);
}
.purchase-popup-dest {
  font-size: 0.66rem;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.62);
}

@media (max-width: 480px) {
  .purchase-popup { top: 10px; padding: 8px 14px 8px 10px; max-width: 92vw; }
  .purchase-popup-art { width: 32px; height: 32px; }
  .purchase-popup-label { font-size: 0.72rem; }
  .purchase-popup-dest { font-size: 0.6rem; }
}

@media (prefers-reduced-motion: reduce) {
  .count-badge, .new-flag, .has-new, .btn.bag.has-items { animation: none; }
  .purchase-popup { transition-duration: 1ms; }
}

/* =====================================================================
   THE RESHUFFLE
   ---------------------------------------------------------------------
   Four blocks swapped homes in pairs:

     HUD   spins → refill,     level bar → active boosts
     DECK  refill → spins,     active boosts → level bar

   The reasoning: the two things a player checks constantly are the
   balances, and the two they glance at occasionally are the level bar
   and whatever boosts are running. Those were the wrong way round — the
   level bar had prime real estate at the top while the spin count, which
   decides whether you can press SPIN at all, sat in a small pill.

   A moved block carries .in-hud so it can be restyled for where it now
   lives without touching how it looked before. That matters because
   .hud-stat and .refill-pill are both styled across several earlier
   sheets, and this file is the last one loaded.

   There was a matching .in-deck for the other direction. Nothing in the
   markup ever carried it — the swap above ended up being done a
   different way — so every .in-deck rule in this file was styling an
   element that does not exist, and they have been removed.
   ===================================================================== */

/* ---- BALANCES, BIGGER ------------------------------------------------
   The figure is the thing being read, so it gets the size; the label is
   context and can shrink. Tabular numerals stop the width jittering as
   the count animates, which at this size is very visible. */
.hud-value,
.hud-stat .hud-value {
  font-size: clamp(1.15rem, 3.4vw, 1.7rem);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  line-height: 1.05;
}
.hud-label { font-size: 0.6rem; letter-spacing: 0.14em; opacity: 0.75; }
.hud-stat .hud-icon { width: 34px; height: 34px; }
#hudCoins { padding-inline: 14px; }

/* ---- REFILL, NOW IN THE HUD ----------------------------------------- */
.refill-pill.in-hud {
  align-self: center;
  min-width: 96px;
  padding: 8px 14px;
}

@media (max-width: 480px) {
  .hud-stat .hud-icon { width: 26px; height: 26px; }
  .refill-pill.in-hud { min-width: 78px; padding: 6px 10px; }
  .hud-label { font-size: 0.54rem; }
}

