/* =====================================================================
   ARRIVAL FROM THE LANDING PAGE
   The landing's departure ends on rgba(3,3,5,0.985) with a gold gif
   filling the screen. This loader starts on the same near-black and
   opens with the same gold, so the two pages join without a flash of
   anything in between — the arrival is a continuation of the departure
   rather than a separate screen.
   ===================================================================== */
#loader {
  background: #030305;
}

/* The gif rushes back out from the centre, reversing the zoom the
   landing page finished on. */
@keyframes loaderArrive {
  0%   { opacity: 0.35; transform: scale(9) rotate(4deg); }
  55%  { opacity: 1; }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
.loader-arrival {
  /* In flow, not absolute: the loader is a flex column, and taking the
     artwork out of flow made the text render on top of it instead of
     underneath. */
  width: 130px;
  height: 130px;
  object-fit: cover;
  border-radius: var(--radius-lg);
  box-shadow: 0 0 40px 10px rgba(255, 217, 77, 0.4);
  animation: loaderArrive 620ms cubic-bezier(0.2, 0.75, 0.3, 1) both;
  pointer-events: none;
}

/* The text follows the artwork in rather than being there from frame
   one, so the eye has something to land on first. */
@keyframes loaderTextIn {
  0%   { opacity: 0; transform: translateY(14px) scale(0.94); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
.loader-text {
  animation: flicker 2s infinite alternate,
             loaderTextIn 460ms 340ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
  /* Real depth rather than a flat glow, matching the landing wordmark. */
  text-shadow:
    0 1px 0 #c9962f, 0 2px 0 #a87c26, 0 3px 0 #8a651f,
    0 5px 12px rgba(0, 0, 0, 0.9),
    0 0 10px #f90, 0 0 26px #ff0;
}

/* Positioned under the text rather than behind it. */
#loader { flex-direction: column; gap: 1.1rem; padding: 24px; }

/* =====================================================================
   THE MARQUEE
   ---------------------------------------------------------------------
   The logo used to sit on a bare blob of glow. It now sits in a lit sign
   frame, which is the thing a slot lobby actually looks like.

   The chase is two identical bulb layers offset by half a step,
   cross-fading. That matters for how it runs, not just how it looks:
   animating background-position would repaint the whole ring every
   frame, whereas opacity is composited. This screen is on while the
   phone is already busy decoding the first machine's art, so the loader
   cannot be the thing that costs anything.
   ===================================================================== */
.loader-marquee {
  position: relative;
  padding: 16px;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(120% 120% at 50% 0%, rgba(255, 217, 77, 0.10), transparent 70%),
    rgba(255, 255, 255, 0.02);
  box-shadow:
    inset 0 0 0 1px rgba(255, 217, 77, 0.22),
    0 18px 60px -18px rgba(255, 170, 40, 0.55);
}

@keyframes loaderBulbChase {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.loader-bulbs {
  position: absolute;
  inset: 6px;
  border-radius: var(--radius-lg);
  pointer-events: none;
  /* One dot pattern per edge, so the ring is drawn without four extra
     elements in the markup. */
  background-image:
    radial-gradient(circle, #ffd94d 0 2px, transparent 2.6px),
    radial-gradient(circle, #ffd94d 0 2px, transparent 2.6px),
    radial-gradient(circle, #ffd94d 0 2px, transparent 2.6px),
    radial-gradient(circle, #ffd94d 0 2px, transparent 2.6px);
  background-size: 18px 6px, 18px 6px, 6px 18px, 6px 18px;
  background-position: 0 0, 0 100%, 0 0, 100% 0;
  background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
  animation: loaderBulbChase 900ms steps(1, end) infinite;
}

/* The half-step offset, in antiphase, is what makes it read as running
   rather than simply blinking. */
.loader-bulbs-alt {
  background-position: 9px 0, 9px 100%, 0 9px, 100% 9px;
  animation-delay: 450ms;
}

.loader-marquee .loader-arrival {
  display: block;
  position: relative;
  z-index: 1;
  /* The old 40px blur ring is gone: the marquee frame is doing that job
     now, and a large blurred box-shadow is one of the more expensive
     things to paint. */
  box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.9);
}

/* =====================================================================
   PROGRESS
   ---------------------------------------------------------------------
   The old screen said "loading..." and left it there, so a slow first
   load was indistinguishable from a hung one. This is driven by the
   image preloader's real completion count, so it means something.

   The fill is scaleX rather than width — a transform is composited,
   a width change relayouts the bar every step.
   ===================================================================== */
.loader-progress {
  position: relative;
  width: min(320px, 74vw);
  height: 6px;
  border-radius: var(--radius-pill);
  overflow: hidden;
  background: rgba(255, 255, 255, 0.08);
  box-shadow: inset 0 0 0 1px rgba(255, 217, 77, 0.18);
  animation: loaderTextIn 460ms 420ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}

.loader-progress-fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, #c9962f, #ffd94d 55%, #fff3c4);
  transform: scaleX(var(--p, 0));
  transform-origin: left center;
  transition: transform 260ms cubic-bezier(0.3, 0.8, 0.3, 1);
}

/* A travelling highlight, so the bar still reads as alive during a long
   wait between two preload completions. */
@keyframes loaderSheen {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(320%); }
}
.loader-progress-sheen {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 30%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.45), transparent);
  animation: loaderSheen 1500ms ease-in-out infinite;
}

.loader-status {
  font-family: 'Orbitron', sans-serif;
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 224, 150, 0.65);
  animation: loaderTextIn 460ms 520ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}

@media (max-width: 480px) {
  .loader-text { font-size: 1.4rem; text-align: center; }
  .loader-marquee { padding: 13px; }
  .loader-arrival { width: 108px; height: 108px; }
}

@media (prefers-reduced-motion: reduce) {
  .loader-arrival { animation: none; }
  .loader-text { animation: flicker 2s infinite alternate; }
  /* The chase and the sheen are decoration; the fill still moves,
     because that one carries information. */
  .loader-bulbs, .loader-progress-sheen { animation: none; }
  .loader-bulbs-alt { opacity: 0; }
}

/* =====================================================================
   BIGGER CHEST ICONS + INFO BUTTON
   ===================================================================== */
/* Chests are the shop's headline goods and were being drawn at the same
   40px as a consumable. They get real presence. */
.shop-card-icon.is-chest img {
  width: 88px;
  height: 88px;
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.7));
}

