/* =====================================================================
   MOBILE — fewer layers, cheaper paints, same game
   ---------------------------------------------------------------------
   The desktop layout leans on blur, multi-layer shadows and several
   always-running gradient animations. Each is cheap on a laptop and
   expensive on a phone, where they compound into dropped frames on the
   one thing that has to stay smooth: the reels turning.

   So on a small screen the decoration is thinned rather than the game.
   ===================================================================== */

@media (max-width: 720px) {
  /* The mascot has no rail column to open a bubble into on a phone. */

  /* Backdrop blurs are the single most expensive thing on this page and
     the least missed: every one of them sits behind an already-opaque
     panel. */
  .shop-screen,
  .chest-overlay,
  .levelup-overlay,
  .stats-overlay,
  .paytable-overlay,
  .odds-overlay { backdrop-filter: none; -webkit-backdrop-filter: none; }

  /* One shadow instead of three or four. The layered versions exist to
     fake depth on a large screen; at this size they read as one glow. */
  .spin-btn { filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.6)); }
  .spin-btn:hover:not(:disabled) { filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.6)); }
  .shop-cta { box-shadow: 0 0 12px rgba(255, 184, 0, 0.45); }
  .boost-chip { box-shadow: none; }

  /* The reel blur is a per-frame filter on five tall elements. Halved:
     enough to read as motion, a fraction of the fill cost. */
  .reel-track.blurring { filter: blur(0.9px); }

  /* The frame's conic sweep repaints a border around the biggest box on
     screen, every frame, forever. It stays — it is what tells you which
     machine you are on — but it turns slowly enough to be nearly free. */
  .cabinet .machine-frame::after { animation-duration: 24s; }
  body.jk1x-active .cabinet .machine-frame::after { animation-duration: 8s; }

  /* Ambient decoration that costs frames and adds nothing on a screen
     this size. */
  .shop-sparkles, .chest-mote, .refill-spark { display: none; }
  .curtain-spark { display: none; }

  .shop-bag { grid-template-columns: 1fr; }
  .shop-qty-btn { min-width: 34px; padding: 6px 8px; }  /* thumb-sized */
  .bag-item-use { padding: 9px 14px; }
}

/* Promote only what actually moves, and only while it is moving. A
   permanent `will-change` on a large element keeps a layer alive for the
   whole session; the reels already set it because they animate on every
   spin, and these join them only for the duration of a transition. */
.curtains.busy .curtain { will-change: transform; }
.curtains:not(.busy) .curtain { will-change: auto; }

/* Touch targets and text selection. A slot machine is a rapid-tap
   interface: without this, a fast double-tap on SPIN zooms the page and
   a long-press selects the button's label. */
@media (pointer: coarse) {
  .spin-btn, .shop-cta, .refill-pill, .btn, .bet-step, .bet-current,
  .bet-max, .shop-qty-btn, .bag-item-use, .hud-plus, .shop-card-buy {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
    -webkit-user-select: none;
  }

  /* Hover styles stick on touch — the device has no way to un-hover, so
     a tapped button stays lit until something else is tapped. */
  .spin-btn:hover:not(:disabled) { transform: none; }
  .shop-cta:hover { transform: none; }
  .deck-social:hover { transform: none; }
  .refill-pill:not(:disabled):hover { transform: none; }
}

/* The reels are the one thing that must stay smooth. Rendering them on
   their own layer keeps a repaint anywhere else in the page — a ticking
   boost chip, a countdown, a coin flying past — from forcing the reel
   strips to repaint with it. */
.reel-col { contain: paint; }
.reels { contain: layout paint; }

/* =====================================================================
   THE BAG, REACHABLE FROM THE MACHINE
   ---------------------------------------------------------------------
   The same inventory the shop shows, as an overlay over the reels. A
   boost is banked so it can be started at the right moment, and going
   back through a curtain transition into a shop to start one defeats
   the point of banking it.
   ===================================================================== */

