/* =====================================================================
   WHEEL — wordless
   ---------------------------------------------------------------------
   The title, the strapline and the odds legend are gone from the face.
   What replaces them: an info button that opens the odds on demand, and
   two icon-only controls.

   The odds are MOVED, not deleted. Twelve equal seats cannot show a
   spread that runs from 20% to 0.6%, so a wheel with no odds anywhere
   would be quietly claiming twelve equal chances. One tap away is
   honest; absent is not.
   ===================================================================== */

.wheel-title, .wheel-sub { display: none; }

/* The info button, top-right of the panel. */
.wheel-info-btn {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 4;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid rgba(255, 214, 138, 0.5);
  background: rgba(10, 6, 2, 0.6);
  color: var(--gold-bright, #ffd94d);
  font: 700 15px/1 'Georgia', serif;
  font-style: italic;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 180ms ease, border-color 180ms ease, transform 180ms ease;
}
.wheel-info-btn:hover {
  background: rgba(255, 214, 138, 0.16);
  border-color: rgba(255, 214, 138, 0.9);
  transform: scale(1.08);
}
.wheel-info-btn[aria-expanded="true"] {
  background: rgba(255, 214, 138, 0.22);
  border-color: var(--gold-bright, #ffd94d);
}

/* The odds, when asked for. */
.wheel-odds[hidden] { display: none; }
.wheel-odds {
  margin-top: 12px;
  animation: wheelOddsIn 240ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@keyframes wheelOddsIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

/* SPIN — icon only.
   A wordless button has to be unmistakable, so it is large, gold, and
   carries a drawn arrow rather than a glyph that depends on a font. */
.wheel-spin-btn {
  position: relative;
  width: 66px;
  height: 66px;
  padding: 0;
  border-radius: 50%;
  font-size: 0;              /* no text node, and none can leak in */
  display: grid;
  place-items: center;
}
.wheel-spin-btn::before {
  content: '';
  width: 0;
  height: 0;
  /* A right-pointing triangle, nudged so its optical centre sits on the
     button's real centre — a centred triangle always looks left-heavy. */
  margin-left: 6px;
  border-left: 20px solid currentColor;
  border-top: 13px solid transparent;
  border-bottom: 13px solid transparent;
}
.wheel-spin-btn:disabled::before { opacity: 0.4; }

/* CLOSE — the multiplication sign, matched to the info button. */
.wheel-close {
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 50%;
  font-size: 14px;
  line-height: 1;
  display: grid;
  place-items: center;
  /* Above the claim panel, which is `position: absolute; inset: 0;
     z-index: 6` with a 90%-opaque background — so it covered this button
     completely while a prize was waiting to be claimed.
     closeWheel() has a deliberate branch for exactly that state: it pays
     an unclaimed prize out rather than discarding it, and its comment
     says "the panel must never be a room the player cannot leave". The
     CSS made that branch unreachable by click. The player was never
     truly stuck (the CLAIM button still worked), but the X was dead and
     the walk-away payout could not happen.
     position is required for z-index to apply at all. */
  position: relative;
  z-index: 7;
}

@media (prefers-reduced-motion: reduce) {
  .wheel-odds { animation: none; }
  .wheel-info-btn:hover { transform: none; }
}

/* The info button is positioned against the panel, which was not a
   positioned ancestor — without this it would anchor to the overlay and
   sit in the corner of the screen instead of the corner of the panel. */
.wheel-panel { position: relative; }

/* =====================================================================
   OUT OF SPINS — the popup
   ---------------------------------------------------------------------
   Running dry used to be a floating line that faded after 2.5 seconds,
   so the most consequential moment in the session was also the quietest.
   This has to be dismissed.
   ===================================================================== */

.nospins-overlay[hidden] { display: none; }
.nospins-overlay {
  position: fixed;
  inset: 0;
  z-index: 9500;
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(2, 1, 6, 0.78);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  animation: noSpinsVeil 220ms ease both;
}
@keyframes noSpinsVeil { from { opacity: 0; } to { opacity: 1; } }

.nospins-panel {
  width: min(24rem, 100%);
  /* Ceilinged and scrollable: the gift variant is taller, and on a short
     phone in landscape the buttons must never be pushed off-screen. */
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  padding: 26px 24px 22px;
  text-align: center;
  border-radius: var(--radius-md, 14px);
  background:
    radial-gradient(ellipse 80% 60% at 50% -10%, rgba(255, 214, 138, 0.16), transparent 70%),
    linear-gradient(180deg, #1a1030, #08050f);
  border: 2px solid var(--gold, #ffb800);
  box-shadow: 0 0 48px rgba(255, 184, 0, 0.28), 0 18px 60px rgba(0, 0, 0, 0.6);
  animation: noSpinsPop 320ms cubic-bezier(0.16, 1.06, 0.3, 1.4) both;
}
@keyframes noSpinsPop {
  from { opacity: 0; transform: translateY(14px) scale(0.94); }
  to   { opacity: 1; transform: none; }
}

.nospins-art img {
  width: 84px;
  height: 84px;
  object-fit: contain;
  filter: drop-shadow(0 4px 14px rgba(0, 0, 0, 0.6));
}
/* Drained: the energy icon greys out, because the popup is about NOT
   having it. It returns to full colour on the gift variant. */
.nospins-overlay:not(.is-gift) .nospins-art img {
  filter: grayscale(1) brightness(0.7) drop-shadow(0 4px 14px rgba(0, 0, 0, 0.6));
}

.nospins-title {
  margin: 12px 0 8px;
  font-family: 'Orbitron', sans-serif;
  font-size: 1.5rem;
  letter-spacing: 0.08em;
  color: var(--gold-bright, #ffd94d);
}
.nospins-body {
  margin: 0 auto 14px;
  max-width: 30ch;
  font-size: 0.94rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.82);
}

/* The gift, on the first time only. */
.nospins-gift[hidden] { display: none; }
.nospins-gift {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  margin: 0 0 16px;
  padding: 12px 8px;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(255, 214, 138, 0.18), rgba(255, 184, 0, 0.06));
  border: 1px solid rgba(255, 214, 138, 0.45);
  animation: noSpinsGiftIn 460ms cubic-bezier(0.16, 1.06, 0.3, 1.4) 220ms both;
}
@keyframes noSpinsGiftIn {
  from { opacity: 0; transform: scale(0.8); }
  to   { opacity: 1; transform: none; }
}
.nospins-gift-amount {
  font-family: 'Orbitron', sans-serif;
  font-size: 2rem;
  font-weight: 900;
  line-height: 1;
  color: var(--gold-bright, #ffd94d);
  text-shadow: 0 0 18px rgba(255, 214, 138, 0.6);
}
.nospins-gift-label {
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  color: rgba(255, 255, 255, 0.72);
}

.nospins-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.nospins-shop {
  width: 100%;
  padding: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
}
.nospins-dismiss {
  width: 100%;
  padding: 9px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-sm);
  background: transparent;
  color: rgba(255, 255, 255, 0.66);
  font-size: 0.86rem;
  letter-spacing: 0.08em;
  cursor: pointer;
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.nospins-dismiss:hover {
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
  border-color: rgba(255, 255, 255, 0.32);
}

@media (prefers-reduced-motion: reduce) {
  .nospins-overlay, .nospins-panel, .nospins-gift { animation: none; }
}
@media (max-width: 720px) {
  .nospins-overlay { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* =====================================================================
   BOOST TIMERS — above SHOP
   ---------------------------------------------------------------------
   Clocks only, in the spin cluster where the eye already is. What each
   boost DOES lives behind the `i`, so the strip stays a row of numbers
   rather than a paragraph the player reads once and never again.
   ===================================================================== */

.boost-timers[hidden] { display: none; }
.boost-timers {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  margin-bottom: 8px;
  animation: boostTimersIn 260ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@keyframes boostTimersIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.boost-timers-list {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
  justify-content: center;
  min-width: 0;
}

.boost-timer {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 7px 3px 4px;
  border-radius: var(--radius-pill);
  background: rgba(10, 6, 20, 0.72);
  border: 1px solid rgba(255, 214, 138, 0.34);
  font-size: 0.72rem;
  line-height: 1;
  color: rgba(255, 255, 255, 0.9);
  white-space: nowrap;
}
.boost-timer img {
  width: 15px;
  height: 15px;
  object-fit: contain;
}
.boost-timer b {
  font-variant-numeric: tabular-nums;   /* the row must not jitter as digits change */
  font-weight: 700;
  color: var(--gold-bright, #ffd94d);
}

/* The last fifteen seconds. */
.boost-timer.is-urgent {
  border-color: rgba(255, 90, 90, 0.7);
  animation: boostTimerUrgent 1s ease-in-out infinite;
}
.boost-timer.is-urgent b { color: #ff8a8a; }
@keyframes boostTimerUrgent {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 90, 90, 0); }
  50%      { box-shadow: 0 0 10px 1px rgba(255, 90, 90, 0.45); }
}

.boost-timers-info {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid rgba(255, 214, 138, 0.45);
  background: rgba(10, 6, 20, 0.72);
  color: var(--gold-bright, #ffd94d);
  font: italic 700 12px/1 'Georgia', serif;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 160ms ease, transform 160ms ease;
}
.boost-timers-info:hover { background: rgba(255, 214, 138, 0.2); transform: scale(1.1); }
.boost-timers-info[aria-expanded="true"] { background: rgba(255, 214, 138, 0.26); }

/* Opens UPWARD. The strip sits directly above SHOP and SPIN, so a panel
   dropping downward would cover the two controls the player is reaching
   for. */
.boost-timers-panel[hidden] { display: none; }
.boost-timers-panel {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 60;
  width: max-content;
  max-width: min(20rem, 78vw);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  text-align: left;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, #1b1130, #0a0614);
  border: 1px solid rgba(255, 214, 138, 0.45);
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.6);
  animation: boostPanelIn 200ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@keyframes boostPanelIn {
  from { opacity: 0; transform: translateX(-50%) translateY(6px); }
  to   { opacity: 1; transform: translateX(-50%); }
}

.boost-timers-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.boost-timers-row img {
  width: 22px;
  height: 22px;
  object-fit: contain;
  flex: none;
  margin-top: 1px;
}
.boost-timers-row-body {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.boost-timers-row-body b {
  font-size: 0.8rem;
  color: var(--gold-bright, #ffd94d);
}
.boost-timers-row-body span {
  font-size: 0.72rem;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.74);
}
.boost-timers-row-body em {
  font-style: normal;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.5);
}

@media (prefers-reduced-motion: reduce) {
  .boost-timers, .boost-timers-panel { animation: none; }
  .boost-timer.is-urgent { animation: none; }
  .boost-timers-info:hover { transform: none; }
}

@media (max-width: 720px) {
  /* The urgent pulse is a box-shadow repaint on a small element every
     frame; the red border already carries the message. */
  .boost-timer.is-urgent { animation: none; }
  .boost-timer { font-size: 0.68rem; padding: 2px 6px 2px 3px; }
  .boost-timer img { width: 13px; height: 13px; }
}

/* The blurb at the top of an item's info panel. The chance-table panels
   never had one because a chest's own name says what it is; an item's
   does not. */
.odds-blurb {
  margin: 0 0 14px;
  font-size: 0.9rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.82);
  text-align: center;
}