.shop-card { position: relative; }

/* Sits on the border at the top right, deliberately small — it is a
   reference, not a call to action competing with the buy button. */
.shop-card-info {
  position: absolute;
  top: -9px;
  right: -9px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  z-index: 5;
  cursor: pointer;
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  font-size: 0.72rem;
  line-height: 1;
  color: #04222c;
  background: linear-gradient(180deg, #a8f4ff, #22e3ff 60%, #0e9fc4);
  border: 2px solid #eafffe;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.6);
  transition: transform 0.16s ease, box-shadow 0.16s ease;
}
.shop-card-info:hover {
  transform: scale(1.18);
  box-shadow: 0 0 14px 3px rgba(34, 227, 255, 0.7);
}

/* =====================================================================
   ODDS PANEL
   ===================================================================== */
.odds-overlay {
  position: fixed;
  inset: 0;
  z-index: 11700;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1.2rem;
  background: rgba(0, 0, 0, 0.85);
}
.odds-overlay.open { display: flex; }

.odds-panel {
  width: min(26rem, 100%);
  max-height: 88vh;
  overflow-y: auto;
  padding: 1.4rem;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, #10202c, #06101a);
  border: 2px solid var(--cyan);
  box-shadow: 0 0 36px rgba(34, 227, 255, 0.3);
}

.odds-head {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-bottom: 1rem;
}
.odds-art img { width: 62px; height: 62px; object-fit: contain; }
.odds-title {
  font-family: 'Orbitron', sans-serif;
  color: var(--cyan-bright);
  font-size: 1.05rem;
}

.odds-group { margin-bottom: 1rem; }
.odds-group h4 {
  font-family: 'Orbitron', sans-serif;
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  color: var(--text-dim);
  margin-bottom: 0.45rem;
  text-transform: uppercase;
}

.odds-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 0.6rem;
  align-items: baseline;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.04);
  margin-bottom: 4px;
  font-size: 0.8rem;
}
.odds-row-label { color: #fff; }
.odds-row-detail { color: var(--text-dim); font-size: 0.72rem; }
.odds-row-chance {
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  color: var(--gold);
  min-width: 3.4rem;
  text-align: right;
}

.odds-foot {
  font-size: 0.68rem;
  line-height: 1.5;
  color: var(--text-dim);
  margin-bottom: 1rem;
}

.odds-close {
  display: block;
  width: 100%;
  padding: 10px;
  border-radius: var(--radius-pill);
  background: transparent;
  border: 2px solid var(--border-dim);
  color: var(--text-dim);
  font-family: 'Orbitron', sans-serif;
  cursor: pointer;
}
.odds-close:hover { color: #fff; border-color: #fff; }

/* =====================================================================
   NEXT-LEVEL PREVIEW under the progress bar
   ===================================================================== */
.hud-level-next {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.55rem;
  margin-top: 6px;
  font-size: 0.66rem;
  color: var(--text-dim);
  line-height: 1.4;
}
.hud-level-next:empty { display: none; }

.lvl-next-head {
  font-family: 'Orbitron', sans-serif;
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  color: var(--cyan);
  text-transform: uppercase;
}
.hud-level-next span {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  white-space: nowrap;
}
.hud-level-next img { width: 13px; height: 13px; object-fit: contain; }
.hud-level-next .lvl-chest { color: var(--gold); }
.hud-level-next .lvl-unlock {
  color: #3a2600;
  background: var(--gold);
  padding: 1px 7px;
  border-radius: var(--radius-pill);
  font-size: 0.6rem;
  letter-spacing: 0.06em;
}

@media (max-width: 768px) {
  .shop-card-icon.is-chest img { width: 68px; height: 68px; }
  .hud-level-next { font-size: 0.6rem; }
}

