/* =====================================================================
   WONDERLAND — timer banner and the spiral doorway
   ===================================================================== */
.alice-timer {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin: 0.5rem auto;
  padding: 8px 16px;
  max-width: 34rem;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, rgba(40, 10, 50, 0.95), rgba(15, 5, 30, 0.95));
  border: 2px solid #ff8ad8;
  box-shadow: 0 0 24px rgba(255, 138, 216, 0.45);
}
.alice-timer[hidden] { display: none !important; }

.alice-timer-mark {
  font-size: 1.2rem;
  color: #ff8ad8;
  transform: rotate(-12deg);
}
.alice-timer-text {
  font-family: 'Orbitron', sans-serif;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  color: #ffd6f2;
}
.alice-timer-text strong { color: #fff; font-size: 1rem; }

/* Levels won inside are WAITING, never granted — the wording and the
   styling both have to say "not yours yet". */
.alice-timer-levels,
#aliceTimerLevels {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  background: #ff8ad8;
  color: #2a0020;
  font-style: normal;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
}
#aliceTimerLevels[hidden] { display: none !important; }

.alice-timer-track {
  flex: 1 1 100%;
  height: 5px;
  border-radius: var(--radius-pill);
  background: rgba(0, 0, 0, 0.55);
  overflow: hidden;
}
.alice-timer-fill {
  height: 100%;
  width: 100%;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, #ff8ad8, var(--violet-mid));
  transition: width 1s linear;
}

/* ---- the spiral doorway ---- */
.spiral-transition {
  position: fixed;
  inset: 0;
  z-index: 12500;
  display: none;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 1.4rem;
  background: radial-gradient(circle at 50% 50%, rgba(60, 10, 70, 0.9), rgba(0, 0, 0, 0.98));
}
.spiral-transition.active { display: flex; }

/* The gif does the hypnosis; this spins and swells it so it reads as
   being pulled INTO rather than merely displayed. */
@keyframes spiralPull {
  0%   { opacity: 0; transform: scale(0.2) rotate(0deg); }
  25%  { opacity: 1; }
  100% { opacity: 1; transform: scale(3.4) rotate(760deg); }
}
.spiral-transition-gif {
  width: min(24rem, 70vw);
  height: min(24rem, 70vw);
  object-fit: contain;
  animation: spiralPull 2600ms cubic-bezier(0.4, 0, 0.6, 1) both;
}

@keyframes spiralWord {
  0%   { opacity: 0; letter-spacing: 0.6em; transform: scale(0.8); }
  35%  { opacity: 1; letter-spacing: 0.18em; transform: scale(1); }
  80%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.1); }
}
.spiral-transition-label {
  position: relative;
  z-index: 2;
  font-family: 'Orbitron', sans-serif;
  font-size: clamp(0.9rem, 3.6vw, 1.5rem);
  letter-spacing: 0.18em;
  color: #ffd6f2;
  text-shadow: 0 0 22px rgba(255, 138, 216, 0.9), 0 3px 8px rgba(0, 0, 0, 0.9);
  animation: spiralWord 2600ms ease-in-out both;
}

/* Everything behind the overlay tips and drains of colour while the
   spiral runs, so the machine itself appears to be going through. */
@keyframes hypnoTilt {
  0%   { filter: saturate(1) hue-rotate(0deg); transform: perspective(900px) rotateX(0) scale(1); }
  100% { filter: saturate(0.25) hue-rotate(70deg); transform: perspective(900px) rotateX(9deg) scale(0.94); }
}
body.hypnotised main.slot-machine {
  animation: hypnoTilt 2600ms ease-in-out both;
}

@media (prefers-reduced-motion: reduce) {
  .spiral-transition-gif,
  .spiral-transition-label,
  body.hypnotised main.slot-machine { animation-duration: 400ms; }
}

/* =====================================================================
   REWARD FLIGHT — tokens travelling from a claimed chest/gift to the
   HUD tile they are about to change.
   ===================================================================== */