.btn.bag {
  position: relative;
  background: linear-gradient(180deg, #d9c2ff, #a06bff 55%, #5c2ea8);
  border-color: #c9a8ff;
  color: #150726;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
}

.btn.bag[hidden] { display: none; }

.bag-count {
  display: inline-grid;
  place-items: center;
  min-width: 15px;
  height: 15px;
  margin-left: 5px;
  padding: 0 3px;
  border-radius: var(--radius-pill);
  font-size: 0.55rem;
  font-weight: 700;
  color: #150726;
  background: #ffd94d;
  box-shadow: 0 0 8px rgba(255, 184, 0, 0.7);
}

.bag-overlay {
  position: fixed;
  inset: 0;
  z-index: 1400;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.72);
}

.bag-overlay.open { display: flex; }

.bag-panel {
  width: min(560px, 100%);
  max-height: min(70vh, 560px);
  overflow-y: auto;
  padding: 18px;
  border-radius: var(--radius-lg);
  border: 2px solid var(--gold-deep);
  background:
    radial-gradient(ellipse at 50% 0%, rgba(255, 217, 77, 0.15), transparent 65%),
    linear-gradient(180deg, #17110a, #0a0704);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.7), 0 0 30px rgba(255, 184, 0, 0.25);
  animation: bagPanelIn 240ms cubic-bezier(0.2, 1.3, 0.4, 1) both;
}

@keyframes bagPanelIn {
  from { opacity: 0; transform: translateY(14px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.bag-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.bag-title {
  margin: 0;
  font-size: 1.05rem;
  letter-spacing: 3px;
  color: var(--gold);
  text-shadow: 0 0 12px rgba(255, 184, 0, 0.5);
}

.bag-close {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid var(--border-dim);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--text-dim);
  background: rgba(255, 255, 255, 0.07);
  transition: color 150ms ease, border-color 150ms ease, background 150ms ease;
}

.bag-close:hover { color: #fff; border-color: #f66; background: rgba(255, 102, 102, 0.2); }

/* One column in the overlay: it is a list of things to press, not a
   grid to scan, and full-width rows give the USE button a real target. */
#machineBag { grid-template-columns: 1fr; }

@media (max-width: 720px) {
  .bag-panel { max-height: 78vh; padding: 14px; }
  .bag-item { grid-template-columns: auto auto minmax(0, 1fr) auto; gap: 6px; }
  .bag-item-use { padding: 10px 14px; }
}

/* A blocked card is dimmed to say "you cannot buy this right now" — but
   when what blocks it is the QUANTITY, the quantity control is the way
   out, so it stays at full strength. Dimming the only escape route
   alongside the thing it escapes from is what made the card feel stuck.
   MAX doubles as a reset: it drops to the largest run you can pay for,
   or to 1 when you can afford none. */
.shop-card.unaffordable .shop-qty {
  opacity: 1;
  filter: none;
}

.shop-card.unaffordable .shop-qty-btn {
  border-color: var(--gold-deep);
  color: var(--gold);
}

.shop-card.unaffordable .shop-qty-btn:hover {
  color: #06212b;
  border-color: var(--cyan);
  background: var(--cyan-bright);
}

/* =====================================================================
   THE CHEST MODAL — the dismiss button is never off-screen
   ---------------------------------------------------------------------
   Opening ten chests produced a reward grid taller than the viewport,
   which pushed NICE! below the fold of a page that cannot scroll. The
   only way out was to zoom the browser out.

   The modal is a column with a hard ceiling now: the art and the rewards
   give up space as the content grows, the rewards scroll if there are
   still too many, and the buttons are pinned to the bottom where they
   can always be pressed.
   ===================================================================== */

.chest-overlay {
  display: none;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.chest-overlay.open { display: flex; }

.chest-overlay .chest-modal {
  display: flex;
  flex-direction: column;
  max-height: calc(100dvh - 32px);
  padding: 20px 22px 18px;
  overflow: hidden;
}

/* The art is the star, but it yields first — it is the one element with
   nothing to read in it. */
.chest-overlay .chest-visual {
  flex: 0 1 auto;
  min-height: 0;
}

.chest-overlay .chest-img {
  max-height: min(38vh, 300px);
  width: auto;
  max-width: 100%;
  object-fit: contain;
}

.chest-overlay .chest-queue { flex: 0 0 auto; }
.chest-overlay .chest-hint  { flex: 0 0 auto; }

/* The scrolling part. Everything else is pinned. */
.chest-overlay .chest-rewards {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  align-content: flex-start;
  padding: 2px;
  scrollbar-width: thin;
}

/* Pinned: whatever the rewards do, these stay reachable. */
.chest-overlay .chest-open-all,
.chest-overlay .chest-done {
  flex: 0 0 auto;
  margin-top: 10px;
}

/* A count badge on a pooled tile — five Castle Keys are one tile now. */
.gift-icon { position: relative; }

.gift-icon-count {
  position: absolute;
  top: -8px;
  right: -8px;
  min-width: 22px;
  padding: 2px 6px;
  border-radius: var(--radius-pill);
  font-family: 'Orbitron', sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1.2;
  color: #1a0f00;
  background: linear-gradient(180deg, #fff3c4, #ffd94d 50%, #ffb800);
  box-shadow: 0 0 12px rgba(255, 184, 0, 0.8);
  z-index: 3;
}

@media (max-width: 720px) {
  .chest-overlay .chest-img { max-height: min(30vh, 220px); }
  .chest-overlay .chest-modal { padding: 14px 14px 12px; }
  .chest-overlay .chest-rewards { gap: 8px; }
}

/* =====================================================================
   THE CHEST, OPENING
   ===================================================================== */

/* Centred, always. The art varies in aspect ratio between tiers — some
   are 512x387, some 512x512 — and left to itself a wide chest sat off
   to one side of a tall one. */
.chest-overlay .chest-visual {
  display: grid;
  place-items: center;
  width: 100%;
  margin: 0 auto;
  background: none;
  border: none;
}

.chest-overlay .chest-img {
  display: block;
  margin: 0 auto;
  object-fit: contain;
}

.chest-overlay .chest-modal,
.daily-gift-modal { text-align: center; }

.gift-chest {
  display: grid;
  place-items: center;
  width: 100%;
  margin: 0 auto;
  background: none;
  border: none;
}

.gift-chest-img { display: block; margin: 0 auto; object-fit: contain; max-height: min(34vh, 260px); }

/* The count badge sat on the tile's corner and was clipped by the grid's
   own bounds — "x3" and "x4" lost their right-hand edge. Padding the
   grid gives every badge room to sit outside its tile without leaving
   the container. */
.chest-rewards,
.daily-gift-icons {
  padding: 12px 12px 4px;
  overflow-x: hidden;
}

.gift-icon { overflow: visible; }

/* Kept inside the tile instead of hanging off it. Nothing can clip a
   badge that never crosses its own edge. */
.gift-icon-count {
  top: 2px;
  right: 2px;
}

/* The queue no longer names what is coming, so its chip is a count and
   a question mark rather than a row of labelled tiers. */
.chest-queue-mark {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  font-size: 0.72rem;
  color: var(--gold);
  background: rgba(0, 0, 0, 0.45);
  box-shadow: inset 0 0 0 1px var(--gold-deep);
}

/* Four chests to a row, so the metal ladder (bronze → mythic) reads as
   one line and the themed ones fall into rows of their own beneath it.
   The server hands them over already ordered; this only sets the width.

   Driven by a class the renderer sets rather than :has() — the grid has
   to lay out correctly whether or not the browser supports it. */
.shop-grid.is-chests {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

@media (max-width: 900px) {
  .shop-grid.is-chests { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The level target, written across the bar itself. A fill with no
   figures cannot tell you whether the next level is two spins away or
   two thousand, which is the only thing the bar is asked. */
.hud-level-bar { position: relative; }

.hud-level-figures {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: 'Orbitron', sans-serif;
  font-size: 0.5rem;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9), 0 0 6px rgba(0, 0, 0, 0.8);
  pointer-events: none;
  white-space: nowrap;
}

@media (max-width: 720px) {
  .hud-level-figures { font-size: 0.44rem; }
}