@keyframes rewardFly {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.4) rotate(0deg); }
  12%  { opacity: 1; transform: translate(0, -18px) scale(1.15) rotate(-8deg); }
  100% {
    opacity: 0.15;
    transform: translate(var(--rfly-x, 0), var(--rfly-y, 0)) scale(0.42) rotate(22deg);
  }
}
.reward-fly {
  position: absolute;
  width: 34px;
  height: 34px;
  object-fit: contain;
  pointer-events: none;
  z-index: 5;
  opacity: 0;
  filter: drop-shadow(0 3px 7px rgba(0, 0, 0, 0.65));
  /* Eased so it leaves slowly, accelerates across, and arrives fast —
     a straight linear slide reads as a sticker being dragged. */
  animation: rewardFly 900ms cubic-bezier(0.55, 0, 0.35, 1) forwards;
}

/* =====================================================================
   CASTLE CLOSING WARNING
   ===================================================================== */
@keyframes terrorFinaleIn {
  0%   { opacity: 0; transform: translate(-50%, -24px) scale(0.9); }
  14%  { opacity: 1; transform: translate(-50%, 0) scale(1); }
  86%  { opacity: 1; transform: translate(-50%, 0) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -14px) scale(0.97); }
}
@keyframes terrorFinalePulse {
  0%, 100% { box-shadow: 0 0 22px 3px rgba(255, 40, 40, 0.5); }
  50%      { box-shadow: 0 0 40px 10px rgba(255, 40, 40, 0.85); }
}
.terror-finale {
  position: fixed;
  top: 14vh;
  left: 50%;
  z-index: 11900;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 12px 26px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, rgba(45, 0, 0, 0.97), rgba(18, 0, 0, 0.97));
  border: 2px solid #ff3b3b;
  pointer-events: none;
  opacity: 0;
}
.terror-finale[hidden] { display: none !important; }
.terror-finale.active {
  animation: terrorFinaleIn 2600ms ease-out forwards,
             terrorFinalePulse 700ms ease-in-out infinite;
}
.terror-finale-skull { font-size: 1.5rem; color: #ff6b6b; }
.terror-finale-text {
  font-family: 'Orbitron', sans-serif;
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  color: #ffd4d4;
}
.terror-finale-text strong { color: #fff; font-size: 1.05rem; }

@media (prefers-reduced-motion: reduce) {
  .reward-fly { animation-duration: 300ms; }
  .terror-finale.active { animation: terrorFinaleIn 2600ms ease-out forwards; }
}

/* =====================================================================
   CASTLE TRANSITION
   Covers the screen completely while the machine is swapped underneath.
   Layered: fog drifting, a vignette closing in, iris bars sweeping shut,
   and the terror art rising through it.
   ===================================================================== */
.terror-transition {
  position: fixed;
  inset: 0;
  z-index: 12800;
  display: none;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #05000a;
}
.terror-transition.active { display: flex; }

/* --- iris bars: what actually makes it opaque --- */
.terror-transition-bars {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
}
.terror-transition-bars span {
  flex: 1;
  background: linear-gradient(90deg, #12000c, #3a0010 45%, #12000c);
  transform: scaleX(0);
  transform-origin: left center;
}
.terror-transition-bars span:nth-child(even) { transform-origin: right center; }

.terror-transition.closing .terror-transition-bars span {
  animation: terrorBarIn 780ms cubic-bezier(0.7, 0, 0.3, 1) forwards;
}
.terror-transition.closing .terror-transition-bars span:nth-child(1) { animation-delay: 0ms; }
.terror-transition.closing .terror-transition-bars span:nth-child(2) { animation-delay: 60ms; }
.terror-transition.closing .terror-transition-bars span:nth-child(3) { animation-delay: 120ms; }
.terror-transition.closing .terror-transition-bars span:nth-child(4) { animation-delay: 180ms; }
.terror-transition.closing .terror-transition-bars span:nth-child(5) { animation-delay: 240ms; }
.terror-transition.closing .terror-transition-bars span:nth-child(6) { animation-delay: 300ms; }
@keyframes terrorBarIn { to { transform: scaleX(1); } }

/* Opening reverses it, and the bars hold at full width until then so
   nothing behind can peek through mid-swap. */
.terror-transition.opening .terror-transition-bars span {
  transform: scaleX(1);
  animation: terrorBarOut 640ms cubic-bezier(0.7, 0, 0.3, 1) forwards;
}
.terror-transition.opening .terror-transition-bars span:nth-child(2) { animation-delay: 70ms; }
.terror-transition.opening .terror-transition-bars span:nth-child(4) { animation-delay: 140ms; }
.terror-transition.opening .terror-transition-bars span:nth-child(6) { animation-delay: 210ms; }
@keyframes terrorBarOut { to { transform: scaleX(0); } }

/* --- drifting fog --- */
@keyframes terrorFog {
  0%   { transform: translateX(-25%) scale(1.3); opacity: 0; }
  30%  { opacity: 0.55; }
  100% { transform: translateX(25%) scale(1.6); opacity: 0.2; }
}
.terror-transition-fog {
  position: absolute;
  inset: -30%;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(ellipse 60% 40% at 30% 55%, rgba(150, 20, 40, 0.5), transparent 70%),
    radial-gradient(ellipse 50% 35% at 70% 45%, rgba(80, 0, 30, 0.55), transparent 70%);
}
.terror-transition.active .terror-transition-fog {
  animation: terrorFog 2400ms ease-out forwards;
}

/* --- vignette squeezing in --- */
@keyframes terrorVignette {
  0%   { box-shadow: inset 0 0 0 0 rgba(0, 0, 0, 0); }
  100% { box-shadow: inset 0 0 220px 90px rgba(0, 0, 0, 0.95); }
}
.terror-transition-vignette {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}
.terror-transition.closing .terror-transition-vignette {
  animation: terrorVignette 900ms ease-in forwards;
}

/* --- the art rising through the fog --- */
@keyframes terrorArtRise {
  0%   { opacity: 0; transform: translateY(70px) scale(0.55); filter: blur(9px); }
  45%  { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
  100% { opacity: 0.9; transform: translateY(-10px) scale(1.06); }
}
.terror-transition-art {
  position: relative;
  z-index: 4;
  width: min(15rem, 46vw);
  filter: drop-shadow(0 0 34px rgba(255, 30, 30, 0.8));
  opacity: 0;
}
.terror-transition.active .terror-transition-art {
  animation: terrorArtRise 1400ms cubic-bezier(0.2, 0.9, 0.3, 1) forwards;
}

@keyframes terrorLabelIn {
  0%   { opacity: 0; letter-spacing: 0.55em; }
  100% { opacity: 1; letter-spacing: 0.16em; }
}
.terror-transition-label {
  position: absolute;
  z-index: 5;
  bottom: 22%;
  left: 50%;
  transform: translateX(-50%);
  width: 90%;
  text-align: center;
  font-family: 'Orbitron', sans-serif;
  font-size: clamp(0.85rem, 3.4vw, 1.35rem);
  letter-spacing: 0.16em;
  color: #ff6b6b;
  text-shadow: 0 0 20px rgba(255, 40, 40, 0.9), 0 3px 8px #000;
  opacity: 0;
}
.terror-transition.active .terror-transition-label {
  animation: terrorLabelIn 900ms 400ms ease-out forwards;
}

/* The machine itself judders as the Castle takes hold. */
@keyframes terrorShake {
  0%, 100% { transform: translate(0, 0); }
  20% { transform: translate(-6px, 3px); }
  40% { transform: translate(5px, -4px); }
  60% { transform: translate(-4px, -3px); }
  80% { transform: translate(6px, 2px); }
}
body.terror-shaking main.slot-machine {
  animation: terrorShake 260ms linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  body.terror-shaking main.slot-machine { animation: none; }
  .terror-transition-fog,
  .terror-transition-art,
  .terror-transition-label { animation-duration: 200ms !important; }
}


/* =====================================================================
   WONDERLAND'S AMBIENT LAYER
   ---------------------------------------------------------------------
   Built by renderWonderlandBackdrop() (machine-render.js) on the same
   pattern as the Castle's: one fixed layer on <body>, inset from the top
   so nothing drifts up through the site nav, everything animated in CSS.

   The pieces answer alice.jpg specifically. The artwork already scatters
   four-pointed sparkles across its dark left half, so the sparkles here
   are the same shape and read as more of the picture rather than as an
   effect laid over it; the cards and the watches are the two things the
   scene is about that it does not already show in motion.
   ===================================================================== */
.wonderland-backdrop {
  position: fixed;
  top: 88px;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.alice-bg-piece {
  position: absolute;
  will-change: transform, opacity;
}

/* One slow violet bloom, low and left. The photograph's own bloom is
   high and right, behind the cast; this balances it without competing. */
.alice-bg-bloom {
  left: -12%;
  bottom: -22%;
  width: 62vmin;
  height: 62vmin;
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(168, 85, 247, 0.22) 0%,
    rgba(123, 44, 191, 0.10) 42%,
    transparent 70%);
  filter: blur(14px);
  animation: aliceBloom 17s ease-in-out infinite;
}
@keyframes aliceBloom {
  0%, 100% { transform: scale(1)    translateY(0);     opacity: 0.75; }
  50%      { transform: scale(1.12) translateY(-3vmin); opacity: 1; }
}

/* A four-pointed star, drawn with a clip-path rather than a glyph so it
   matches the ones painted into the artwork. */
.alice-bg-spark {
  width: var(--spark-size, 8px);
  height: var(--spark-size, 8px);
  background: #fff;
  clip-path: polygon(50% 0%, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0% 50%, 42% 42%);
  filter: drop-shadow(0 0 5px rgba(214, 190, 255, 0.9));
  opacity: 0;
  animation: aliceSpark ease-in-out infinite;
}
@keyframes aliceSpark {
  0%, 100% { opacity: 0;    transform: scale(0.4) rotate(0deg); }
  50%      { opacity: 0.95; transform: scale(1)   rotate(45deg); }
}

/* Falling cards. They tumble on two axes at once — a card that only
   rotated in the plane of the screen would read as a spinning sticker. */
.alice-bg-card {
  top: -14%;
  width: var(--card-w, 22px);
  aspect-ratio: 5 / 7;
  display: grid;
  place-items: center;
  border-radius: 3px;
  background: linear-gradient(160deg, #fffdf5, #e6dcc8);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(0, 0, 0, 0.18);
  font-size: calc(var(--card-w, 22px) * 0.5);
  line-height: 1;
  opacity: 0.62;
  animation: aliceCardFall linear infinite;
}
.alice-bg-card.is-red   { color: #d2264b; }
.alice-bg-card.is-black { color: #1d1a2b; }

@keyframes aliceCardFall {
  0% {
    transform: translate3d(0, 0, 0) rotate(0deg) rotateY(0deg);
    opacity: 0;
  }
  8%   { opacity: 0.62; }
  92%  { opacity: 0.62; }
  100% {
    transform: translate3d(var(--card-drift, 0px), 118vh, 0) rotate(420deg) rotateY(540deg);
    opacity: 0;
  }
}

/* The White Rabbit's watch, drifting rather than falling. */
.alice-bg-watch {
  bottom: -12%;
  color: #ffd94d;
  text-shadow: 0 0 12px rgba(255, 217, 77, 0.55);
  opacity: 0.4;
  animation: aliceWatchRise linear infinite;
}
@keyframes aliceWatchRise {
  0%   { transform: translateY(0) rotate(-12deg); opacity: 0; }
  12%  { opacity: 0.4; }
  88%  { opacity: 0.4; }
  100% { transform: translateY(-118vh) rotate(14deg); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .alice-bg-bloom,
  .alice-bg-spark,
  .alice-bg-card,
  .alice-bg-watch { animation: none; }
  .alice-bg-card,
  .alice-bg-watch { display: none; }
  .alice-bg-spark { opacity: 0.7; }
}

/* Ambient motion is the first thing to go when the device is struggling,
   exactly as the Castle's bats and skulls do. */
.lean-fx .alice-bg-card,
.lean-fx .alice-bg-watch { display: none; }

/* =====================================================================
   WONDERLAND: THE "XP IS LOST IN TRANSPORT" CARD
   ---------------------------------------------------------------------
   Replaces a gain chip that fired on every winning spin of the visit.
   It waits to be dismissed rather than timing out, because the thing it
   is explaining is a rule, and a rule the player missed is one they will
   keep being surprised by.

   Anchored low and centred: high enough to read, clear of the reels so
   it does not cover the result it is explaining.
   ===================================================================== */
.wl-notice {
  position: fixed;
  left: 50%;
  bottom: clamp(84px, 14vh, 160px);
  transform: translateX(-50%);
  z-index: 12400;
  pointer-events: none;
  width: min(30rem, 92vw);
}
.wl-notice-card {
  pointer-events: auto;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "art body" "art btn";
  align-items: center;
  gap: 4px 14px;
  padding: 14px 16px;
  border-radius: 16px;
  border: 2px solid #ff8ad8;
  background: linear-gradient(180deg, rgba(46, 12, 58, 0.97), rgba(24, 6, 34, 0.98));
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6), 0 0 26px rgba(255, 138, 216, 0.35);
  opacity: 0;
  transform: translateY(14px) scale(0.96);
  transition: opacity 260ms ease, transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
.wl-notice.open .wl-notice-card { opacity: 1; transform: none; }

.wl-notice-art {
  grid-area: art;
  width: 62px;
  height: 62px;
  object-fit: contain;
  filter: drop-shadow(0 0 10px rgba(255, 138, 216, 0.6));
}
.wl-notice-body { grid-area: body; min-width: 0; }
.wl-notice-body b {
  display: block;
  font-family: "Orbitron", sans-serif;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: #ffd6f2;
}
.wl-notice-body p {
  margin: 3px 0 0;
  font-size: 0.76rem;
  line-height: 1.35;
  color: #e6c9f5;
}
.wl-notice-btn {
  grid-area: btn;
  justify-self: start;
  margin-top: 8px;
  min-height: 38px;
  padding: 0 20px;
  border-radius: 999px;
  border: 0;
  cursor: pointer;
  font-family: "Orbitron", sans-serif;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  color: #3d0a2e;
  background: linear-gradient(180deg, #ffc2ec, #ff8ad8);
  box-shadow: 0 3px 0 #b8479a;
}
.wl-notice-btn:hover { filter: brightness(1.08); }
.wl-notice-btn:active { transform: translateY(2px); box-shadow: 0 1px 0 #b8479a; }

@media (max-width: 720px) {
  .wl-notice { bottom: clamp(70px, 12vh, 120px); }
  .wl-notice-art { width: 50px; height: 50px; }
  .wl-notice-body p { font-size: 0.72rem; }
}
@media (prefers-reduced-motion: reduce) {
  .wl-notice-card { transition: none; }
}

/* =====================================================================
   SEASONAL MACHINE CARDS
   Sit under the rotation card in the right rail. Two states: in season
   (lit, in the rotation) and out (dim, shop only).
   ===================================================================== */
.season-cards {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.season-card {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  border-radius: var(--radius-sm, 8px);
  border: 1px solid var(--border-dim, rgba(255, 255, 255, 0.14));
  background: rgba(0, 0, 0, 0.34);
  opacity: 0.72;
}
.season-card.is-open {
  opacity: 1;
  border-color: rgba(255, 138, 60, 0.75);
  box-shadow: 0 0 16px rgba(255, 138, 60, 0.25);
}
.season-card[data-key="christmas"].is-open {
  border-color: rgba(120, 230, 140, 0.75);
  box-shadow: 0 0 16px rgba(120, 230, 140, 0.25);
}
.season-card-art { width: 34px; height: 34px; object-fit: contain; }
.season-card-body { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.season-card-body b {
  font-family: "Orbitron", sans-serif;
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  color: var(--panel-text, #eaf6ff);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.season-card-state { font-size: 0.54rem; letter-spacing: 0.1em; color: var(--text-dim); }
.season-card.is-open .season-card-state { color: #ffb060; }
.season-card[data-key="christmas"].is-open .season-card-state { color: #8fe89f; }
.season-week { font-size: 0.54rem; color: var(--text-dim); }
.season-card-time {
  font-family: "Orbitron", sans-serif;
  font-size: 0.74rem;
  font-weight: 800;
  color: var(--panel-text, #eaf6ff);
  white-space: nowrap;
}

@media (max-width: 720px) {
  .season-card { grid-template-columns: 26px 1fr auto; padding: 5px 8px; gap: 7px; }
  .season-card-art { width: 26px; height: 26px; }
  .season-week { display: none; }
}

/* --- THE SEASONAL CARDS GET A SCENE BEHIND THEM ----------------------
   They were a flat dark panel with a coloured border, which read as a
   disabled button rather than as a countdown to something. Each card now
   carries its own season behind the text: pumpkin orange fading up out
   of the dark for Halloween, a cold spruce-green for Christmas, with the
   art sitting in its own lit well on the left.

   The gradient is drawn on the CARD and the text sits above it, so the
   countdown stays legible while the panel is unmistakably themed. */
.season-card {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.season-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.55;
  transition: opacity 300ms ease;
}
.season-card.is-open::before { opacity: 1; }

.season-card[data-key="halloween"]::before {
  background:
    radial-gradient(ellipse 70% 130% at 12% 50%, rgba(255, 138, 30, 0.42), transparent 62%),
    linear-gradient(100deg, #2a1206 0%, #1b0a14 55%, #120616 100%);
}
.season-card[data-key="christmas"]::before {
  background:
    radial-gradient(ellipse 70% 130% at 12% 50%, rgba(120, 230, 140, 0.34), transparent 62%),
    linear-gradient(100deg, #07281c 0%, #0b1a2a 55%, #0a1020 100%);
}

/* A lit well for the art, so the pumpkin and the Santa read against the
   scene rather than floating on it. */
.season-card-art {
  border-radius: 50%;
  padding: 2px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.16), transparent 70%);
}
.season-card[data-key="halloween"].is-open .season-card-art {
  filter: drop-shadow(0 0 7px rgba(255, 150, 40, 0.85));
}
.season-card[data-key="christmas"].is-open .season-card-art {
  filter: drop-shadow(0 0 7px rgba(130, 240, 150, 0.85));
}

/* Out of season the border was the only thing saying which card was
   which. Now it agrees with the scene behind it. */
.season-card[data-key="halloween"] { border-color: rgba(255, 138, 30, 0.42); }
.season-card[data-key="christmas"] { border-color: rgba(120, 230, 140, 0.38); }

/* --- THE JACKPOT LADDER, NOW IN THE LEFT RAIL ------------------------
   The right rail sized it against a column that also held the rotation
   card; the left one is narrower and has the menu above it, so it takes
   the full width it is given and keeps its own top margin. */
.jackpot-banner-left {
  width: 100%;
  margin-top: 8px;
}

/* --- THE HOLD NOTICE -------------------------------------------------
   Reuses the Wonderland card's shape and swaps the palette to the hold
   button's own red, so the thing being explained and the explanation
   look like they belong to each other. */
.hold-notice .wl-notice-card {
  border-color: #ff5a63;
  background: linear-gradient(180deg, rgba(58, 12, 18, 0.97), rgba(30, 6, 10, 0.98));
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6), 0 0 26px rgba(255, 90, 99, 0.32);
}
.hold-notice .wl-notice-body b { color: #ffd9dc; }
.hold-notice .wl-notice-body p { color: #f0c9cd; }
.hold-notice .wl-notice-btn {
  color: #3d0a0f;
  background: linear-gradient(180deg, #ffc2c6, #ff5a63);
  box-shadow: 0 3px 0 #b8474f;
}
.hold-notice .wl-notice-btn:active { box-shadow: 0 1px 0 #b8474f; }
/* The HOLD chip, the same red pill the button wears. */
.hold-notice-art {
  grid-area: art;
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  border-radius: 14px;
  font-family: "Orbitron", sans-serif;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: #fff;
  background: linear-gradient(180deg, #ff5a63, #d21421 50%, #7a0710);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.35), 0 3px 8px rgba(0, 0, 0, 0.5);
}
@media (max-width: 720px) {
  .hold-notice-art { width: 50px; height: 50px; font-size: 0.62rem; }
}

/* --- THE RETURN CARD -------------------------------------------------
   Bigger and warmer than the hold notice, because it is a reward screen
   rather than a correction: the visit paid out, and this is the door back
   to the player's own machine. */
.return-card {
  position: fixed;
  inset: 0;
  /* Above every transition it can follow — the spiral is 12500 and the
     Castle vortex 12800 — because the card is shown as one of those is
     still tearing down. At 1400 (where this started) it opened behind
     them and the player saw a dimmer with nothing in it. Stays under the
     20500 machine transition, which must cover everything. */
  z-index: 12900;
  display: grid;
  place-items: center;
  padding: 20px;
  background: radial-gradient(ellipse at center, rgba(24, 10, 42, 0.82), rgba(4, 2, 10, 0.94));
  opacity: 0;
  transition: opacity 0.3s ease;
}
.return-card.open { opacity: 1; }
.return-card[hidden] { display: none; }

/* A slow rotating shaft of light behind the panel. Sits under it and is
   clipped by the overlay, so it never adds scroll. */
.return-card-glow {
  position: absolute;
  width: min(120vmin, 900px);
  height: min(120vmin, 900px);
  background: conic-gradient(from 0deg,
    rgba(255, 214, 122, 0.22) 0deg, transparent 26deg,
    rgba(255, 214, 122, 0.18) 90deg, transparent 118deg,
    rgba(255, 214, 122, 0.22) 180deg, transparent 206deg,
    rgba(255, 214, 122, 0.18) 270deg, transparent 298deg);
  animation: returnCardSweep 18s linear infinite;
  pointer-events: none;
}
@keyframes returnCardSweep { to { transform: rotate(360deg); } }

.return-card-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: min(420px, 92vw);
  padding: 26px 26px 24px;
  text-align: center;
  border-radius: 22px;
  border: 2px solid #ffd67a;
  background: linear-gradient(180deg, rgba(40, 20, 66, 0.98), rgba(16, 8, 30, 0.99));
  box-shadow: 0 26px 60px rgba(0, 0, 0, 0.7), 0 0 40px rgba(255, 214, 122, 0.28),
    inset 0 1px 0 rgba(255, 255, 255, 0.16);
  transform: translateY(18px) scale(0.94);
  transition: transform 0.42s cubic-bezier(0.16, 1, 0.3, 1);
}
.return-card.open .return-card-panel { transform: none; }

.return-card-kicker {
  font-family: "Orbitron", sans-serif;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: #c9a6ff;
  text-transform: uppercase;
}
/* The art sits in its own lit frame so a symbol with a dark background
   still reads against the panel. */
.return-card-frame {
  display: grid;
  place-items: center;
  width: 118px;
  height: 118px;
  border-radius: 18px;
  border: 1px solid rgba(255, 214, 122, 0.4);
  background: radial-gradient(circle at 50% 40%, rgba(255, 214, 122, 0.22), rgba(0, 0, 0, 0.45));
  box-shadow: inset 0 0 26px rgba(255, 214, 122, 0.2);
}
.return-card-art {
  width: 88px;
  height: 88px;
  object-fit: contain;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.6));
}
.return-card-art[hidden] { display: none; }

.return-card-name {
  font-family: "Orbitron", sans-serif;
  font-size: 1.7rem;
  line-height: 1.1;
  color: #ffe9b0;
  text-shadow: 0 0 18px rgba(255, 214, 122, 0.55);
}
.return-card-sub {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.4;
  color: #d9c8f0;
}
.return-card-btn {
  margin-top: 6px;
  width: 100%;
  padding: 13px 18px;
  border: 0;
  border-radius: 12px;
  cursor: pointer;
  font-family: "Orbitron", sans-serif;
  font-size: 0.95rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  color: #3a2405;
  background: linear-gradient(180deg, #ffe9b0, #ffc247 55%, #f0a41f);
  box-shadow: 0 4px 0 #b87a12, 0 8px 20px rgba(0, 0, 0, 0.45);
  animation: returnCardBtnPulse 1.8s ease-in-out infinite;
}
.return-card-btn:hover { filter: brightness(1.07); }
.return-card-btn:active {
  transform: translateY(3px);
  box-shadow: 0 1px 0 #b87a12, 0 4px 12px rgba(0, 0, 0, 0.45);
  animation: none;
}
@keyframes returnCardBtnPulse {
  0%, 100% { box-shadow: 0 4px 0 #b87a12, 0 8px 20px rgba(0, 0, 0, 0.45), 0 0 0 rgba(255, 194, 71, 0); }
  50% { box-shadow: 0 4px 0 #b87a12, 0 8px 20px rgba(0, 0, 0, 0.45), 0 0 24px rgba(255, 194, 71, 0.55); }
}
@media (prefers-reduced-motion: reduce) {
  .return-card-glow, .return-card-btn { animation: none; }
}
@media (max-width: 720px) {
  .return-card-panel { padding: 22px 18px 20px; gap: 10px; }
  .return-card-frame { width: 96px; height: 96px; }
  .return-card-art { width: 72px; height: 72px; }
  .return-card-name { font-size: 1.4rem; }
}

/* --- THE SERVER ERROR PANEL ------------------------------------------
   Above everything except the machine transition (20500), because a
   server fault is the one message that must not be painted over: it is
   shown precisely when the rest of the UI can no longer be trusted. */
.server-error-overlay {
  position: fixed;
  inset: 0;
  z-index: 19000;
  display: none;
  place-items: center;
  padding: 20px;
  background: rgba(4, 2, 8, 0.92);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.server-error-overlay.open { display: grid; }

.server-error-modal {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  width: min(420px, 92vw);
  padding: 28px 26px 24px;
  text-align: center;
  border-radius: 20px;
  border: 2px solid #ff6b74;
  background: linear-gradient(180deg, rgba(46, 14, 20, 0.98), rgba(20, 6, 10, 0.99));
  box-shadow: 0 26px 60px rgba(0, 0, 0, 0.72), 0 0 40px rgba(255, 107, 116, 0.26);
  animation: serverErrorIn 0.34s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes serverErrorIn {
  from { opacity: 0; transform: translateY(16px) scale(0.95); }
  to   { opacity: 1; transform: none; }
}

.server-error-icon {
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 50%;
  color: #ff8a92;
  background: rgba(255, 107, 116, 0.12);
  border: 1px solid rgba(255, 107, 116, 0.35);
}
.server-error-icon svg { width: 30px; height: 30px; }

.server-error-title {
  margin: 0;
  font-family: "Orbitron", sans-serif;
  font-size: 1.25rem;
  line-height: 1.2;
  color: #ffd9dc;
}
/* 1rem and a real line-height: this is a sentence to be READ, which is
   the whole reason it is not going through the 5rem win banner. */
.server-error-body {
  margin: 0;
  font-size: 1rem;
  line-height: 1.5;
  color: #f0c9cd;
}
.server-error-btn {
  margin-top: 4px;
  width: 100%;
  padding: 13px 18px;
  border: 0;
  border-radius: 12px;
  cursor: pointer;
  font-family: "Orbitron", sans-serif;
  font-size: 0.95rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  color: #3d0a0f;
  background: linear-gradient(180deg, #ffc2c6, #ff5a63);
  box-shadow: 0 4px 0 #b8474f, 0 8px 20px rgba(0, 0, 0, 0.45);
}
.server-error-btn:hover { filter: brightness(1.07); }
.server-error-btn:active {
  transform: translateY(3px);
  box-shadow: 0 1px 0 #b8474f;
}
@media (max-width: 720px) {
  .server-error-modal { padding: 22px 18px 20px; }
  .server-error-title { font-size: 1.1rem; }
  .server-error-body { font-size: 0.94rem; }
}
@media (prefers-reduced-motion: reduce) {
  .server-error-modal { animation: none; }
}
