/* ============================================================
   screens.css  -  the layout of the screens:
     1. Title (the character select and Collection are in menus.css)   2. Shared bits   3. Map   4. Rewards   5. Battle
   Phone layouts are handled at the bottom in @media rules.
   ============================================================ */

/* ============ 1. TITLE ============ */
.title {
  font-size: clamp(3.4rem, 15vw, 6.5rem);
  line-height: 0.95;
  font-weight: 900;
  color: var(--gold);
  -webkit-text-stroke: 0.09em var(--blue);
  paint-order: stroke fill;
  margin: 10px 0 22px;
}
.title small {
  display: block;
  margin-top: 0.45em;
  font-family: var(--pixel-font); font-synthesis-weight: none;   /* in the game's pixel font, with a hard outline in the logo's dark blue */
  font-weight: 400;
  font-size: clamp(0.75rem, 3vw, 1.1rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff8e0;
  -webkit-text-stroke: 0;
  text-shadow:
    2px 0 0 #14275e, -2px 0 0 #14275e, 0 2px 0 #14275e, 0 -2px 0 #14275e,
    2px 2px 0 #14275e, -2px 2px 0 #14275e, 2px -2px 0 #14275e, -2px -2px 0 #14275e,
    0 5px 0 #0d1a44;
  transform: none;
  animation: subtitleIn 0.8s ease-out both 0.7s;
}

/* the pixel logo (js/logo.js, a canvas a letter): letters bounce in one by one, then a slow wave with a shine
   rolls through them; the "o" is a Poké Ball that wobbles like a catch */
.title-logo { display: inline-flex; flex-direction: column; align-items: center; filter: drop-shadow(0 0 22px rgba(255, 214, 110, 0.28)); }
.tl-row { display: inline-flex; align-items: flex-end; }
.tl-small { margin-bottom: -0.04em; }
.tl canvas { display: block; image-rendering: pixelated; }
.tl-ball canvas { transform-origin: 50% 85%; animation: ballWobble 3.2s ease-in-out infinite 1.4s; }
.tl {
  display: inline-block;
  animation:
    letterIn 0.6s cubic-bezier(0.2, 1.6, 0.4, 1) both calc(var(--i) * 80ms),
    letterWave 3.2s ease-in-out infinite calc(1s + var(--i) * 0.14s);
}
.pokeball {
  position: relative;
  display: inline-block;
  width: 0.6em;
  height: 0.6em;
  margin: 0 0.02em;
  border-radius: 50%;
  border: 0.07em solid var(--blue);
  background: linear-gradient(180deg, #ff4a3d 0 44%, #1b1f3a 44% 56%, #fff 56%);
  box-shadow: 0 0.03em 0 #1e3a80, 0 0.06em 0 #14275e, 0 0.09em 0 #0d1a44, inset -0.06em -0.06em 0 rgba(0, 0, 0, 0.18);
  animation: ballWobble 3.2s ease-in-out infinite 1.4s;
}
.pokeball::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 0.2em;
  height: 0.2em;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: #fff;
  border: 0.045em solid #1b1f3a;
}
@keyframes letterIn {
  from { opacity: 0; transform: translateY(-0.6em) scale(0.4); }
  to   { opacity: 1; transform: none; }
}
@keyframes letterWave {
  0%, 100% { transform: translateY(0); filter: brightness(1); }
  18%      { transform: translateY(-0.07em); filter: brightness(1.3); }
  36%      { transform: translateY(0); filter: brightness(1); }
}
@keyframes ballWobble {
  0%, 55%, 100% { transform: rotate(0); }
  64% { transform: rotate(-22deg); }
  74% { transform: rotate(16deg); }
  84% { transform: rotate(-8deg); }
  92% { transform: rotate(3deg); }
}
@keyframes subtitleIn {
  from { opacity: 0; letter-spacing: 0.3em; }
  to   { opacity: 1; letter-spacing: 0.08em; }
}
@media (prefers-reduced-motion: reduce) {
  .tl, .tl-ball canvas, .pokeball, .title small { animation: none; }
}

/* ---------- title screen (js/title.js): a Gold/Silver-style night sky over the start screen ---------- */
.title-screen {
  --ground: 110px;           /* set by title.js to match the ledge painted on the canvas */
  position: fixed;
  inset: 0;
  z-index: 60;
  overflow: hidden;
  cursor: pointer;
  background: #0a0c26;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
body.titling { overflow: hidden; }
.title-sky { position: absolute; inset: 0; width: 100%; height: 100%; }
.title-center {
  position: absolute;
  inset: 0 0 var(--ground);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(22px, 6vh, 56px);
  padding: 0 16px 6vh;
  text-align: center;
}
.title-big { margin: 0; font-size: clamp(3.8rem, 18vw, 8rem); }
.press-start {
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  padding: 6px 10px;
  border: 0;
  background: none;
  color: #fff;
  font: 1rem/1 var(--pixel-font);
  font-synthesis-weight: none;
  letter-spacing: 0.12em;
  text-shadow: 3px 3px 0 #1c1d4e;
  cursor: pointer;
  opacity: 0;
}
.press-start:focus-visible { outline: 2px dashed var(--gold); outline-offset: 6px; }
/* no words under the shut Pokédex (the user's call, 2026-10-08: its pulsing power button says it); the button stays for keys and screen readers */
.press-start { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.title-screen.powering .press-start { visibility: hidden; }

/* the smooth light over the pixel sky (js/title-light.js), and the dark the shut Pokédex lies in until it's on */
.title-light { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.title-veil {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(ellipse at 50% 46%, rgba(6, 8, 26, 0.5), rgba(3, 4, 14, 0.86) 75%);
  transition: opacity 1.6s ease;
}
.title-screen.powering .title-veil { opacity: 0.72; }
.title-screen.menu .title-veil { opacity: 0; }
.title-center { z-index: 2; }
.title-screen:not(.menu) .title-big { display: none; }

/* the shut Pokédex before the first tap (powerOn() in js/title.js): its power button pulses; a tap presses it, the LED
   turns green, the cover swings open on its left hinge and the screen flickers on with the logo and a hello */
.title-dex {
  position: relative; display: flex; flex-direction: column; gap: 8px; width: clamp(200px, 58vw, 250px); aspect-ratio: 10 / 13;
  padding: 10px 12px 14px; border-radius: 22px;
  background: linear-gradient(180deg, var(--shell-hi), var(--shell) 40%, var(--shell-lo));
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset 6px 0 0 rgba(255, 255, 255, 0.08), 0 20px 40px rgba(0, 0, 0, 0.55), 0 0 70px rgba(130, 160, 255, 0.16);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  animation: tdxFloat 4s ease-in-out infinite;
}
.title-screen.menu .title-dex:not(.away), .title-dex.gone { display: none; }
@keyframes tdxFloat { 50% { transform: translateY(-6px); } }
.tdx-top { flex: none; display: flex; align-items: center; gap: 7px; height: 40px; }
.tdx-top .pdx-lens { width: 32px; height: 32px; border-width: 3px; }
.tdx-glass {
  flex: 1; display: flex; padding: 7px; border-radius: 10px 10px 10px 24px;
  background: #e4e4ea; box-shadow: inset 0 0 0 3px var(--shell-rim), inset 0 -4px 0 rgba(0, 0, 0, 0.14);
}
.tdx-screen {
  position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  overflow: hidden; border: 3px solid #2a2a30; border-radius: 5px 5px 5px 18px; background: #0a1020; text-align: center;
}
.tdx-screen > * { opacity: 0; }
.tdx-buddy { width: 62%; max-width: 150px; aspect-ratio: 1; object-fit: contain; image-rendering: pixelated; filter: drop-shadow(0 4px 0 rgba(0, 0, 0, 0.3)); }
.tdx-buddy:not([src]) { visibility: hidden; }
.title-dex.open .tdx-screen > .tdx-buddy { animation: tdxShow 0.4s ease-out forwards 1s, tdxBuddyHop 0.45s ease-out 1.4s; }
@keyframes tdxBuddyHop { 40% { translate: 0 -12px; } }
.tdx-hello { min-height: 1em; font-size: 0.75rem; letter-spacing: 1px; color: #b6f08e; }
.tdx-cover {
  position: absolute; left: 0; right: 0; top: 58px; bottom: 0; z-index: 2; border-radius: 0 0 22px 22px;
  transform-origin: left center; backface-visibility: hidden;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.12), transparent 40%), linear-gradient(180deg, var(--shell-hi), var(--shell) 45%, var(--shell-fold));
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset -10px 0 0 rgba(0, 0, 0, 0.12);
}
/* the classic yellow chevron on the cover */
.tdx-cover::before {
  content: ''; position: absolute; left: 50%; top: 10%; width: 52%; height: 16%; translate: -50% 0;
  background: linear-gradient(180deg, #ffe36b, #e8b818); clip-path: polygon(0 0, 100% 0, 88% 100%, 12% 100%);
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.2); opacity: 0.9;
}
.tdx-led {
  position: absolute; top: 12px; right: 16px; width: 11px; height: 11px; border-radius: 50%;
  background: #ff5a5a; box-shadow: inset 0 0 0 2px var(--shell-deep); animation: tdxStandby 2.4s ease-in-out infinite;
}
@keyframes tdxStandby { 50% { background: #6a1e22; } }
/* the lock-screen clock between the chevron and the power button (runClock() in js/title.js) */
.tdx-clock {
  position: absolute; left: 50%; top: 33%; translate: -50% 0; width: 62%;
  display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto auto; align-items: center; column-gap: 7px; row-gap: 3px;
  padding: 6px 9px 5px; border-radius: 7px;
  background: linear-gradient(180deg, #c8e2a0, #a8c97e); color: #1f3a14;
  box-shadow: inset 0 0 0 2px var(--shell-deep), inset 0 3px 4px rgba(0, 0, 0, 0.18), 0 1px 0 rgba(255, 255, 255, 0.18);
}
.tdx-sky { grid-row: 1 / 3; width: 26px; height: 26px; border-radius: 50%; background: #2a4a70; display: grid; place-items: center; }
.tdx-clock[data-time="day"] .tdx-sky { background: #5aa8e8; }
.tdx-clock[data-time="dawn"] .tdx-sky { background: linear-gradient(180deg, #8a7ad0, #ffb0a0); }
.tdx-clock[data-time="dusk"] .tdx-sky { background: linear-gradient(180deg, #4a3a8a, #e8708a); }
.tdx-clock[data-time="night"] .tdx-sky { background: #1a2450; }
.tdx-sky svg { width: 20px; height: 20px; display: block; }
.tdx-time { font-size: clamp(0.8rem, 4vw, 0.95rem); line-height: 1; letter-spacing: 1px; text-align: center; }
.tdx-date { font-size: 0.75rem; line-height: 1; letter-spacing: 1px; text-align: center; color: #3e5e2a; }
.tdx-power {
  position: absolute; left: 50%; bottom: 11%; width: 58px; height: 58px; translate: -50% 0; border-radius: 50%;
  background: radial-gradient(circle at 38% 32%, #e6f8ff 0 10%, #5ec8ff 24%, #1f78c8 72%); border: 4px solid #fff;
  box-shadow: 0 0 0 3px var(--shell-rim), 0 4px 0 var(--shell-deep);
  animation: tdxPulse 1.8s ease-out infinite; cursor: pointer;
  transition: translate 0.08s, box-shadow 0.2s;
}
.tdx-power::before { content: ''; position: absolute; left: 50%; top: 20%; width: 4px; height: 32%; translate: -50% 0; border-radius: 2px; background: #fff; }
.tdx-power::after { content: ''; position: absolute; inset: 28%; border-radius: 50%; border: 4px solid #fff; border-top-color: transparent; }
@keyframes tdxPulse {
  0%   { box-shadow: 0 0 0 3px var(--shell-rim), 0 4px 0 var(--shell-deep), 0 0 0 3px rgba(127, 216, 255, 0.7); }
  100% { box-shadow: 0 0 0 3px var(--shell-rim), 0 4px 0 var(--shell-deep), 0 0 0 22px rgba(127, 216, 255, 0); }
}
.title-dex.on .tdx-power { translate: -50% 3px; animation: none; box-shadow: 0 0 0 3px var(--shell-rim), 0 1px 0 var(--shell-deep), 0 0 26px 8px #7fd8ff; }
.title-dex.on .tdx-led { animation: none; background: #6be36b; box-shadow: inset 0 0 0 2px var(--shell-deep), 0 0 12px 3px #6be36b; }
.title-dex.open .tdx-cover { animation: tdxSwing 0.55s cubic-bezier(0.55, 0, 0.35, 1) forwards; }
@keyframes tdxSwing {
  80%  { transform: perspective(900px) rotateY(-80deg); opacity: 1; }
  100% { transform: perspective(900px) rotateY(-104deg); opacity: 0; }
}
.title-dex.open .pdx-light { animation: pdxBlink 0.16s steps(1) 5 0.3s; }
.title-dex.open .pdx-light.yellow { animation-delay: 0.38s; }
.title-dex.open .pdx-light.green { animation-delay: 0.46s; }
.title-dex.open .pdx-lens { animation: pdxLens 0.9s ease-out 0.3s; }
.title-dex.open .tdx-screen {
  background: radial-gradient(circle at 50% 40%, #2a5a98, #10234a 75%); box-shadow: inset 0 0 30px rgba(127, 216, 255, 0.3);
  animation: pdxPowerOn 0.5s steps(8) 0.45s;
}
.title-dex.open .tdx-screen > * { animation: tdxShow 0.4s ease-out forwards 0.85s; }
.title-dex.open .tdx-hello { animation-delay: 1.3s; }
@keyframes tdxShow { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
/* lifting away as the sky lights up; or, the very first time, diving into the screen */
.title-dex.away { z-index: 5; animation: tdxAway 0.7s ease-in forwards; pointer-events: none; }
@keyframes tdxAway { to { transform: translateY(-24px) scale(1.12); opacity: 0; filter: brightness(1.7); } }
.title-dex.dive { z-index: 5; animation: tdxDive 0.56s cubic-bezier(0.6, 0, 0.9, 0.5) forwards; }
.title-dex.dive .tdx-screen { filter: brightness(1.6); transition: filter 0.4s; }
@keyframes tdxDive { to { transform: scale(var(--dive, 12)); } }
@media (prefers-reduced-motion: reduce) {
  .title-dex, .tdx-power, .tdx-led { animation: none; }
}
/* a new player's setup on the opened device (onboard() in js/title.js): it opens bigger, onto the name, then the buddy */
.title-dex { transition: width 0.45s ease-out; }
.title-dex.setup { width: clamp(270px, 84vw, 340px); animation: none; }
.title-dex.setup .tdx-screen > :not(.tdx-setup) { display: none; }
.title-dex.instant .tdx-cover { display: none; }
.title-dex.instant .tdx-screen > * { opacity: 1; animation: none; }
.tdx-setup { display: flex; flex-direction: column; align-items: center; gap: 12px; width: 100%; padding: 12px; }
.tdx-step { font-size: 0.75rem; letter-spacing: 2px; color: #7fb8ff; }
.tdx-ask { font-size: clamp(0.75rem, 3.4vw, 0.8rem); letter-spacing: 1px; color: #ffd84a; text-shadow: 2px 2px 0 #2a4cb0; line-height: 1.4; }
.tdx-note { margin-top: -4px; font-size: 0.75rem; line-height: 1.5; letter-spacing: 0.5px; color: #b6f08e; }
.tdx-field {
  width: 88%; padding: 10px 8px; border: 0; border-radius: 6px; text-align: center;
  background: linear-gradient(180deg, #c8e2a0, #a8c97e); color: #1f3a14;
  box-shadow: inset 0 0 0 3px #2a2a30, inset 0 3px 4px rgba(0, 0, 0, 0.18);
  font: 16px var(--pixel-font); font-synthesis-weight: none; letter-spacing: 1px; text-transform: uppercase;
}
.tdx-field::placeholder { color: rgba(31, 58, 20, 0.4); }
.tdx-field:focus { outline: 2px dashed var(--gold); outline-offset: 3px; }
.tdx-ok {
  min-width: 84px; height: 34px; padding: 0 18px; cursor: pointer;
  border: 2px solid #5a3a08; border-radius: 999px;
  background: linear-gradient(#fff3a0, #f8d030 45%, #e0a818);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.7), inset 0 -2px 0 rgba(120, 70, 0, 0.35), 0 3px 0 #5a3a08, 0 0 8px 2px rgba(255, 216, 64, 0.5);
  color: #3a2400; font: 0.75rem var(--pixel-font); font-synthesis-weight: none; text-transform: uppercase;
  -webkit-tap-highlight-color: transparent;
}
.tdx-ok:active { translate: 0 2px; }
.tdx-ok:disabled { filter: grayscale(1) brightness(0.7); box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.4), 0 3px 0 #3a3a3a; cursor: default; }
.tdx-ok.back { background: linear-gradient(#f4f4f8, #c8c8d4); border-color: #3a3a48; color: #2a2a38; box-shadow: inset 0 2px 0 #fff, 0 3px 0 #3a3a48; }
.tdx-keys { display: flex; gap: 10px; }
.tdx-mates { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; width: 100%; }
.tdx-mate {
  display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 6px 2px 7px; cursor: pointer;
  border: 2px solid rgba(255, 255, 255, 0.18); border-radius: 10px;
  background: radial-gradient(circle at 50% 38%, var(--c1, #557) 0, var(--c2, #223) 85%);
  opacity: 0.72; transition: opacity 0.15s, transform 0.15s, border-color 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.tdx-mate[data-type="fire"]  { --c1: #ff8f4d; --c2: #7a2210; }
.tdx-mate[data-type="grass"] { --c1: #7ed36a; --c2: #1f5a22; }
.tdx-mate[data-type="water"] { --c1: #6ab8ff; --c2: #1a3a8a; }
.tdx-mate img { width: 100%; max-width: 72px; aspect-ratio: 1; object-fit: contain; image-rendering: pixelated; }
.tdx-mate-name { font: 0.75rem var(--pixel-font); color: #fff; text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.6); }
.tdx-mate.on { opacity: 1; border-color: var(--gold); transform: translateY(-3px); box-shadow: 0 0 12px 2px rgba(255, 216, 64, 0.55); }
.tdx-mate.on img { animation: tdxHop 0.5s ease-out; }
@keyframes tdxHop { 40% { transform: translateY(-8px); } }
@media (prefers-reduced-motion: reduce) { .tdx-mate.on img { animation: none; } }
/* the setup's trainer step (askLook() in js/title.js): the four heroes, the picked one walking on the spot */
.tdx-looks { grid-template-columns: repeat(4, 1fr); }
.tdx-look { --c1: #8f8fbf; --c2: #2a2a4a; }
.tdx-look .look-art { --s: 100%; max-width: 64px; height: auto; aspect-ratio: 1; }
.tdx-look.on .look-art { animation: look-walk 0.6s steps(4) infinite; }
@media (prefers-reduced-motion: reduce) { .tdx-look.on .look-art { animation: none; } }
:root.calm-fx .tdx-look.on .look-art { animation: none; }
.press-cursor { font-size: 0.7em; color: var(--gold); }

/* the flying legendaries cross the sky in turn (nextFlyer() in js/title.js): a silhouette until unlocked, like Ho-Oh in the
   Gold intro, then in colour. One scale for all (Moltres's old 90-150px), from each GIF's own width (--w). */
.title-flyer {
  position: absolute;
  top: clamp(4px, 7vh, 70px);
  left: 0;
  width: calc(var(--w, 128) * clamp(0.7px, 0.156vw, 1.17px));
  filter: brightness(0);
  opacity: 0.9;
  animation: flyAcross 13s linear infinite 1.2s;
  translate: 110vw 0;
}
.title-flyer.lit { filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.35)); opacity: 1; }
@keyframes flyAcross {
  0%   { translate: 110vw 30px; }
  45%  { translate: -40vw -10px; }
  100% { translate: -40vw -10px; }
}

/* the broken Sealed Gate stands open on the ledge once Mewtwo is free (sizeGate() in js/title.js), its feet sunk a little
   into the grass; a tap swells its violet light over the screen (.gate-opening) on the way to Mewtwo's Prepare step */
.title-gate {
  position: absolute; bottom: calc(var(--ground) - 20px); z-index: 1;
  padding: 0; border: 0; background: none; cursor: pointer;
  filter: drop-shadow(0 0 12px rgba(150, 90, 255, 0.5));
  animation: gateGlow 3s ease-in-out infinite;
  -webkit-tap-highlight-color: transparent;
}
.title-gate[hidden] { display: none; }
.title-gate canvas { display: block; image-rendering: pixelated; }
.title-gate:hover, .title-gate:focus-visible { filter: drop-shadow(0 0 18px rgba(170, 110, 255, 0.85)); outline: none; }
@keyframes gateGlow { 50% { filter: drop-shadow(0 0 18px rgba(150, 90, 255, 0.7)); } }
.title-screen.gate-opening { cursor: default; pointer-events: none; }
.title-screen.gate-opening::after {
  content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background: radial-gradient(circle at var(--gate-x) var(--gate-y), #fff 0, #e0c0ff 6%, #9a60f0 22%, #4a2490 48%, #1a0c38 80%);
  animation: gateSwell 1.1s ease-in forwards;
}
@keyframes gateSwell {
  0%   { opacity: 0; clip-path: circle(0 at var(--gate-x) var(--gate-y)); }
  40%  { opacity: 0.85; }
  100% { opacity: 1; clip-path: circle(150% at var(--gate-x) var(--gate-y)); }
}
@media (max-width: 599px) { .title-gate { bottom: calc(var(--ground) - 15px); } }

/* pressing start: the prompt flickers fast, a white flash, then the sky fades away */
.title-screen.leaving { cursor: default; }
.title-screen.leaving::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #fff;
  animation: titleFlash 1.1s ease-out forwards;
}
.title-screen.leaving { animation: titleFade 1.1s ease-in forwards; }
@keyframes titleFlash { 0%, 35% { opacity: 0; } 45% { opacity: 1; } 100% { opacity: 0; } }
@keyframes titleFade { 0%, 45% { opacity: 1; } 100% { opacity: 0; } }

@media (max-width: 480px) {
  .press-start { font-size: 0.85rem; }
}
@media (prefers-reduced-motion: reduce) {
  .press-start { animation: none; opacity: 1; }
  .title-flyer { display: none; }
}

/* ============ 2. SHARED BITS (deck windows, hints) ============ */
.hint { color: #dfe3ff; font-size: 0.92rem; text-shadow: 0 1px 4px #000; }

.count { margin-left: 8px; padding: 2px 10px; border-radius: 999px; background: rgba(255, 255, 255, 0.16); font-size: 0.9rem; }


.card-pool {
  margin-top: 12px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(136px, 1fr));
  gap: 18px 14px;
}
.pool-heading { grid-column: 1 / -1; font-size: 1.05rem; margin-top: 4px; color: var(--gold); }

/* ============ 3. BATTLE ============ */
body[data-screen="battle-screen"] { height: 100vh; height: 100dvh; overflow: hidden; }
/* nothing on the battle screen pans, zooms, pulls to refresh or long-press selects on a phone; the hand has its own slide (initScrub()) */
html:has(body[data-screen="battle-screen"]), body[data-screen="battle-screen"] { overscroll-behavior: none; }
#battle-screen { touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }

#battle-screen {
  display: grid;
  grid-template-columns: minmax(0, 1fr);   /* stops wide content from stretching the page */
  grid-template-rows: 1fr auto;
  gap: 8px;
  padding: 10px 14px 6px;
  min-height: 0;
  max-width: 1200px;
}

.arena {
  position: relative;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
  padding: 4px 4px calc(2.375rem + 34px);   /* the text box's two lines (0.95rem x 1.25 x 2) + its padding and border + a 12px gap */
}
/* Laid out like the games: the enemy's nameplate top left with the enemy top right, your Pokémon bottom
   left with its nameplate bottom right. The two sprites share the middle row, in different columns, so
   the scene is no taller than when each nameplate sat under its own sprite. */
#enemy-plate  { grid-column: 1; grid-row: 1; align-self: center; justify-self: center; }
#player-plate { grid-column: 2; grid-row: 3; align-self: end; justify-self: center; }

/* --- nameplates: a small Pokégear window under each fighter with its name and Gold/Silver HP bar --- */
.nameplate {
  width: min(100%, 240px);
  padding: 6px 10px 5px;
  border: 3px solid #b8b8c8;
  background: var(--win-bg);
  color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 3px 3px 0 2px rgba(0, 0, 0, 0.4);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.nameplate-title { display: flex; justify-content: space-between; align-items: center; gap: 8px; min-width: 0; }
.nameplate-title strong { font-size: 0.95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nameplate-title .chip { padding: 0; background: none; font-size: 1rem; line-height: 1; cursor: help; display: inline-flex; gap: 2px; }
.nameplate-title .chip .type-badge { width: 1.3em; height: 1.3em; }   /* just the type's pixel icon, no pill */
/* the main games' caught ball, under a wild's HP bar (the user's call, 2026-10-29; it sat by the name): beaten once (the
   Pokédex's Poké Ball), gold with a star once researched */
.dex-mark { flex: none; position: relative; align-self: center; margin: 0 4px 0 0; width: 1.15em; height: 1.15em; font-size: 1rem; cursor: help; }
.dex-mark[hidden] { display: none; }
.dex-mark img { width: 100%; height: 100%; image-rendering: pixelated; display: block; }
.dex-mark.gold img { filter: sepia(1) saturate(4) hue-rotate(5deg) brightness(1.15) drop-shadow(0 0 2px #f8d030); }
.dex-mark.gold::after { content: "★"; position: absolute; right: -5px; bottom: -4px; font-size: 0.75rem; line-height: 1; color: #ffd23a; text-shadow: 1px 1px 0 #6a4800, -1px 0 0 #6a4800, 0 -1px 0 #6a4800; }
/* a duo switches by holding the one out (holdStart() in js/battle.js): a ring fills round it, then the Go pill comes up */
.player-zone.duo { -webkit-touch-callout: none; user-select: none; -webkit-user-select: none; touch-action: manipulation; }
.player-zone.duo #player-sprite { -webkit-user-drag: none; }
.player-zone.duo::after { content: ''; position: absolute; left: 50%; bottom: 14px; width: 120px; height: 120px; translate: -50% 0; border-radius: 50%;
  background: conic-gradient(#ffd84a calc(var(--hold, 0) * 1%), transparent 0); mask: radial-gradient(circle, transparent 55%, #000 57% 66%, transparent 68%);
  opacity: 0; pointer-events: none; }
.player-zone.duo.holding::after { opacity: 1; animation: holdFill 0.45s linear forwards; }
@property --hold { syntax: '<number>'; inherits: false; initial-value: 0; }
@keyframes holdFill { from { --hold: 0; } to { --hold: 100; } }
.switch-go-name, .switch-go-price { display: block; }
.switch-go-price { font-size: 0.75rem; }
.switch-go-edge.up { color: #b8201a; }
.switch-go-edge.down { color: #1d58b8; }
/* small on purpose (the user's call, 2026-10-20): beside the plate, the enemy and its intent stay in view */
.switch-go {
  position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 6;
  padding: 3px 8px; line-height: 1.25; text-align: left;
  border: 2px solid #303038; border-radius: var(--round-sm);
  background: #ffd84a; color: #303038;
  font-family: var(--pixel-font); font-size: 0.75rem; white-space: nowrap;
  box-shadow: 0 2px 0 #a07a10, 0 0 6px rgba(255, 216, 74, 0.5);
  cursor: pointer;
}
.switch-go[hidden] { display: none; }
.switch-go:disabled { filter: grayscale(1) brightness(0.8); cursor: default; }
/* Gen 5's ability pop-up (abilityBanner() in js/battle.js): a window that slides in from the left edge on your side */
.ability-banner {
  position: absolute; left: 0; top: 46%; z-index: 6;
  display: flex; flex-direction: column; gap: 4px;
  padding: 7px 14px 7px 12px;
  border: 3px solid #b8b8c8; border-left: 0;
  border-radius: 0 var(--round-sm) var(--round-sm) 0;
  background: var(--win-bg); color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 3px 3px 0 2px rgba(0, 0, 0, 0.4);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  pointer-events: none;
}
.ability-banner span { font-size: 0.75rem; color: var(--win-muted); }
.ability-banner strong { font-size: 0.95rem; font-weight: normal; color: var(--accent-dark); }
.ability-banner.show { animation: bannerIn 1.9s ease-out both; }
@keyframes bannerIn {
  0% { transform: translateX(-110%); }
  14%, 86% { transform: none; }
  100% { transform: translateX(-110%); }
}
@media (prefers-reduced-motion: reduce) { .ability-banner.show { animation: none; } }
/* StS's turn banner (turnBanner() in js/battle.js): a dark stripe opens across the arena, the words slide in from the
   right, hold, and slide out left as the stripe closes */
.turn-banner {
  position: absolute; left: 0; right: 0; top: 50%; z-index: 7;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 10px 0 9px;
  background: linear-gradient(90deg, rgba(16, 16, 24, 0), rgba(16, 16, 24, 0.82) 18%, rgba(16, 16, 24, 0.82) 82%, rgba(16, 16, 24, 0));
  border-block: 2px solid rgba(255, 216, 74, 0.55);
  font-family: var(--pixel-font); font-synthesis-weight: none; text-align: center;
  pointer-events: none;
  transform: translateY(-50%);
}
.turn-banner[data-side="enemy"] { border-color: rgba(232, 80, 72, 0.6); }
.turn-banner strong {
  font-size: 1.35rem; font-weight: normal; color: #fff; letter-spacing: 1px;
  text-shadow: 2px 2px 0 #303038, -1px -1px 0 #303038, 1px -1px 0 #303038, -1px 1px 0 #303038;
}
.turn-banner[data-side="enemy"] strong { color: #ff8a80; }
.turn-banner[data-side="start"] strong { color: #ffd84a; }
.turn-banner[data-side="win"] strong { color: #ffd84a; font-size: 1.7rem; }
.turn-banner[data-side="lose"] { border-color: rgba(140, 140, 160, 0.6); }
.turn-banner[data-side="lose"] strong { color: #b8b8c8; }
.turn-banner[data-side="relic"] { border-color: rgba(200, 160, 48, 0.7); }
.turn-banner[data-side="relic"] { flex-wrap: wrap; column-gap: 12px; row-gap: 2px; padding-inline: 12px; }
.turn-banner[data-side="relic"] strong { color: #ffe9a6; font-size: 1.05rem; line-height: 1.5; }
.turn-banner[data-side="relic"] span { color: #8af0a8; font-size: 1rem; text-shadow: 1px 1px 0 #303038, -1px -1px 0 #303038; }   /* what it did: "+2 HP" */
.turn-banner[data-side="relic"] span:empty { display: none; }
/* the turn's number: a chunky slanted gold numeral that slams in just after the words */
.turn-banner b {
  font-family: "Chakra Petch", var(--pixel-font); font-weight: 700; font-style: italic; font-size: 2.6rem; line-height: 0.8;
  background: linear-gradient(180deg, #fff6c0 0%, #ffd84a 45%, #f08a1c 100%); -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-stroke: 1.5px #303038;
  filter: drop-shadow(2px 2px 0 #303038) drop-shadow(0 0 8px rgba(255, 196, 60, 0.55));
  padding-right: 4px;
}
.turn-banner b:empty { display: none; }
.turn-banner.show { animation: turnStripe 1.15s ease-out both; }
.turn-banner.show > * { animation: turnWords 1.15s cubic-bezier(0.2, 0.8, 0.3, 1) both; }
.turn-banner.show b { animation-name: turnSlam; }
@keyframes turnSlam {
  0%, 10% { opacity: 0; transform: scale(2.6) rotate(-8deg); }
  24% { opacity: 1; transform: scale(0.92); }
  30%, 76% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateX(-45%); }
}
@keyframes turnStripe {
  0% { opacity: 0; transform: translateY(-50%) scaleY(0); }
  14%, 80% { opacity: 1; transform: translateY(-50%) scaleY(1); }
  100% { opacity: 0; transform: translateY(-50%) scaleY(0.4); }
}
@keyframes turnWords {
  0% { opacity: 0; transform: translateX(45%); }
  22%, 76% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateX(-45%); }
}
.fast-battle .turn-banner.show, .fast-battle .turn-banner.show > * { animation-duration: 0.58s; }
.calm-fx .turn-banner.show > * { animation-name: turnFade; }
@keyframes turnFade { 0%, 100% { opacity: 0; } 20%, 78% { opacity: 1; } }
@media (min-width: 900px) { .turn-banner strong { font-size: 1.8rem; } .turn-banner b { font-size: 3.4rem; } }
@media (min-width: 900px) { .ability-banner { padding: 9px 20px 9px 16px; } .ability-banner span { font-size: 0.85rem; } .ability-banner strong { font-size: 1.2rem; } }
.nameplate .gb-hp { width: 100%; margin: 0; }
/* under the HP bar: the status chips from the left, growing right, and the HP numbers on the right */
.nameplate-foot { display: flex; align-items: flex-start; gap: 4px 8px; }
.nameplate .gb-hp-num { flex: none; width: auto; margin: 0 0 0 auto; font-size: 0.85rem; line-height: 20px; }
.nameplate .gb-hp-track { transition: border-color 0.2s, box-shadow 0.2s; }
/* while a fighter has block, its HP bar gets a blue rim so you can tell at a glance */
.nameplate.has-block .gb-hp-track { border-color: #2060d8; box-shadow: 0 0 0 2px #88c0ff, 2px 2px 0 1px rgba(0, 0, 0, 0.45); }

/* --- status badges (in the nameplates; the How to play guide shows them on their own too) --- */
.badges {
  display: flex;
  justify-content: center;
  gap: 8px;
  min-height: 38px;
  align-items: flex-end;
}
.badge {
  position: relative;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  font-size: 1.15rem;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.62);
  border: 2px solid var(--panel-edge);
  cursor: help;
  animation: badgeIn 0.25s ease-out;
}
.badge b {
  position: absolute;
  right: -7px;
  bottom: -5px;
  min-width: 20px;
  height: 20px;
  padding: 0 4px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  font-size: 0.75rem;
  font-weight: 900;
  background: #fff;
  color: #111;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
.badge.block { border-color: #6fb8ff; background: rgba(20, 60, 120, 0.8); }
.badge.block b { background: #6fb8ff; }
.badge.good { border-color: var(--good); }
.badge.bad  { border-color: var(--bad); }
.badge.bad b { background: var(--bad); color: #fff; }
@keyframes badgeIn { from { transform: scale(0.4); opacity: 0; } }
/* Status floats just outside the nameplate (the user's call, 2026-10-03), so the plate stays one size: under the
   enemy's, over yours, icon then number. Yours wraps upwards. */
.nameplate { position: relative; }
.nameplate .badges {
  position: absolute; left: 0; right: 0; z-index: 3;
  justify-content: flex-start; flex-wrap: wrap; gap: 5px 6px; min-height: 0; align-items: center;
}
#enemy-plate .badges  { top: calc(100% + 9px); }
#player-plate .badges { bottom: calc(100% + 9px); flex-wrap: wrap-reverse; }
.nameplate .badges:empty { display: none; }
.nameplate .badge {
  width: auto;
  height: 22px;
  padding: 0 6px 0 4px;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  border: 0;
  background: none;
  font-size: 0.85rem;
  filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.7));
}
/* No chip behind them (the user's call, 2026-10-03), so the numbers carry a dark outline to read over the arena.
   Their colour says what kind of status it is. */
.nameplate .badge b {
  position: static; min-width: 0; height: auto; padding: 0; background: none; box-shadow: none;
  color: #fff; font-size: 0.8rem;
  text-shadow: 1px 0 0 #181820, -1px 0 0 #181820, 0 1px 0 #181820, 0 -1px 0 #181820;
}
.nameplate .badge.block b { color: #8cc8ff; }
.nameplate .badge.good b { color: #7ee08a; }
.nameplate .badge.bad b { color: #ff7a6a; }

/* --- enemy --- */
/* the enemy's frame takes its own type colour */
.enemy-zone[data-type="fire"]  { --accent: #ff7a45; }
.enemy-zone[data-type="water"] { --accent: #3fa3ff; }
.enemy-zone[data-type="grass"] { --accent: #4fcf6c; }
.enemy-zone[data-type="normal"] { --accent: #b7bdd6; }
.enemy-zone[data-type="electric"] { --accent: #f8d030; }
.enemy-zone[data-type="ice"] { --accent: #78d8e8; }
.enemy-zone[data-type="fighting"] { --accent: #e05848; }
.enemy-zone[data-type="poison"] { --accent: #b868d0; }
.enemy-zone[data-type="ground"] { --accent: #d8b060; }
.enemy-zone[data-type="flying"] { --accent: #a898f0; }
.enemy-zone[data-type="psychic"] { --accent: #f070a8; }
.enemy-zone[data-type="bug"] { --accent: #a8c830; }
.enemy-zone[data-type="rock"] { --accent: #c8b058; }
.enemy-zone[data-type="ghost"] { --accent: #8a70c0; }
.enemy-zone[data-type="dragon"] { --accent: #8060f0; }
.enemy-zone[data-type="dark"] { --accent: #8a7058; }
.enemy-zone[data-type="steel"] { --accent: #b0b0c8; }
.enemy-zone[data-type="fairy"] { --accent: #f0a0c8; }

.enemy-zone {
  position: relative;
  grid-column: 2;
  grid-row: 1 / 3;
  justify-self: center;
  align-self: start;
  width: min(100%, 300px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.enemy-zone.boss-waiting { visibility: hidden; }
/* The Clearing's boss gets a scenery-only beat before any battle UI or Pokémon appears. */
body.boss-prelude .topbar,
body.boss-prelude #battle-screen :is(.nameplate, .intent, .battle-controls, .battle-log, .ability-banner) { visibility: hidden; }
body.boss-prelude .enemy-zone::after,
body.boss-prelude .player-zone::before { visibility: hidden; }
/* The enemy's next move: a Pokégear speech bubble over its head (like the games' "!" emote), with a pixel
   tail pointing down at it. The frame says what kind of move: red attack, purple drain, blue defend, green buff. */
.intent {
  --kind: #e04040;
  position: relative;
  translate: 0 calc(var(--base) * var(--size, 1) * var(--head-room, 0));   /* down to the Pokémon's head (--head-room: sizeSprite() in js/battle.js) */
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 7px;
  padding: 3px 10px 3px 7px;
  border: 2px solid var(--kind);
  background: var(--win-bg);
  color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, 2px 2px 0 2px rgba(0, 0, 0, 0.4);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  line-height: 1;
  cursor: help;
}
.intent::after {                     /* the stepped pixel tail */
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  width: 10px;
  height: 6px;
  margin-top: 2px;
  transform: translateX(-50%);
  background: var(--kind);
  clip-path: polygon(0 0, 100% 0, 100% 50%, 70% 50%, 70% 100%, 30% 100%, 30% 50%, 0 50%);
}
.intent:empty { visibility: hidden; }
.intent.drain  { --kind: #9048c8; }
.intent.defend { --kind: #3878f0; }
.intent.buff   { --kind: #30a040; }
.intent.status { --kind: #707078; }
.intent.paralyzed { --kind: #d8a800; }   /* Static full: it loses its move (Electric) */
.intent.charge { --kind: #ff2a6a; animation: chargeWarn 0.6s steps(2) infinite; }   /* charging a huge hit (Eternamax's Eternabeam): it blinks */
@keyframes chargeWarn { 50% { --kind: #ffd23a; } }   /* shuffles junk (a status card) into your deck, or hidden by the Dusk Stone */
.intent.fresh { animation: intentPop 0.35s ease-out, bob 1.8s ease-in-out 0.35s infinite; }
.intent-icon { font-size: 1rem; }
.intent-value { font-size: 1.05rem; font-weight: 400; color: #283060; }
.intent-name { font-size: 0.8rem; color: #283060; text-shadow: 1px 0 0 currentColor; white-space: nowrap; }   /* the 1px copy is a crisp pixel "bold": the font has no bold weight */
@media (max-width: 420px) { .intent-name { font-size: 0.75rem; } }   /* "Flamethrower" still clears the screen edge on an iPhone SE */
@keyframes bob { 50% { transform: translateY(-4px); } }
@keyframes intentPop { from { transform: translateY(8px) scale(0.3); opacity: 0; } 60% { transform: translateY(-3px) scale(1.15); opacity: 1; } }

.enemy-zone { --base: clamp(92px, 16vh, 160px); }   /* the enemy's box before --size (sizeSprite() in js/battle.js); its pad scales with it too */
.enemy-portrait {
  width: calc(var(--base) * var(--size, 1));
  aspect-ratio: 1;
  min-height: 0;   /* keeps a tall sprite's box square, or it stretches the box and is drawn too big */
  border-radius: 22px;
  overflow: hidden;
  border: 4px solid var(--accent);
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.5), 0 0 26px var(--accent), 0 10px 24px rgba(0, 0, 0, 0.6);
  transition: opacity 0.9s, transform 0.9s, filter 0.9s;
}
.enemy-portrait img { width: 100%; height: 100%; object-fit: cover; }

/* --- player --- */
.player-zone {
  position: relative;
  grid-column: 1;
  grid-row: 2 / 4;
  align-self: end;
  justify-self: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: min(100%, 300px);
  padding-bottom: 20px;
}

/* Your Pokémon grows as it evolves: the first form is drawn at 78% and the middle one at 90% of its final
   size, scaled from its feet. `scale` stacks with the attack/hit/evolve animations' transforms and leaves
   the layout alone, so nothing around the sprite moves. */
:is(.run-sprite, .map-trainer) { scale: var(--grow, 1); transform-origin: 50% 100%; }
:is(.run-sprite, .map-trainer)[data-stage="0"] { --grow: 0.78; }
:is(.run-sprite, .map-trainer)[data-stage="1"] { --grow: 0.9; }
#player-sprite {
  /* sized from the window height so it fits on short screens too; --size (sizeSprite() in js/battle.js) scales it by the file's real size */
  width: calc(clamp(96px, 21vh, 230px) * var(--size, 1));
  aspect-ratio: 1;
  object-fit: contain;
  object-position: 50% 100%;
  translate: calc(var(--shift, 0) * 100%) calc(var(--drop, 0) * 100%);   /* stands the resting pose centred at the bottom */
  max-width: 92%;
  filter: drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5));
}

/* The battle text: a Gold/Silver text box that types itself out, with a blinking ▼ once the line is done */
.battle-log {
  position: absolute;
  left: 50%;
  bottom: 2px;
  transform: translateX(-50%);
  width: min(64%, 560px);
  --log-font: 0.95rem;
  min-height: calc(var(--log-font) * 2.5 + 20px);   /* always two lines tall, like the games' box, so a long line never grows it into your nameplate */
  padding: 7px 26px 7px 14px;
  border: 3px solid #b8b8c8;
  background: var(--win-bg);
  color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 3px 3px 0 2px rgba(0, 0, 0, 0.4);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: var(--log-font);
  line-height: 1.25;
  text-align: left;
}
.battle-log.quiet { visibility: hidden; }
#battle-log-text { display: block; }   /* a block, so fitLog() in js/battle.js can measure its lines */
.battle-log.tight { font-size: calc(var(--log-font) * 0.86); }
.battle-log.done::after {
  content: '▼';
  position: absolute;
  right: 9px;
  bottom: 5px;
  font-size: 0.75rem;
  color: #c02020;
  animation: cursorBlink 1s steps(1) infinite;
}

/* the relic flash (relicFlash() in js/battle.js), after a relic's first banner: its icon in Torrent's window
   (.ability-banner's look) slides in from the left edge the same way, holds and slides back out, one after another,
   above where Torrent's shows */
.relic-flash {
  position: absolute; left: 0; top: 34%; z-index: 6;
  padding: 5px 12px 5px 10px;
  border: 3px solid #b8b8c8; border-left: 0;
  border-radius: 0 var(--round-sm) var(--round-sm) 0;
  background: var(--win-bg);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 3px 3px 0 2px rgba(0, 0, 0, 0.4);
  font-size: 1.4rem; line-height: 1;
  pointer-events: none;
  animation: bannerIn 1.4s ease-out both;
}
.calm-fx .relic-flash { animation-name: turnFade; }
.fast-battle .relic-flash { animation-duration: 0.7s; }
/* the lethal warning (renderIntent()): the bubble throbs red with a skull, and your HP bar blinks red (red arena edges
   looked like a frame on a phone, the user's call) */
.intent.lethal { --kind: #ff2020; }
.intent.lethal.fresh, .intent.lethal { animation: lethalThrob 0.9s ease-in-out infinite; }
@keyframes lethalThrob { 50% { box-shadow: 0 0 0 2px #303038, 0 0 14px 4px rgba(255, 32, 32, 0.75); } }
.intent-mark { font-size: 0.95rem; }
.intent-mark.safe { font-size: 0.8rem; color: #fff; background: #3878f0; border-radius: 50%; width: 18px; height: 18px; display: grid; place-items: center; }
#player-plate.danger .gb-hp { animation: dangerPulse 0.9s ease-in-out infinite; }
@keyframes dangerPulse { 50% { box-shadow: 0 0 0 2px #ff2020, 0 0 10px 2px rgba(255, 32, 32, 0.7); } }
.calm-fx .intent.lethal { animation: none; box-shadow: 0 0 0 2px #303038, 0 0 12px 3px rgba(255, 32, 32, 0.6); }
.calm-fx #player-plate.danger .gb-hp { animation: none; box-shadow: 0 0 0 2px #ff2020; }

/* --- floating numbers --- */
.pop {
  position: absolute;
  left: 50%;
  top: 35%;
  z-index: 8;
  white-space: nowrap;
  font-size: 2rem;
  font-weight: 900;
  color: #fff;
  -webkit-text-stroke: 5px #7a1010;
  paint-order: stroke fill;
  pointer-events: none;
  opacity: 0;
  animation: floatUp 1.2s ease-out both;
}
.pop.heal  { color: #b6ffcc; -webkit-text-stroke-color: #13683a; }
.pop.block { color: #cfe8ff; -webkit-text-stroke-color: #1a4a8a; font-size: 1.6rem; }
.pop.note  { font-size: 1.05rem; color: #ffe9a6; -webkit-text-stroke: 4px #4a3300; top: 62%; }
.pop.note.good { color: #c8ffd6; -webkit-text-stroke-color: #15602f; }
.pop.note.bad  { color: #ffc9c9; -webkit-text-stroke-color: #7a1010; }
@keyframes floatUp {
  0%   { opacity: 0; transform: translate(-50%, 10px) scale(0.6); }
  15%  { opacity: 1; transform: translate(-50%, -6px) scale(1.15); }
  100% { opacity: 0; transform: translate(-50%, -70px) scale(1); }
}

/* --- hit / attack animations --- */
.hit { animation: shake 0.42s; }
@keyframes shake {
  0%, 100% { transform: translateX(0); filter: none; }
  20% { transform: translateX(-12px); filter: brightness(2) saturate(2); }
  40% { transform: translateX(10px); }
  60% { transform: translateX(-7px); }
  80% { transform: translateX(4px); }
}
/* a big hit (bigHit() in battle.js): the arena jolts and the screen flashes white; `translate` leaves the sprites' own transforms alone */
#battle-screen.big-hit .arena { animation: bigJolt 0.45s linear; }
/* any other hit nudges the arena as hard as the hit (--jolt, strikeFx() in battle.js) */
#battle-screen.fx-jolt:not(.big-hit) .arena { animation: fxJolt 0.24s linear; }
@keyframes fxJolt { 20% { translate: calc(var(--jolt) * -1) calc(var(--jolt) * 0.5); } 45% { translate: calc(var(--jolt) * 0.7) calc(var(--jolt) * -0.4); } 70% { translate: calc(var(--jolt) * -0.3) 0; } }
.fast-battle #battle-screen.fx-jolt .arena { animation-duration: 0.12s; }
/* the foe flashes the colour of what hit it, in its own shape */
.hit-tint {
  position: absolute; z-index: 1; pointer-events: none; mix-blend-mode: screen;
  -webkit-mask: var(--mask) 50% 100% / contain no-repeat; mask: var(--mask) 50% 100% / contain no-repeat;
  animation: hitTint 0.36s ease-out forwards;
}
@keyframes hitTint { 0% { opacity: 0.95; } 100% { opacity: 0; } }
.fast-battle .hit-tint { animation-duration: 0.18s; }
@keyframes bigJolt {
  11% { translate: -8px 4px; }
  22% { translate: 7px -5px; }
  33% { translate: -6px -3px; }
  44% { translate: 5px 4px; }
  55% { translate: -4px 2px; }
  66% { translate: 3px -2px; }
  77% { translate: -2px 1px; }
}
#battle-screen.big-hit::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 50;
  background: #fff;
  pointer-events: none;
  animation: bigFlash 0.3s ease-out forwards;
}
@keyframes bigFlash { from { opacity: 0.5; } to { opacity: 0; } }
/* the finishing blow on an Alpha, Kenmatta or a boss (finishingBlow() in battle.js): everything freezes mid-move for a
   beat while the enemy burns white and the number slams in, then the arena shakes in whole steps */
#battle-screen.hitstop :is(*, *::before, *::after):not(.ko-num, .ko-flash) { animation-play-state: paused !important; }
.ko-flash {
  position: absolute; z-index: 2; pointer-events: none; background: #fff;
  -webkit-mask: var(--mask) 50% 100% / contain no-repeat; mask: var(--mask) 50% 100% / contain no-repeat;
  animation: koFlash 0.85s steps(1) forwards;
}
@keyframes koFlash { 0% { opacity: 1; } 45% { opacity: 0; } 55% { opacity: 1; } 65% { opacity: 0; } 75% { opacity: 1; } 85%, 100% { opacity: 0; } }
.ko-num {
  position: absolute; left: 50%; top: 22%; z-index: 9; pointer-events: none; white-space: nowrap;
  font-size: 3.4rem; color: #ffe14a; -webkit-text-stroke: 7px #3a0000; paint-order: stroke fill;
  text-shadow: 4px 4px 0 #3a0000;
  animation: koNum 1.6s steps(1) both;
}
@keyframes koNum {
  0%   { transform: translate(-50%, 0) scale(2.2); }
  5%   { transform: translate(-50%, 0) scale(1.6); }
  10%  { transform: translate(-50%, 0) scale(1); color: #fff; }
  16%  { color: #ffe14a; }
  60%  { transform: translate(-50%, -6px) scale(1); opacity: 1; }
  70%  { transform: translate(-50%, -12px) scale(1); opacity: 1; }
  80%  { transform: translate(-50%, -18px) scale(1); opacity: 0.5; }
  90%, 100% { transform: translate(-50%, -24px) scale(1); opacity: 0; }
}
#battle-screen.ko-shake .arena { animation: koShake 0.52s steps(1); }
@keyframes koShake {
  0%  { translate: -10px 6px; }  12% { translate: 9px -6px; }  24% { translate: -8px -4px; } 36% { translate: 7px 5px; }
  48% { translate: -5px 3px; }   60% { translate: 4px -3px; }  72% { translate: -2px 2px; }  84%, 100% { translate: 0 0; }
}
.fast-battle #battle-screen.ko-shake .arena { animation-duration: 0.26s; }
@media (prefers-reduced-motion: reduce) { .ko-num { animation: koNumStill 1.6s steps(1) both; } }
@keyframes koNumStill { 0%, 85% { transform: translate(-50%, 0); opacity: 1; } 100% { transform: translate(-50%, 0); opacity: 0; } }
#player-sprite.lunge { animation: lunge 0.38s ease-out; }
@keyframes lunge { 40% { transform: translate(40px, -14px); } }
/* the enemy winds up, then lunges; a big hit makes its sprite reel back (bigHit()), on the img so it doesn't fight the box's shake */
.enemy-portrait.attacking { animation: enemyLunge 0.3s ease-in; }
@keyframes enemyLunge { 25% { transform: translate(12px, -6px) scale(0.97); } 65% { transform: translate(-46px, 24px) scale(1.06); } }
#enemy-img.recoil { transform-origin: 50% 100%; animation: enemyRecoil 0.52s ease-out; }
@keyframes enemyRecoil { 18% { translate: 12px -8px; rotate: 9deg; scale: 0.94; } 50% { translate: 5px -3px; rotate: 4deg; scale: 0.98; } }
@media (prefers-reduced-motion: reduce) { .enemy-portrait.attacking, #enemy-img.recoil { animation: none; } }
.no-battle-fx :is(.enemy-portrait.attacking, #enemy-img.recoil, #player-sprite.lunge) { animation: none; }
/* 2x battle speed (Settings, js/settings.js): the same animations at half their length, to match pause() in battle.js */
.fast-battle #battle-screen .pop { animation-duration: 0.6s; }
.fast-battle #battle-screen .hit { animation-duration: 0.21s; }
.fast-battle #battle-screen.big-hit .arena { animation-duration: 0.225s; }
.fast-battle #battle-screen.big-hit::after { animation-duration: 0.15s; }
.fast-battle #player-sprite.lunge { animation-duration: 0.19s; }
.fast-battle .enemy-portrait.attacking { animation-duration: 0.15s; }
.fast-battle #enemy-img.recoil { animation-duration: 0.26s; }
/* a super-effective hit's number is red and a notch bigger */
.pop.dmg.super { color: #ff5a3a; -webkit-text-stroke-color: #3a0000; font-size: 2.35rem; }
/* the block preview (showPreview() in battle.js): the block a raised card would add blinks on your nameplate */
.nameplate.block-preview .gb-hp-track { animation: blockGhost 0.7s steps(1) infinite; }
@keyframes blockGhost { 50% { border-color: #2060d8; box-shadow: 0 0 0 2px #88c0ff, 2px 2px 0 1px rgba(0, 0, 0, 0.45); } }
.badge.preview { animation: badgeGhost 0.7s steps(1) infinite; }
@keyframes badgeGhost { 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) { .nameplate.block-preview .gb-hp-track, .badge.preview { animation: none; } }
/* the HP your block would save from the coming hit (shieldPreview()): blue over the end of the bar, at least 4px, since
   the old red damage chunk read as a stray dot on small hits. The block you have holds steady; a raised card's blinks
   between two blues (never to nothing); when the hit lands it flashes white and breaks off (soakShield()) */
.nameplate .gb-hp-track { position: relative; }
.gb-hp-shield {
  position: absolute; top: 3px; bottom: 3px;
  left: max(3px, calc(3px + (100% - 6px) * var(--from)));
  width: max(4px, calc((100% - 6px) * var(--size)));
  background: #3878f0; box-shadow: inset 0 2px 0 #88c0ff;
}
.gb-hp-shield.ghost { animation: shieldGhost 0.7s steps(1) infinite; }
@keyframes shieldGhost { 50% { background: #88c0ff; box-shadow: inset 0 2px 0 #c8e4ff; } }
.gb-hp-shield.soak { animation: shieldSoak 0.5s steps(5) forwards; }
@keyframes shieldSoak {
  0%   { background: #fff; box-shadow: inset 0 2px 0 #fff; }
  40%  { background: #c8e4ff; translate: 0 -1px; }
  100% { background: #88c0ff; translate: 0 -5px; opacity: 0; }
}
.fast-battle .gb-hp-shield.soak { animation-duration: 0.25s; }
@media (prefers-reduced-motion: reduce) { .gb-hp-shield.ghost { animation: none; } .gb-hp-shield.soak { animation: shieldSoak 0.5s steps(1) forwards; } }
.enemy-portrait.defeated { opacity: 0; transform: scale(0.6) rotate(8deg); filter: grayscale(1); }
#player-sprite { transition: opacity 0.9s, transform 0.9s, filter 0.9s, clip-path 0.9s; }
/* Dig: the sprite sinks into the ground and pops back up. Moving it down while clipping its bottom by the same share keeps
   its feet on the ground line, so it reads as going into the earth, not sliding off. A wild Pokémon's Fly flies off the top. */
#player-sprite.dug, .enemy-portrait:is(.away-dig, .away-dive) #enemy-img { clip-path: inset(0 0 100% 0); transform: translateY(100%); transition: transform 0.55s ease-in, clip-path 0.55s ease-in, opacity 0.55s; }
#enemy-img { transition: transform 0.9s, clip-path 0.9s, opacity 0.6s; }
.enemy-portrait.away-fly #enemy-img { transform: translateY(-140%) scale(0.6); opacity: 0; transition: transform 0.6s ease-in, opacity 0.6s ease-in; }
#player-sprite.defeated { opacity: 0; transform: translateY(50px); filter: grayscale(1); }
#player-sprite.fled { opacity: 0; transform: translateX(-120px); }   /* Poké Doll: ran away */

/* A stat change (statFx() in js/battle.js), like the games: stripes scroll over the Pokémon's silhouette,
   the sprite's own GIF as the mask. Stepped, so it moves in pixel jumps. */
.enemy-portrait { position: relative; }
.stat-fx {
  position: absolute;
  z-index: 1;
  pointer-events: none;
  -webkit-mask: var(--mask) 50% 100% / contain no-repeat;
  mask: var(--mask) 50% 100% / contain no-repeat;
  background: repeating-linear-gradient(to bottom, var(--fx-a) 0 8px, var(--fx-b) 8px 16px);
  mix-blend-mode: hard-light;
  opacity: 0;
  animation: statFx 0.9s linear forwards;
}
.stat-fx.up   { --fx-a: rgba(255, 96, 48, 0.85); --fx-b: rgba(255, 216, 96, 0.55); --fx-to: -64px; }
.stat-fx.down { --fx-a: rgba(40, 96, 255, 0.85); --fx-b: rgba(150, 200, 255, 0.5); --fx-to: 64px; }
@keyframes statFx {
  0%   { opacity: 0; background-position: 0 0; }
  15%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { opacity: 0; background-position: 0 var(--fx-to); }
}

/* --- battle intro: enemy appears, then a Poké Ball releases your Pokémon --- */
/* Like Diamond/Pearl: the enemy slides in on its pad from off the right edge as a silhouette, then
   colours in (.revealed) as it cries. The `translate` property, so the sprite's own transforms are untouched. */
html:has(body[data-screen="battle-screen"]) { overflow-x: clip; }   /* no sideways scroll while it's off-screen (on body, phones could still swipe) */
.enemy-zone.entering { animation: enemySlideIn 0.8s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
.enemy-zone.entering { will-change: transform; }
@keyframes enemySlideIn { from { transform: translate3d(100vw, 0, 0); } to { transform: translate3d(0, 0, 0); } }
.enemy-zone.entering .intent { visibility: hidden; }
.enemy-zone.entering #enemy-img { filter: brightness(0) opacity(0.85); }
.enemy-zone.revealed #enemy-img { animation: enemyReveal 0.4s ease-out; }
/* every step ends in the sprite's own resting filter (--rest: its shadow, an elite's red or a boss's gold glow), or the
   filters can't blend and it held a bright glow, then snapped back */
@keyframes enemyReveal {
  from { filter: brightness(0) opacity(0.85) var(--rest); }
  40% { filter: brightness(2.2) opacity(1) var(--rest); }
  to { filter: brightness(1) opacity(1) var(--rest); }
}
.player-zone.awaiting #player-sprite,
.player-zone.awaiting ~ #player-plate { visibility: hidden; }
#player-sprite.released { animation: released 0.6s ease-out; }
/* a duo's recall (switchOut() in js/battle.js): the games' red light, shrinking back into the ball */
#player-sprite.recalled { animation: recalled 0.38s ease-in forwards; }
@keyframes recalled {
  from { transform: scale(1); filter: brightness(1) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); }
  35%  { transform: scale(1.04); filter: brightness(1.4) sepia(1) saturate(8) hue-rotate(-30deg) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); }
  to   { transform: scale(0.1); opacity: 0.2; filter: brightness(2) sepia(1) saturate(8) hue-rotate(-30deg) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); }
}
/* a shiny's sparkles as it comes out of the ball (shinySparkle() in js/battle.js) */
.shiny-burst { position: absolute; left: 50%; bottom: 40%; width: 0; height: 0; pointer-events: none; z-index: 3; }
.shiny-star {
  position: absolute;
  left: -14px;
  top: -14px;
  font-size: 28px;
  line-height: 1;
  opacity: 0;
  animation: shinyStar 0.8s ease-out var(--delay) forwards;
}
@keyframes shinyStar {
  0% { opacity: 1; transform: rotate(var(--angle)) translateY(-10px) scale(0.4); }
  60% { opacity: 1; }
  100% { opacity: 0; transform: rotate(var(--angle)) translateY(-90px) scale(1.1); }
}
/* white as it grows out of the ball, colour back by the time it settles: every step keeps the sprite's drop shadow, or the
   filters can't blend and it held a bright glow, then snapped (the user saw Charmander glow after coming out) */
@keyframes released {
  from { transform: scale(0.15); filter: brightness(8) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); }
  55%  { transform: scale(1.12); filter: brightness(2.5) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); }
  75%  { filter: brightness(1) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); }
  to   { transform: scale(1); filter: brightness(1) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); }
}
.intro-ball {
  position: absolute;
  left: 50%;
  top: 42%;
  z-index: 3;
  width: 0;
  height: 0;
  font-size: 80px;   /* the flash is sized in em */
  pointer-events: none;
}
/* a 3D ball (js/ball-looks.js): its sheet's 16 frames of one clockwise turn in a row (tools/ball-sheets.mjs), --b its
   size; `.spin` turns it, `.back` the other way */
.ball3d { --b: 64px; display: block; width: var(--b); height: var(--b); background: var(--sheet) 0 0 / calc(var(--b) * 16) var(--b) no-repeat; }
.ball3d.spin { animation: ballRoll 0.28s steps(16) infinite; }
.ball3d.spin.back { animation-direction: reverse; }
@keyframes ballRoll { to { background-position-x: calc(var(--b) * -16); } }
/* the ball your partner comes out of (js/data/workshop.js's sendSprite(): a Poké Ball, or the Apricorn ball carried) */
.intro-ball .ball3d { position: absolute; translate: -50% -50%; filter: drop-shadow(0 4px 3px rgba(0, 0, 0, 0.35)); }
/* thrown in an arc, spinning, from off the window's bottom-left corner (--from-x/y are set by playIntro()) */
.intro-ball.thrown { animation: ballArcX 0.7s linear both; }
.intro-ball.thrown .ball3d { animation: ballArcY 0.7s both, ballRoll 0.28s steps(16) infinite; }
@keyframes ballArcX { from { transform: translateX(var(--from-x)); } }
@keyframes ballArcY {
  from { top: var(--from-y); animation-timing-function: ease-out; }
  45%  { top: -16vh; animation-timing-function: ease-in; }
  to   { top: 0; }
}
.intro-ball.open .ball3d { animation: ballPop 0.3s ease-in both; }
@keyframes ballPop { to { transform: scale(1.5); opacity: 0; } }
.intro-ball.open::after {
  content: "";
  position: absolute;
  width: 2.4em;
  height: 2.4em;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0 30%, rgba(255, 255, 255, 0.7) 50%, transparent 70%);
  animation: ballFlash 0.5s ease-out both;
}
@keyframes ballFlash {
  from { transform: scale(0.1); opacity: 1; }
  40%  { opacity: 1; }
  to   { transform: scale(2.6); opacity: 0; }
}

/* --- bottom row: PP | hand | End Turn --- */
.battle-controls {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "orb hand side";
  align-items: center;
  gap: 10px;
}
/* PP and End Turn are drawn like the Diamond/Pearl move screen: a white pill on the salmon striped move
   panel. PP shows "PP" on the left and "2/3" on the right; the numbers turn red when you're out. */
.energy-orb, #end-turn-btn {
  position: relative;
  padding: 7px 8px;
  border: 0;
  border-radius: 999px;   /* a capsule following the white pill inside */
  background: repeating-linear-gradient(#f07068 0 4px, #f8887c 4px 8px);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #c84840, 4px 4px 0 2px rgba(0, 0, 0, 0.45);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  line-height: 1;
  transition: filter 0.25s;
}
.orb-wrap { grid-area: orb; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.pp-pill {
  display: flex;
  align-items: baseline;
  gap: 18px;
  padding: 10px 16px 9px;
  border-radius: 999px;
  background: #f8f8f8;
  box-shadow: 0 0 0 4px var(--rim, #c84840), inset 0 -3px 0 #d0d0d8;   /* a thick ring in the panel's dark rim colour */
  color: #404048;
  text-shadow: 2px 2px 0 #c0c0c8;   /* the DS text's grey drop shadow */
  white-space: nowrap;
}
.pp-label { font-size: 1rem; }
.pp-count { margin-left: auto; font-size: 1.35rem; }
.energy-orb b { display: inline-block; font-weight: 400; }
.energy-orb b.bump { animation: ppBump 0.35s ease-out; }
.energy-orb.empty .pp-count { color: #e03828; text-shadow: 2px 2px 0 #f8b8a8; }
@keyframes ppBump { 50% { transform: translateY(-4px) scale(1.15); } }
/* PP's refill (ppChanged() in js/battle.js, with js/movefx.js's gold motes): the capsule charges gold, a shine sweeps it
   and the number pops gold; a card's +PP gets the shine alone. End Turn wears the same shine as it hops and when pressed. */
:is(.energy-orb, #end-turn-btn)::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 232, 128, 0.75) 47%, rgba(255, 255, 255, 0.95) 50%, rgba(255, 232, 128, 0.75) 53%, transparent 62%) no-repeat;
  background-size: 300% 100%; background-position: 100% 0; opacity: 0;
}
@keyframes pillShine { from { background-position: 100% 0; opacity: 1; } 90% { opacity: 1; } to { background-position: 0 0; opacity: 0; } }
.energy-orb.refill { animation: ppCharge 0.9s ease-out 0.3s; }
.energy-orb.refill::after { animation: pillShine 0.55s ease-out 0.4s both; }
.energy-orb.gain::after { animation: pillShine 0.45s ease-out 0.25s both; }
@keyframes ppCharge {
  30% { box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #c84840, 0 0 0 5px #f8d030, 0 0 22px 8px rgba(248, 208, 48, 0.7), 4px 4px 0 2px rgba(0, 0, 0, 0.45); }
}
.energy-orb b.fill { animation: ppFill 0.7s ease-out 0.35s both; }
@keyframes ppFill {
  0% { transform: none; }
  35% { transform: translateY(-5px) scale(1.3); color: #e8a800; text-shadow: 2px 2px 0 #fff0a0, 0 0 10px #ffe060; }
  100% { transform: none; }
}
#end-turn-btn.nudge::after { animation: pillShine 1.4s ease-out infinite; }
#end-turn-btn.pressed { animation: turnPress 0.35s ease-out; }
#end-turn-btn.pressed::after { animation: pillShine 0.4s ease-out both; }
@keyframes turnPress { 30% { filter: brightness(1.5); scale: 0.94; } }
@media (prefers-reduced-motion: reduce) {
  :is(.energy-orb, #end-turn-btn)::after, .energy-orb.refill, .energy-orb b.fill, #end-turn-btn.pressed { animation: none; }
}
.energy-orb.shake { animation: ppShake 0.36s linear; }   /* tried to play a card without enough PP */
@keyframes ppShake { 0%, 100% { transform: none; } 20%, 60% { transform: translateX(-5px); } 40%, 80% { transform: translateX(5px); } }
.turn-side { grid-area: side; display: flex; flex-direction: column; align-items: center; gap: 6px; }
/* beside the hand, PP and End Turn sit level with the lower half of the cards rather than their middle */
.battle-controls > :is(.orb-wrap, .turn-side) { translate: 0 18px; }
#end-turn-btn { cursor: pointer; }
#end-turn-btn .pp-pill { font-size: 1.05rem; }
#end-turn-btn:hover:not(:disabled) .pp-pill { background: #fff; }
#end-turn-btn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #c84840, 2px 2px 0 1px rgba(0, 0, 0, 0.45); }
#end-turn-btn:focus-visible { outline: 3px solid #f8d030; outline-offset: 3px; }
#end-turn-btn:disabled { filter: grayscale(1) brightness(0.9); opacity: 0.7; cursor: not-allowed; }
/* nothing left to play (.nudge, renderAll()): End Turn hops, its stripes scroll and a gold ring blinks (no ▶ in the pill: it widened the button) */
#end-turn-btn.nudge { background-size: 100% 8px; animation: turnHop 1.4s ease-in-out infinite, turnRing 0.7s steps(1) infinite, stripeScroll 0.5s steps(4) infinite; }
@keyframes turnHop { 0%, 60%, 80%, 100% { translate: 0 0; } 70% { translate: 0 -7px; } 90% { translate: 0 -3px; } }
@keyframes turnRing { 50% { box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #c84840, 0 0 0 5px #f8d030, 4px 4px 0 5px rgba(0, 0, 0, 0.45); } }
@media (prefers-reduced-motion: reduce) {
  #end-turn-btn.nudge { animation: none; box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #c84840, 0 0 0 5px #f8d030, 4px 4px 0 5px rgba(0, 0, 0, 0.45); }
}
/* The Safari Zone's Throw Ball (js/battle.js): the End Turn capsule in the Safari's green, the Safari Ball in its pill.
   .spent: PP already used this turn (a tap says why). On phones it sits left of End Turn on the PP row. */
.throw-btn {
  position: relative; padding: 8px 9px; border: 0; border-radius: 999px; cursor: pointer;
  background: repeating-linear-gradient(#58a838 0 4px, #78c850 4px 8px);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #2e7020, 4px 4px 0 2px rgba(0, 0, 0, 0.45);
  font-family: var(--pixel-font); font-synthesis-weight: none; line-height: 1;
  animation: throwHop 1.6s ease-in-out infinite;
}
.throw-btn .pp-pill { --rim: #2e7020; justify-content: center; align-items: center; gap: 8px; font-size: 1.05rem; }
.battle-controls .throw-btn .pp-pill { min-width: 0; }
.throw-ball-icon { width: 30px; height: 30px; image-rendering: pixelated; }
.throw-btn:hover .pp-pill { background: #fff; }
.throw-btn:active { transform: translate(2px, 2px); }
.throw-btn:focus-visible { outline: 3px solid #f8d030; outline-offset: 3px; }
.throw-btn.spent { animation: none; filter: grayscale(0.8) brightness(0.9); }
@keyframes throwHop { 0%, 70%, 90%, 100% { translate: 0 0; } 80% { translate: 0 -5px; } }
@media (prefers-reduced-motion: reduce) { .throw-btn { animation: none; } }
/* The Sky Pillar's Mulligan augment borrows Throw's capsule and place, in violet, without the hop */
.mulligan-btn { animation: none; background: repeating-linear-gradient(#8858d0 0 4px, #a078e8 4px 8px); box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #503090, 4px 4px 0 2px rgba(0, 0, 0, 0.45); }
.mulligan-btn .pp-pill { --rim: #503090; }
.mulligan-btn:disabled { filter: grayscale(0.8) brightness(0.9); cursor: default; }
/* Insight: the move after the next one, small under the intent */
.intent .intent-then { position: absolute; top: 100%; left: 50%; translate: -50% 3px; padding: 2px 6px; border-radius: 6px; background: rgba(20, 16, 40, 0.78); color: #fff; font-size: 0.75rem; white-space: nowrap; pointer-events: none; }
/* the picker: a DS menu window over the Throw button, one row per ball (sprite, name, stock, odds) */
.ball-picker {
  position: fixed; z-index: 60; width: min(17rem, calc(100vw - 16px)); padding: 6px;
  background: #f8f8f8; border-radius: 6px;
  box-shadow: 0 0 0 3px #303038, inset 0 0 0 3px #78c850, inset 0 0 0 5px #f8f8f8, inset 0 0 0 6px #2e7020, 4px 4px 0 3px rgba(0, 0, 0, 0.45);
  font-family: var(--pixel-font); color: #404048;
}
.ball-picker-title { padding: 6px 10px 4px; font-size: 0.8rem; color: #2e7020; }
.ball-row {
  display: grid; grid-template-columns: 32px 1fr auto auto; align-items: center; gap: 8px; width: 100%;
  min-height: 44px; padding: 4px 10px; border: 0; border-radius: 4px; background: none;
  font: inherit; font-size: 0.85rem; color: inherit; text-align: left; cursor: pointer;
  text-shadow: 1px 1px 0 #d0d0d8;
}
.ball-row:hover, .ball-row:focus-visible { background: #e0f0d0; outline: none; }
.ball-row:hover .ball-name::before, .ball-row:focus-visible .ball-name::before { content: "▶"; margin-right: 4px; font-size: 0.7em; color: #e03828; }
.ball-icon .item-sprite { width: 30px; height: 30px; image-rendering: pixelated; display: block; }
.ball-left { font-size: 0.75rem; color: #707078; }
.ball-odds { min-width: 3ch; text-align: right; font-weight: 400; color: #2e7020; }
/* the thrown ball (ballAnimation()): moved by the Web Animations API, from the arena's top-left corner */
.thrown-ball { position: absolute; left: 0; top: 0; z-index: 4; width: 0; height: 0; pointer-events: none; }
.thrown-ball .ball3d { --b: 24px; position: absolute; translate: -50% -50%; filter: drop-shadow(0 2px 1px rgba(0, 0, 0, 0.35)); }
.thrown-ball.caught .ball3d { filter: brightness(0.6); transition: filter 0.4s ease; }
.thrown-ball.burst .ball3d { animation: ballPop 0.3s ease-in both; }
/* pulled into the ball: a white flash and a shrink into it, like the games */
.enemy-portrait:is(.captured, .recalled) { transition: transform 0.4s ease-in, opacity 0.4s ease-in, filter 0.2s ease-out; transform: scale(0.05) translateY(40%); opacity: 0; filter: brightness(8); }
.enemy-portrait.ran { transition: transform 1s ease-in, opacity 1s ease-in; transform: translateX(140px); opacity: 0; }
.catch-star { color: #f8d030; }
/* a rare spawn's nameplate: a gold rim and a slow shimmer on its name */
/* a rare spawn's rim is grass green, so it isn't mistaken for a shiny's gold (2026-10-20) */
#enemy-plate.rare { box-shadow: 0 0 0 2px #58c040, 0 0 14px rgba(88, 192, 64, 0.6); }
#enemy-plate.rare #enemy-name { color: #2a7a20; }
/* a RARE tag under its HP bar, the word alone (the user's call, 2026-10-28: the running count moved out to the status row) */
.rare-tag { flex: none; margin-right: auto; padding: 1px 8px; font-size: 0.75rem; line-height: 18px; border: 1px solid #62d474;
  background: #1c5a2c; color: #b8f0c0; }
/* its run-off count, first in the status row under the plate: a figure running on the spot and the turns left (moved out
   of the plate 2026-10-28), red on its last turn. The figure moves by transform, which the compositor runs */
.nameplate .badge.flee b { color: #7ee08a; }
.nameplate .badge.flee.bad b { color: #ff7a6a; }
.badge .flee-run { width: 18px; height: 18px; flex: none; }   /* over .smooth-icon's 1em */
@media (prefers-reduced-motion: no-preference) {
  .flee-run { animation: fleeRun 0.4s steps(1) infinite; }
  .badge.flee.bad .flee-run { animation-duration: 0.24s; }
}
@keyframes fleeRun { 0% { transform: translateX(-1px); } 50% { transform: translateX(2px) translateY(-1px); } }

/* PP and End Turn are one size, so the two ends of the controls match (wrap + align-content centres the PP's baseline row).
   Big here, on PCs and phones held sideways; the phone rules shrink them so the hand keeps the room. */
.battle-controls :is(.energy-orb, #end-turn-btn) { padding: 8px 9px; }
.battle-controls .pp-pill { min-width: 9.5rem; height: 3.1rem; padding: 12px 20px 11px; flex-wrap: wrap; align-content: center; }
.battle-controls .pp-label { font-size: 1.2rem; }
.battle-controls .pp-count { font-size: 1.6rem; }
#end-turn-btn .pp-pill { justify-content: center; font-size: 1.25rem; }
/* Draw and discard piles: a pixel card stack and the count, floating in the top bar like the coins (each explains itself in its title) */
.piles { display: none; gap: 12px; margin: 0 auto 0 12px; }   /* in the top bar, beside the Poké Ball */
body[data-screen="battle-screen"] .piles { display: flex; }
/* the map's floor, beside the Poké Ball like battle's piles: a pixel staircase (outlined by the drop shadows on its
   wrapper, since the clip-path would cut them off the stairs themselves) and F7 */
.floor-tag {
  display: none; align-items: center; gap: 6px; margin: 0 auto 0 12px;
  font-family: var(--pixel-font); font-synthesis-weight: none; line-height: 1;
  color: #fff8e0;
  text-shadow: 2px 2px 0 #181010, -1px -1px 0 #181010, 1px -1px 0 #181010, -1px 1px 0 #181010;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
  cursor: help;
}
body[data-screen="map-screen"] .floor-tag { display: flex; }
.floor-tag b { font-size: 1.3rem; font-weight: 400; }
.floor-stairs { display: block; filter: drop-shadow(1px 0 0 #181010) drop-shadow(-1px 0 0 #181010) drop-shadow(0 1px 0 #181010) drop-shadow(0 -1px 0 #181010) drop-shadow(2px 2px 0 #181010); }
.floor-stairs i {
  display: block; width: 18px; height: 18px; background: #fff8e0;
  clip-path: polygon(0 100%, 0 67%, 33% 67%, 33% 33%, 67% 33%, 67% 0, 100% 0, 100% 100%);
}
/* Abandon run beside the map's floor, a key on the run card's LCD like the title's (css/menus.css .title-abandon): a
   Game & Watch runner (gameWatchRunner() in js/smooth-icons.js) whose three printed segments light one at a time, in
   steps, the unlit ones left as the LCD's faint ghosts. Only over a run's map, not a Sky Pillar climb's bar */
.map-flee {
  display: none; place-items: center; width: 50px; height: 28px; margin: 0 auto 0 10px; padding: 0 3px; flex: none;
  border: 2px solid currentColor; border-radius: 4px; background: rgba(31, 58, 20, 0.08); color: #1f3a14; cursor: pointer;
  -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; user-select: none;
}
body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .map-flee { display: grid; }
body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .floor-tag { margin-right: 0; }
.map-flee svg { width: 40px; height: 18px; overflow: visible; pointer-events: none; }
.map-flee:active { translate: 0 1px; }
.map-flee:focus-visible { outline: none; background: #1f3a14; color: #c8e0a0; border-color: #1f3a14; }
@media (hover: hover) { .map-flee:hover { background: #1f3a14; color: #c8e0a0; border-color: #1f3a14; } }
.gw-seg { opacity: 0.14; }
.gw-seg:nth-child(2) { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .gw-seg { animation: gwTick 0.75s step-end infinite; }
  .gw-seg:nth-child(2) { animation-delay: -0.5s; }
  .gw-seg:nth-child(3) { animation-delay: -0.25s; }
}
@keyframes gwTick { 0% { opacity: 1; } 33.3%, 100% { opacity: 0.14; } }
/* your HP on every choice screen (showChoiceHp() in js/rewards.js): just the bar and its numbers over the scene, no
   window behind them (the user's call, 2026-10-03), the numbers outlined like the map's floor tag */
.hp-plate {
  display: none; align-items: center; gap: 6px; margin: 0 auto 0 10px;
  color: #fff8e0;
  text-shadow: 2px 2px 0 #181010, -1px -1px 0 #181010, 1px -1px 0 #181010, -1px 1px 0 #181010;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
}
body[data-screen="reward-screen"] .hp-plate { display: flex; }
.hp-plate .gb-hp-fill { transition-duration: 0.8s, 0.3s; }   /* an event's HP change runs down visibly (showHpChange())*/
.hp-plate .gb-hp { width: 96px; margin: 0; }
.hp-plate .gb-hp-track { height: 14px; padding: 2px; }
.hp-plate .gb-hp-tag { line-height: 14px; font-size: 0.75rem; }
.hp-plate .gb-hp-num { width: auto; align-self: center; font-size: 0.75rem; letter-spacing: 0.04em; white-space: nowrap; }
.pile {
  display: flex;
  align-items: center;
  gap: 4px;
  font-family: var(--pixel-font); font-synthesis-weight: none;
  color: #fff8e0;
  text-shadow: 2px 2px 0 #181010, -1px -1px 0 #181010, 1px -1px 0 #181010, -1px 1px 0 #181010;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
  line-height: 1;
  cursor: help;
}
button.pile { padding: 0; border: 0; background: none; cursor: pointer; }   /* tap for the pile's cards (openPiles()) */
button.pile:is(:hover, :focus-visible) { translate: 0 -2px; }
.pile-icon { font-size: 1rem; }   /* floating, no plate: the user preferred it smaller (2026-10-03) */
.pile b { font-size: 1.15rem; font-weight: 400; }

/* --- hand --- */
.hand-wrap { grid-area: hand; min-width: 0; padding-top: 4px; position: relative; isolation: isolate; }
/* the slide / swipe hint (showHandHint() in js/battle.js), in the gap over the fan, behind the cards, so it moves nothing.
   Wordless (the user's call, 2026-10-28: the two worded pills looked crammed): a fingertip slides along a track with an
   arrow each end, then lifts up past a chevron, on a loop. The dark ring and gold glow read over any scenery. */
.hand-hint { position: absolute; z-index: -1; top: -8px; left: 50%; width: 92px; height: 16px; translate: -50% 0; pointer-events: none;
  --hh-gold: #ffe680; --hh-ink: rgb(16 16 28 / 0.55); }
.hand-hint > i { position: absolute; display: block; }
.hh-track { left: 6px; right: 6px; top: 7px; height: 2px; border-radius: 2px; background: var(--hh-gold); box-shadow: 0 0 0 1px var(--hh-ink);
  opacity: 0; animation: hhTrack 4.4s ease-in-out infinite; }
.hh-track::before, .hh-track::after { content: ''; position: absolute; top: -3px; width: 6px; height: 6px; border: solid var(--hh-gold);
  border-width: 2px 2px 0 0; filter: drop-shadow(0 0 1px var(--hh-ink)); }
.hh-track::before { left: -1px; rotate: -135deg; }
.hh-track::after { right: -1px; rotate: 45deg; }
.hh-up { left: calc(50% - 5px); top: -22px; width: 8px; height: 8px; border: solid var(--hh-gold); border-width: 2px 0 0 2px; rotate: 45deg;
  filter: drop-shadow(0 0 1px var(--hh-ink)); opacity: 0; animation: hhUp 4.4s ease-out infinite; }
.hh-dot { left: calc(50% - 7px); top: 1px; width: 14px; height: 14px; border-radius: 50%; background: rgb(255 255 255 / 0.9);
  box-shadow: 0 0 0 2px var(--hh-ink), 0 0 8px 2px rgb(255 230 128 / 0.7); opacity: 0; animation: hhDot 4.4s ease-in-out infinite; }
@keyframes hhDot {
  0% { opacity: 0; translate: 0 0; scale: 1.3; }
  6% { opacity: 1; translate: 0 0; scale: 1; }
  18% { translate: -34px 0; }
  32% { translate: 34px 0; }
  42%, 52% { opacity: 1; translate: 0 0; scale: 1; }
  68% { opacity: 1; translate: 0 -26px; scale: 0.9; }
  76%, 100% { opacity: 0; translate: 0 -34px; scale: 0.8; }
}
.swap-hint { position: absolute; z-index: 3; left: 0; right: 0; top: var(--hint-y, 50%); translate: 0 -50%; display: flex; justify-content: center; pointer-events: none; font-size: 0.75rem; white-space: nowrap; }
.swap-hint[hidden] { display: none; }
.swap-hint > span { padding: 2px 10px; line-height: 1.2; color: #ffe680; text-shadow: 1px 1px 0 #181818; background: rgb(16 16 28 / 0.45);
  border: 1px solid rgb(255 230 128 / 0.35); border-radius: 999px; opacity: 0; animation: swapHint 4s ease-in-out 0.6s infinite; }
@keyframes swapHint { 0% { opacity: 0; transform: translateY(4px); } 15%, 60% { opacity: 1; transform: none; } 80%, 100% { opacity: 0; transform: translateY(-4px); } }
@media (prefers-reduced-motion: reduce) { .swap-hint > span { animation: none; opacity: 0.85; } }
@keyframes hhTrack { 0% { opacity: 0; } 6%, 40% { opacity: 0.85; } 50%, 100% { opacity: 0; } }
@keyframes hhUp { 0%, 48% { opacity: 0; translate: 0 6px; } 60%, 70% { opacity: 1; translate: 0 0; } 80%, 100% { opacity: 0; translate: 0 -6px; } }
.hand {
  --hand-card-w: clamp(112px, 12vw, 148px);
  display: flex;
  padding: 18px 6px 22px;
  min-height: calc(var(--hand-card-w) * 1.48 + 40px);
}
.hand > :first-child { margin-left: auto; }
.hand > :last-child  { margin-right: auto; }
/* a hovered card lifts 16px and grows 6%: leave room above it with a mouse */
@media (hover: hover) { .hand { padding-top: calc(22px + var(--hand-card-w) * 0.06); min-height: calc(var(--hand-card-w) * 1.54 + 44px); } }
@media (hover: none) { .card.in-hand:hover:not(.unplayable):not(.selected) { transform: none; } }   /* a tap leaves :hover stuck on touch screens; the picked card lifts on its own (.selected) */

.result h2 { font-size: 1.8rem; text-align: center; }
.result p { text-align: center; }

/* ============ PHONES AND SMALL SCREENS ============ */
@media (max-width: 720px) {
  .screen { padding: 14px 12px 20px; }
  .card-pool { grid-template-columns: repeat(3, 1fr); gap: 16px 10px; }

  /* battle: orb and End Turn share a row above the hand so the cards get the full width */
  #battle-screen { padding: 8px 8px 4px; gap: 6px; }
  .battle-controls { grid-template-columns: auto 1fr; grid-template-areas: "orb side" "hand hand"; gap: 4px 10px; }
  /* the PP row drops 8px away from the text box; the hand gives up 8px of its top room (a picked card lifts 10px), so the cards don't move */
  .battle-controls { margin-top: 8px; }
  .battle-controls > :is(.orb-wrap, .turn-side) { translate: 0; }
  .hand { padding-top: 10px; }
  .energy-orb { padding: 6px 7px; }
  .pp-pill { gap: 16px; padding: 10px 14px 9px; }
  .turn-side { align-items: flex-end; }
  /* Throw shows: PP | Throw | End Turn, with Throw in the middle of the screen (the user's call: it sat off to the right) */
  .battle-controls:has(.throw-btn:not([hidden])) { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-areas: "orb throw side" "hand hand hand"; }
  .battle-controls:has(.throw-btn:not([hidden])) .turn-side { display: contents; }
  .battle-controls .throw-btn { grid-area: throw; align-self: center; }
  .battle-controls:has(.throw-btn:not([hidden])) #end-turn-btn { grid-area: side; align-self: center; }
  .battle-controls .throw-btn { padding: 5px 6px; }
  .throw-btn .pp-pill { font-size: 0.8rem; gap: 4px; padding: 3px 10px 2px 6px; }
  .throw-ball-icon { width: 26px; height: 26px; }
  #end-turn-btn { padding: 6px 7px; }
  .battle-controls :is(.energy-orb, #end-turn-btn) { padding: 5px 6px; }
  .battle-controls .pp-pill { min-width: 5.9rem; height: 2.2rem; gap: 10px; padding: 7px 11px 6px; }
  .battle-controls .pp-label { font-size: 0.85rem; }
  .battle-controls .pp-count { font-size: 1.1rem; }
  #end-turn-btn .pp-pill { font-size: 0.8rem; }
  /* Safari: three equal capsules filling the row, so End Turn isn't squeezed (the user's call, 2026-10-03) */
  .battle-controls:has(.throw-btn:not([hidden])) :is(.orb-wrap, .throw-btn, #end-turn-btn) { justify-self: stretch; }
  .battle-controls:has(.throw-btn:not([hidden])) :is(.energy-orb, .throw-btn, #end-turn-btn) { width: 100%; padding: 5px 6px; }
  .battle-controls:has(.throw-btn:not([hidden])) .pp-pill { min-width: 0; height: 2.2rem; padding: 7px 8px 6px; flex-wrap: nowrap; }
  .battle-controls:has(.throw-btn:not([hidden])) #end-turn-btn .pp-pill { align-items: center; }   /* nowrap drops align-content's centring, and baseline sat the label high */
  .enemy-zone { width: 100%; }
  .nameplate { padding: 4px 8px 6px; }
  .nameplate-title strong { font-size: 0.85rem; }
  .badge { width: 30px; height: 30px; font-size: 0.95rem; }
  .badges { min-height: 32px; gap: 6px; }
  .enemy-zone { --base: clamp(80px, 13vh, 118px); }
  .hand { --hand-card-w: 108px; }
  .battle-log { width: 96%; --log-font: 0.85rem; }
}

/* Short windows (small laptops): make the battle scene a little more compact */
@media (max-height: 760px) and (min-width: 721px) {
  .enemy-zone { --base: clamp(76px, 14vh, 160px); }
  .hand { --hand-card-w: clamp(96px, 17vh, 148px); }
}

/* Tablets held upright: beside the hand, the big PP and End Turn left room for only three cards,
   so they move to a row above it like on phones and a full hand of five fits across */
@media (min-width: 721px) and (max-width: 1100px) and (orientation: portrait) {
  .battle-controls { grid-template-columns: auto 1fr; grid-template-areas: "orb side" "hand hand"; gap: 6px 12px; }
  .battle-controls > :is(.orb-wrap, .turn-side) { translate: 0; }
  .turn-side { align-items: flex-end; }
  .turn-side:has(.throw-btn:not([hidden])) { flex-direction: row; justify-content: flex-end; align-items: center; gap: 12px; }
  .hand { --hand-card-w: clamp(112px, 16vw, 160px); }
}

/* ============================================================
   THE RUN: evolution line, map, rewards, relics
   ============================================================ */


/* ---------- run card (top of the map): who you are and your HP ----------
   No box around it: like the battle screen, everything floats on the backdrop with a shadow. */
.run-card { position: relative; display: flex; align-items: center; justify-content: center; gap: 14px; padding: 4px 2px 8px; }

/* Your Pokémon floats on the scenery, with a Gold/Silver HP bar beside it:
   a black "HP:" tag, an outlined bar that goes green -> yellow -> red, and the numbers underneath */
.run-sprite { width: 76px; height: 76px; object-fit: contain; filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55)); }

/* The fidget: tap your Pokémon and it's recalled in a red beam into its ball, which sits and wobbles until you tap it
   again; then the lid pops open in a flash and it comes out white, then in colour, with its cry (toggleMon()) */
.run-mon { position: relative; flex: none; width: 76px; height: 76px; padding: 0; border: 0; background: none; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.run-mon .run-sprite { display: block; transform-origin: 50% 100%; }
.run-mon .run-ball { position: absolute; left: 50%; bottom: 2px; width: 28px; height: 28px; margin-left: -14px; transform-origin: 50% 90%; opacity: 0; pointer-events: none; filter: drop-shadow(0 3px 3px rgba(0, 0, 0, 0.5)); }
.run-mon[data-state="in"] .run-sprite { opacity: 0; }
.run-mon:not([data-state="in"], [data-state="recalling"], [data-state="releasing"]) .run-ball { animation: none; }   /* see-through, it still wobbled (menus.css's .cball-ball) */
.run-mon[data-state="in"] .run-ball { opacity: 1; animation: ballWobble 3.2s ease-in-out infinite 0.6s; }
.run-mon[data-state="recalling"] .run-sprite { animation: monRecall 0.55s ease-in forwards; }
.run-mon[data-state="recalling"] .run-ball { animation: monBallIn 0.9s ease-in-out forwards; }
.run-mon[data-state="recalling"] .cball-top { animation: monLid 0.9s steps(1) forwards; }
.run-mon[data-state="recalling"] .cball-light { animation: cballLight 0.45s ease-out 0.1s; }
.run-mon[data-state="releasing"] .run-ball { opacity: 1; animation: monBallOut 0.9s ease-in forwards; }
.run-mon[data-state="releasing"] .cball-top { transform: rotate(-38deg); }
.run-mon[data-state="releasing"] .cball-light { animation: cballLight 0.45s ease-out; }
.run-mon[data-state="releasing"] .run-sprite { animation: monRelease 0.6s ease-out 0.2s backwards; }
@keyframes monRecall {
  0% { transform: none; filter: none; }
  30% { transform: none; filter: brightness(0.7) sepia(1) saturate(9) hue-rotate(-40deg); }
  100% { transform: scale(0.1); opacity: 0; filter: brightness(0.7) sepia(1) saturate(9) hue-rotate(-40deg); }
}
@keyframes monLid { 0% { transform: rotate(-38deg); } 70% { transform: none; } }
@keyframes monBallIn { 0% { opacity: 1; transform: none; } 70% { transform: none; } 80% { transform: rotate(-18deg); } 90% { transform: rotate(12deg); } 100% { opacity: 1; transform: none; } }
@keyframes monBallOut { 0%, 30% { opacity: 1; transform: none; } 100% { opacity: 0; transform: scale(0.2); } }
@keyframes monRelease {
  0% { transform: scale(0.2); filter: brightness(0) invert(1); }
  60% { transform: scale(1.12); filter: brightness(0) invert(1); }
  100% { transform: none; filter: none; }
}
@media (prefers-reduced-motion: reduce) {
  .run-mon .run-sprite, .run-mon .run-ball, .run-mon .cball-top, .run-mon .cball-light { animation: none !important; }
}
.gb-hp { --hp-color: #48c848; display: flex; align-items: center; width: min(190px, 100%); margin-top: 3px; }
.gb-hp[data-level="mid"] { --hp-color: #f8c030; }
.gb-hp[data-level="low"] { --hp-color: #f84830; }
.gb-hp-tag {
  font-family: var(--pixel-font); font-synthesis-weight: none;
  padding: 0 4px 0 5px;
  border: 2px solid #181818;
  border-right: 0;
  border-radius: 6px 0 0 6px;
  background: #181818;
  color: #f8b030;
  font-size: 0.75rem;
  font-weight: 900;
  line-height: 16px;
}
.gb-hp-track {
  flex: 1;
  height: 16px;
  padding: 3px;
  border: 2px solid #181818;
  border-radius: 0 8px 8px 0;
  background: #f8f8f0;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.45);
}
/* scaled, not resized, and eased, not stepped (the user found the 12-step drain choppy): it runs on the GPU */
.gb-hp-fill { display: block; height: 100%; width: 100%; background: var(--hp-color); transform: scaleX(var(--hp, 1)); transform-origin: left; transition: transform 0.6s cubic-bezier(0.25, 0.8, 0.3, 1), background 0.3s; }
.gb-hp-num { font-family: var(--pixel-font); font-synthesis-weight: none; align-self: flex-start; width: min(190px, 100%); text-align: right; font-size: 0.9rem; font-weight: 900; letter-spacing: 0.08em; font-variant-numeric: tabular-nums; }

.run-info { flex: 0 1 auto; display: flex; flex-direction: column; gap: 3px; width: 222px; min-width: 0; text-shadow: 0 1px 3px #000, 0 2px 10px rgba(0, 0, 0, 0.6); }
.run-info strong { font-size: 1.1rem; }
/* the name starts where the bar does: an invisible copy of the "HP:" tag in front of it */
.run-info .run-name { gap: 0; }
.run-info .run-name::before { content: "HP:"; visibility: hidden; flex: none; font-family: var(--pixel-font); font-size: 0.75rem; font-weight: 900; padding: 0 4px 0 5px; border-left: 2px solid transparent; }
.run-info .run-name strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.run-info .gb-hp, .run-info .run-foot { width: 100%; }
/* the map's "HP:" tag sits on the bar's cream, not black */
.run-bars .gb-hp-tag { background: #f8f8f0; color: #e06818; text-shadow: none; box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.45); }
/* the Level chip sits under the bars, left of the HP numbers, so the name row stays short */
.run-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; width: min(190px, 100%); }
.run-foot .gb-hp-num { width: auto; }
.run-foot .level-chip { font-size: 0.75rem; padding: 1px 8px; cursor: help; }
.sel-ability .item-sprite { width: 1.5em; height: 1.5em; margin: -0.3em 0; }
/* The Ability is a pill in the starter's colour left of the Level chip (tap for its text). Blaze only counts below half
   HP: the pill is dim until then, then it glows and bobs and your Pokémon flickers with flame */
/* Always alive: a soft glow breathing in its type colour and a sheen of light sweeping across every few seconds. Both
   are layers moved by transform and opacity (the sheen inside .ability-shine, which run.js and battle.js put in the
   chip), which the compositor animates: animating its background and box-shadow repainted it every frame of a fight,
   on the thread the played cards and the 3D arena share (2026-10-18). */
.run-ability {
  flex: none; cursor: help; margin-right: auto; font-size: 0.75rem; padding: 1px 8px; border: 1px solid;
  position: relative; isolation: isolate;
}
.run-ability::after {
  content: ""; position: absolute; inset: -1px; z-index: -1; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 5px var(--glow, currentColor); opacity: 0; animation: abilityGlow 2.6s ease-in-out infinite;
}
.ability-shine { position: absolute; inset: 0; z-index: -1; border-radius: inherit; overflow: hidden; pointer-events: none; }
.ability-shine::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 60%; transform: translateX(-170%);
  background: linear-gradient(105deg, transparent, rgba(255, 255, 255, 0.28) 50%, transparent);
  animation: abilitySheen 4.5s ease-in-out infinite;
}
.run-ability[data-type="grass"]   { background-color: #1c5a2c; color: #b8f0c0; border-color: #62d474; }
.run-ability[data-type="fire"]    { background-color: #6a3008; color: #ffd0a0; border-color: #ffa650; }
.run-ability[data-type="water"]   { background-color: #173a78; color: #cfe2ff; border-color: #6aaaf8; }
.run-ability[data-type="psychic"] { background-color: #4e1666; color: #f0c8ff; border-color: #d670f0; }
.run-ability[data-type="electric"] { background-color: #5c4800; color: #fff3b0; border-color: #f8d030; }
.run-ability[data-type="ice"] { background-color: #124a5c; color: #d8f6ff; border-color: #78d8f0; }
.run-ability[data-type="fighting"] { background-color: #5c1c10; color: #ffdccc; border-color: #f08060; }
.run-ability[data-type="ground"] { background-color: #4a3414; color: #fbe8c0; border-color: #e0b060; }
.run-ability[data-type="flying"] { background-color: #24205c; color: #e8e4ff; border-color: #a8a0f8; }
.run-ability[data-type="dark"] { background-color: #2a201c; color: #f0e4da; border-color: #a88c74; }
@keyframes abilitySheen { 0%, 55% { transform: translateX(-170%); } 100% { transform: translateX(170%); } }
@keyframes abilityGlow { 50% { opacity: 1; } }
.run-ability[data-type="grass"]   { --glow: #62d474; }
.run-ability[data-type="fire"]    { --glow: #ffa650; }
.run-ability[data-type="water"]   { --glow: #6aaaf8; }
.run-ability[data-type="psychic"] { --glow: #d670f0; }
.run-ability[data-type="electric"] { --glow: #f8d030; }
.run-ability[data-type="ice"] { --glow: #78d8f0; }
.run-ability[data-type="fighting"] { --glow: #f08060; }
.run-ability[data-type="ground"] { --glow: #e0b060; }
.run-ability[data-type="flying"] { --glow: #a8a0f8; }
.run-ability[data-type="dark"] { --glow: #a88c74; }
.run-ability[data-state="off"] { filter: saturate(0.7) brightness(0.85); }
.run-ability[data-state="on"] { box-shadow: 0 0 6px #ff5010; animation: blazeCapsule 0.8s steps(2) infinite; }
.run-ability[data-state="on"]::after { animation: none; }
.run-ability[data-state="on"] .ability-shine::before { animation-duration: 1.8s; }
@keyframes blazeCapsule { 50% { translate: 0 -2px; } }
.run-sprite[data-blaze] { animation: blazeAura 0.5s steps(1) infinite; }
@keyframes blazeAura {
  0% { filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 3px #ff7a18) drop-shadow(0 -2px 2px #ffb020); }
  50% { filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 5px #ff5010) drop-shadow(0 -4px 3px #ffd040); }
}
@media (prefers-reduced-motion: reduce) {
  .run-ability, .run-ability[data-state="on"], .run-ability::after, .ability-shine::before { animation: none; }
  .run-sprite[data-blaze] { animation: none; filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 4px #ff7a18); }
}

/* HP and Gold/Silver's thin blue EXP bar share one tag, the EXP flush under the HP */
.run-bars { align-items: stretch; }
/* the tag runs down beside the EXP bar too, so HP and EXP read as one block */
.run-bars .gb-hp-tag { border-radius: 6px 0 0 6px; display: flex; align-items: center; }
.gb-bars { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.gb-bars .gb-hp-track { flex: none; }
.gb-exp { display: block; height: 10px; padding: 2px; border: 2px solid #181818; border-top: 0; border-radius: 0 0 6px 0; background: #f8f8f0; box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.45); cursor: help; margin-top: -2px; }
.gb-exp-fill { display: block; height: 100%; width: 0; background: #3890f8; transition: width 0.6s ease-out; }

/* The Bag button: a frameless pixel backpack in the top-right corner beside the coins and the Poké Mart.
   Shown only on run screens (showScreen() in js/ui.js); open (aria-expanded) looks pressed in. */
.bag-btn {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: none;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55));
  transition: transform 0.1s ease-out, filter 0.1s;
}
.bag-btn:hover { transform: translateY(-2px); }
.bag-btn[aria-expanded="true"], .bag-btn:active { transform: translateY(2px) scale(0.9); filter: brightness(0.85) drop-shadow(0 1px 1px rgba(0, 0, 0, 0.55)); }

/* ---------- the biome's name: a pixel location sign, like the one the games show when you enter an area ---------- */
.map-head { display: flex; flex-direction: column; align-items: center; gap: 10px; margin: 12px 0 14px; }
/* the Silph Scope button (a complete Pokédex's prize): a small Pokégear capsule, "1/1" reveals left, lying in the map's
   bottom-left corner (routes start from the middle, so it's always free). It's the map's one in-flow child, set down in the
   corner by the map's flex column (not a top margin: a sticky box won't move its margin out of the map), and sticky, so on a
   tall map scrolled up it waits at the screen's bottom instead. */
.map:has(> .map-tools > .scope-btn:not([hidden])) { display: flex; flex-direction: column; justify-content: flex-end; }
.map > .map-tools { position: sticky; bottom: calc(max(10px, env(safe-area-inset-bottom)) + 4px); z-index: 3; margin: 0 0 12px 12px; display: flex; gap: 8px; width: fit-content; }
/* Unown Rubbing (the Ruins page's perk) sits beside the Scope, the same capsule */
.rubbing-icon { display: grid; place-items: center; width: 32px; height: 32px; font-size: 22px; line-height: 1; }
.scope-btn {
  display: flex;
  width: fit-content;
  height: 44px;
  align-items: center;
  gap: 6px;
  padding: 3px 12px 3px 6px;
  border: 3px solid #b8b8c8;
  border-radius: 999px;
  background: var(--win-bg);
  color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, 2px 3px 0 2px rgba(0, 0, 0, 0.35);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 0.75rem;
  cursor: pointer;
}
.scope-btn[hidden] { display: none; }
.scope-icon .item-sprite { display: block; width: 32px; height: 32px; image-rendering: pixelated; }
.scope-btn:disabled { filter: grayscale(1); opacity: 0.6; cursor: default; }
.scope-btn.on { border-color: var(--gold); animation: scopeBlink 0.9s steps(1) infinite; }
@keyframes scopeBlink { 50% { border-color: #fff; } }
.biome-sign {
  --plank: #b0682c;
  --plank-dark: #95521f;
  --rim: #d89050;
  --frame: #3e1e0c;
  --nail: #3e1e0c;
  --text: #fff4d6;
  position: relative;
  margin: 0;
  padding: 7px 22px 8px;
  border: 3px solid var(--frame);
  background:
    linear-gradient(var(--nail), var(--nail)) 5px 5px / 4px 4px no-repeat,
    linear-gradient(var(--nail), var(--nail)) calc(100% - 5px) 5px / 4px 4px no-repeat,
    linear-gradient(var(--nail), var(--nail)) 5px calc(100% - 5px) / 4px 4px no-repeat,
    linear-gradient(var(--nail), var(--nail)) calc(100% - 5px) calc(100% - 5px) / 4px 4px no-repeat,
    repeating-linear-gradient(180deg, var(--plank) 0 7px, var(--plank-dark) 7px 9px);
  box-shadow: inset 0 0 0 2px var(--rim), 4px 4px 0 rgba(0, 0, 0, 0.45);
  color: var(--text);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 1.45rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.1;
  text-align: center;
  text-shadow: 2px 2px 0 var(--frame);
}
.biome-sign[data-biome="shrine"] { --plank: #6f7f62; --plank-dark: #5b6a50; --rim: #9aae84; --frame: #1f2a18; --nail: #2f4a24; --text: #eef8dc; }
.biome-sign[data-biome="ruins"] { --plank: #4f7472; --plank-dark: #3f5e5c; --rim: #8cc8c0; --frame: #102422; --nail: #d8c890; --text: #e0fbf6; animation: runeGlint 3.4s steps(2) infinite; }   /* sea-worn stone, its runes waking now and then */
.biome-sign[data-biome="ruins"].arrive { animation: signDrop 0.7s ease-out both, runeGlint 3.4s steps(2) 0.7s infinite; }
@keyframes runeGlint { 50% { box-shadow: inset 0 0 0 2px #b8fff4, 4px 4px 0 rgba(0, 0, 0, 0.45), 0 0 8px rgba(110, 240, 224, 0.5); } }
.biome-sign[data-biome="thornwood"] { --plank: #3e5a2a; --plank-dark: #30481f; --rim: #8cc850; --frame: #12200c; --nail: #c8e070; --text: #eaffd0; }
.biome-sign[data-biome="savanna"] { --plank: #a8743a; --plank-dark: #8a5c2a; --rim: #f0c040; --frame: #2a1a08; --nail: #f86a20; --text: #fff4d0; }   /* sun-bleached wood, a gold rim */
.biome-sign[data-biome="wastes"] { --plank: #54403a; --plank-dark: #43322d; --rim: #e0602a; --frame: #1c1210; --nail: #f8a030; --text: #ffe0b0; }
.biome-sign[data-biome="depths"] { --plank: #3a2c5c; --plank-dark: #2c2148; --rim: #7ae8ff; --frame: #120a22; --nail: #ff6ac8; --text: #eadcff; animation: crystalGlint 2.6s steps(2) infinite; }   /* a slab of amethyst, glinting cyan */
.biome-sign[data-biome="depths"].arrive { animation: signDrop 0.7s ease-out both, crystalGlint 2.6s steps(2) 0.7s infinite; }
@keyframes crystalGlint { 50% { box-shadow: inset 0 0 0 2px #ff6ac8, 4px 4px 0 rgba(0, 0, 0, 0.45), 0 0 8px rgba(122, 232, 255, 0.55); } }
.biome-sign[data-safari] { --plank: #3e8a3a; --plank-dark: #317030; --rim: #f0d878; --frame: #183a14; --nail: #f0d878; --text: #fff8d8; }   /* the Safari Zone's green signboard */
.biome-sign.arrive { animation: signDrop 0.7s ease-out both; }
/* the place you stand in, a little board hung from the biome sign on two cords; it swings in when you reach a new one */
.stage-sign {
  --plank: #c88040; --frame: #3e1e0c; --text: #fff4d6; --cord: #3e1e0c;
  position: relative;
  margin: -2px 0 0;
  padding: 4px 12px 5px;
  border: 3px solid var(--frame);
  background: var(--plank);
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.18), 3px 3px 0 rgba(0, 0, 0, 0.45);
  color: var(--text);
  font-size: 0.75rem;
  line-height: 1.1;
  letter-spacing: 0.04em;
  text-shadow: 1px 1px 0 var(--frame);
  transform-origin: 50% -12px;
}
.stage-sign:empty { display: none; }
.stage-sign::before, .stage-sign::after {
  content: '';
  position: absolute;
  top: -13px;
  width: 3px;
  height: 10px;
  background: var(--cord);
}
.stage-sign::before { left: 14px; }
.stage-sign::after { right: 14px; }
.stage-sign[data-biome="shrine"] { --plank: #7f8f70; --frame: #1f2a18; --text: #eef8dc; --cord: #c8b070; }
.stage-sign[data-biome="ruins"] { --plank: #5f8482; --frame: #102422; --text: #e0fbf6; --cord: #c8b070; }
.stage-sign[data-biome="thornwood"] { --plank: #4e6a38; --frame: #12200c; --text: #eaffd0; --cord: #8a6a3a; }
.stage-sign[data-biome="savanna"] { --plank: #b8844a; --frame: #2a1a08; --text: #fff4d0; --cord: #6a4220; }
.stage-sign[data-biome="wastes"] { --plank: #64504a; --frame: #1c1210; --text: #ffe0b0; --cord: #1c1210; }
.stage-sign[data-biome="depths"] { --plank: #4a3a74; --frame: #120a22; --text: #eadcff; --cord: #7ae8ff; }
.stage-sign[data-safari] { --plank: #d8b070; --frame: #3a2410; --text: #fff8e0; --cord: #3a2410; }
.stage-sign[data-stage="3"] { --plank: #a02c20; --text: #fff0c0; }   /* the boss's arena */
.stage-sign.arrive { animation: stageSwing 0.9s ease-out both; }
@keyframes stageSwing {
  from { transform: rotate(-14deg); opacity: 0; }
  30%  { transform: rotate(9deg); opacity: 1; }
  60%  { transform: rotate(-4deg); }
  80%  { transform: rotate(2deg); }
  to   { transform: none; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .stage-sign.arrive { animation: none; } }
@keyframes signDrop {
  from { transform: translateY(-24px); opacity: 0; }
  60%  { transform: translateY(3px); opacity: 1; }
  to   { transform: none; opacity: 1; }
}

/* ---------- the map's drop-downs (Relics, Key) ---------- */
.drop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 5;
  width: min(340px, calc(100vw - 24px));
  padding: 12px;
  border-radius: var(--round);
  border: 3px solid #b8b8c8;
  background: #171b3d;   /* solid: a blur can't see out of the run card, so a see-through panel shows the map through it */
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 0 12px 30px rgba(0, 0, 0, 0.55);
  animation: menuDrop 0.16s ease-out;
}
.drop .howto-list { grid-template-columns: 1fr; gap: 6px; }
.drop .howto-li { padding: 5px 10px; gap: 10px; border-radius: var(--round-sm); }
.drop .howto-li:last-child:nth-child(2n+1) { width: auto; justify-self: stretch; }   /* one column: an odd last row is full width too */
.drop .howto-node { width: 34px; height: 34px; font-size: 1.35rem; }
.drop-note { margin-top: 10px; font-size: 0.78rem; line-height: 1.35; color: var(--muted); text-align: center; }
.drop-empty { font-size: 0.85rem; color: var(--muted); text-align: center; padding: 4px 0; }

/* ---------- the Bag: Deck, Relics and the map Key in one drop-down ----------
   Styled after the Gold/Silver Bag screen: a cream menu in the grey frame, a "◀ pocket ▶"
   header, pocket tabs you can tap, and a blinking ▲ cursor under the open pocket. */
.bag-sprite { width: 32px; height: 32px; }
.bag { padding: 10px; font-family: var(--pixel-font); font-synthesis-weight: none; background: var(--win-bg); color: var(--win-ink); }
.bag-head { display: flex; align-items: center; justify-content: space-between; background: #283060; box-shadow: inset 0 0 0 2px #303038; }
.bag-head strong { font-size: 0.95rem; letter-spacing: 0.14em; text-transform: uppercase; color: #fff; }
.bag-flip { width: 36px; height: 34px; padding: 0; border: 0; background: none; color: #f8d030; font-size: 0.95rem; animation: bagBlink 1s steps(1) infinite; }
.bag-flip:hover { color: #fff; }
@keyframes bagBlink { 50% { opacity: 0.35; } }
.bag-pockets { display: flex; justify-content: center; gap: 12px; margin: 12px 0 20px; }
.bag-pocket {
  position: relative;
  width: 54px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border-radius: var(--round-sm);
  border: 3px solid var(--win-edge);
  background: var(--win-panel);
  box-shadow: 2px 2px 0 var(--win-shadow);
  font-size: 1.3rem;
}
.bag-pocket[aria-selected="true"] { border-color: #f89030; background: var(--win-tile); transform: translateY(-3px); box-shadow: 2px 5px 0 var(--win-shadow); }
.bag-pocket[aria-selected="true"]::after {
  content: '▲';
  position: absolute;
  left: 50%;
  bottom: -19px;
  transform: translateX(-50%);
  font-size: 0.75rem;
  color: var(--win-ink);
  animation: bagBlink 1s steps(1) infinite;
}
.bag-pocket b {
  position: absolute;
  right: -9px;
  top: -9px;
  min-width: 22px;
  height: 20px;
  padding: 0 4px;
  display: grid;
  place-items: center;
  border: 2px solid #f89030;
  background: #402010;
  color: #fff;
  font-size: 0.75rem;
  font-weight: 900;
}
.bag .howto-li { background: none; border: 0; border-bottom: 2px dashed var(--win-edge); }
.bag .howto-li:last-child { border-bottom: 0; }
.bag .howto-li-text small, .bag .drop-note, .bag .drop-empty { color: var(--win-muted); }
.bag-deck-text { margin: 4px 0 12px; font-size: 0.9rem; text-align: center; }
.bag #run-deck-btn { width: 100%; }

/* ---------- the map: a Pokégear-style town map ----------
   js/map.js paints terrain and routes onto a small canvas scaled up with sharp pixels,
   and lays the rooms over it. --grid-w / --grid-h (set by js/map.js) are the size in tiles,
   so --tile is one tile of the map's width and everything on it scales together. */
#map-screen { max-width: 1100px; }
.map-wrap { padding: 10px; }
.map {
  --tile: calc(100% / var(--grid-w, 37));
  position: relative;
  container-type: inline-size;
  width: min(100%, calc(78vh * var(--grid-w, 37) / var(--grid-h, 70)));
  aspect-ratio: var(--grid-w, 37) / var(--grid-h, 70);
  margin: 0 auto;
  background: #58c040;
  /* a chunky grey frame, like the Pokégear's */
  box-shadow: 0 0 0 3px #303038, 0 0 0 7px #b8b8c8, 0 0 0 10px #303038, 0 12px 30px 10px rgba(0, 0, 0, 0.45);
}
.map-terrain { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; }
.map-routes { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
@media (min-width: 721px) { .map { width: min(100%, calc(var(--grid-w, 37) * 11px)); } }   /* WIDE_TILE in js/map.js */
/* The Bag's look at the map from a battle or a reward (openMapPeek() in js/run.js): smaller, to fit a window */
.map-peek-wrap { padding: 12px; overflow: auto; }
.map-peek { width: min(100%, calc(66vh * var(--grid-w, 37) / var(--grid-h, 70)), calc(var(--grid-w, 37) * 11px)); box-shadow: 0 0 0 3px #303038, 0 0 0 7px #b8b8c8, 0 0 0 10px #303038; }
#bag-map-btn { width: 100%; margin-bottom: 8px; }
@media (min-width: 721px) { .map-trainer { scroll-margin: 40px 0 60px; } }   /* showMap()'s scrollIntoView left its feet on the screen's edge */

/* A room: the button is a tap target one tile bigger than the town square drawn inside it */
.map-node {
  position: absolute;
  z-index: 1;
  transform: translate(-50%, -50%);
  width: calc(var(--tile) * 5);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: none;
  cursor: default;
}
.map-town {
  width: 60%;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  background: #402010;                                  /* the dark inner square */
  border: calc(100cqw / var(--grid-w, 37) * 0.5) solid #f89030;   /* the orange outer square */
  box-shadow: 0 0 0 1px #582808, 2px 2px 0 1px rgba(0, 0, 0, 0.35);
  font-size: calc(100cqw / var(--grid-w, 37) * 1.35);
  line-height: 1;
}
.map-node.type-elite .map-town { border-color: #f04038; }
.map-node.type-boss { width: calc(var(--tile) * 6); }
.map-node.type-boss .map-town { width: 84%; border-color: var(--gold); background: #4a2670; font-size: calc(100cqw / var(--grid-w, 37) * 2.4); box-shadow: 0 0 0 2px #6b4b00, 3px 3px 0 1px rgba(0, 0, 0, 0.35); }
.map-node.visited .map-town { border-color: #a89880; background: #504840; filter: grayscale(0.7); opacity: 0.8; }
.map-node.current .map-town { border-color: var(--gold); filter: none; opacity: 1; }
.map-node.reachable { cursor: pointer; }
.map-node.reachable .map-town { position: relative; }
/* the blink is a white ring over the border, faded in and out: an opacity the compositor runs, where a blinking
   border-color restyled the whole map every frame (2026-10-21) */
.map-node.reachable .map-town::after { content: ''; position: absolute; inset: calc(100cqw / var(--grid-w, 37) * -0.5);
  border: calc(100cqw / var(--grid-w, 37) * 0.5) solid #fff; border-radius: inherit; opacity: 0; pointer-events: none;
  animation: townBlink 0.9s steps(1) infinite; }
.map-node.reachable:hover .map-town, .map-node.reachable:focus-visible .map-town { border-color: #fff; transform: scale(1.12); }
@keyframes townBlink { 50% { opacity: 1; } }
/* picking a room for the Silph Scope: the fight rooms it can reveal blink gold, the rest fade back */
.map.scoping .map-node:not(.scope-pick) { opacity: 0.45; }
.map-node.scope-pick { cursor: pointer; }
.map-node.scope-pick .map-town { border-color: var(--gold); animation: scopePick 0.7s steps(1) infinite; }
.map-node.scope-pick:hover .map-town, .map-node.scope-pick:focus-visible .map-town { transform: scale(1.15); }
@keyframes scopePick { 50% { border-color: #fff; box-shadow: 0 0 0 2px var(--gold); } }
/* a revealed room's Pokémon stands above it in full colour, like the boss above its room, with its type beside it */
/* a Safari rare spawn's room: a gold star over it (js/map.js), with a soft glow that swells as it bobs and twinkles; slow
   and eased so it catches the eye without flashing. The prep window's rare-spawn rule shows the same star (.inline) */
.map-rare { color: #f8d030; font-size: 22px; line-height: 1; pointer-events: none;
  text-shadow: 1px 1px 0 #303038, -1px -1px 0 #303038, 1px -1px 0 #303038, -1px 1px 0 #303038;
  filter: drop-shadow(0 0 3px rgba(255, 224, 96, 0.7)); animation: rareTwinkle 2.2s ease-in-out infinite; }
/* the map's floating icons are buttons of their own beside their room (js/map.js's floater()), so a tap on one says what
   it is in a bubble (.map-tip; the user's ask, 2026-10-18); a wider invisible ring makes them easy to hit on a phone */
.map-float { position: absolute; z-index: 3; padding: 0; border: 0; background: none; font-family: inherit;
  transform: translate(-50%, -50%); margin-top: -12px; pointer-events: auto; cursor: pointer; }
.map-float::after { content: ''; position: absolute; inset: -8px; }
.map-tip { position: absolute; z-index: 6; width: max-content; max-width: min(230px, 72%); padding: 6px 9px;
  transform: translate(calc(-50% + var(--dx, 0px)), calc(-100% - 26px)); background: #fffbe8; color: #302820;
  border: 2px solid #302820; border-radius: 6px; box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.35); font-size: 0.75rem;
  line-height: 1.4; text-align: left; pointer-events: none; }
.map-tip.below { transform: translate(calc(-50% + var(--dx, 0px)), 18px); }
/* z-index: auto, since a grid item (the Safari prep's rule icon) honours z-index even unpositioned and drew over the sticky Poké Ball bar */
.map-rare.inline { position: static; z-index: auto; display: inline-block; font-size: 1.25rem; }
.dialog .map-rare.inline { text-shadow: 1px 1px 0 #303038, -1px -1px 0 #303038, 1px -1px 0 #303038, -1px 1px 0 #303038; }
@keyframes rareTwinkle {
  0%, 100% { translate: 0 0; scale: 1; color: #f8d030; }
  50% { translate: 0 -3px; scale: 1.15; color: #fff4b0; }
}
/* a badge's glow swells as a halo behind it fading in and out, not as an animated drop-shadow: a filter animation
   repainted on the main thread every frame (2026-10-21: ~200 ms a second on a Safari run's map) */
.map-sparkle::before, .map-grass::before { content: ''; position: absolute; inset: -9px; z-index: -1; border-radius: 50%;
  background: radial-gradient(circle, transparent 0 48%, var(--halo) 58%, transparent 72%); opacity: 0; pointer-events: none;
  animation: glintHalo 2.2s ease-in-out infinite; }
@keyframes glintHalo { 50% { opacity: 1; } }
/* a town's material on the map: a glowing badge on its room's top-right corner (floater() in js/map.js).
   It floated 24px above the room until 2026-10-18, pale on the grass: the user couldn't
   see it, and it read as hanging between rooms */
.map-sparkle { --halo: rgba(170, 240, 255, 0.9); width: 24px; height: 24px; margin-top: 0;
  display: grid; place-items: center; border-radius: 50%; border: 2px solid #c8f6ff; box-sizing: border-box;
  background: radial-gradient(circle, #2a6aa8 0 45%, #0c2440 100%); color: #fff; font-size: 15px;
  text-shadow: 0 0 3px #8ae8ff; animation-name: sparkleGlint; filter: drop-shadow(0 0 2px rgba(140, 230, 255, 0.7)) drop-shadow(0 0 1px #0c2440); }
@keyframes sparkleGlint {
  0%, 100% { translate: 0 0; scale: 1; }
  50% { translate: 0 -2px; scale: 1.18; }
}
/* a town's Waystone Shard on its Alpha's top-right corner, like a material's badge (2026-10-18: it floated above, between rooms): a crystal in the town's colour (--gem), turning as it bobs */
.map-duo { margin-top: 0; width: 14px; height: 14px; padding: 0; border-radius: 50%; box-shadow: 0 0 0 1.5px #fff, 0 0 4px 1px rgba(255, 255, 255, 0.7); animation: sparkleGlint 2.2s ease-in-out infinite; }
.map-duo { display: grid; place-items: center; font-size: 0; line-height: 0; }   /* no text line to push the badge out of its ring */
.map-duo .type-badge { display: block; width: 100%; height: 100%; }
.map-shard { margin-top: 0; animation-name: shardBob; animation-duration: 2.6s; filter: drop-shadow(0 0 4px var(--gem)) drop-shadow(0 0 1px #fff); }
.map-shard-gem { display: inline-block; width: 14px; height: 22px; clip-path: polygon(50% 0, 100% 38%, 50% 100%, 0 38%);
  background: linear-gradient(115deg, #fff 0 22%, var(--gem) 23% 58%, color-mix(in srgb, var(--gem) 55%, #102030) 59%); }
@keyframes shardBob {
  0%, 100% { translate: 0 0; scale: 1 1; }
  25% { scale: 0.55 1; }
  50% { translate: 0 -4px; scale: 1 1; }
  75% { scale: 0.55 1; }
}
/* a Safari rare spawn: rustling grass (rareMark() in js/ui.js) in a gold-rimmed badge on its room's top-right corner, like a
   material's (2026-10-20, the user's ask: the gold ✦ floating above read as a shiny and hung between rooms). It shakes like
   the games' rustling grass instead of twinkling. .inline is the same badge in the Safari's rules, the Duo Run's areas and a
   rare's nameplate in battle until 2026-10-28 (now a running figure in its status row, .badge.flee) */
.rare-mark { display: inline-grid; place-items: center; width: 24px; height: 24px; box-sizing: border-box; border-radius: 50%;
  border: 2px solid #f8d030; background: radial-gradient(circle, #fffbe0 0 50%, #e8f0b0 100%); box-shadow: 0 0 0 1px #303038;
  vertical-align: middle; }
.rare-mark svg { width: 16px; height: auto; image-rendering: pixelated; animation: grassRustle 1.1s steps(1) infinite; }
.map-grass { --halo: rgba(255, 224, 96, 0.85); margin-top: 0; color: inherit; text-shadow: none; animation: sparkleGlint 2.2s ease-in-out infinite;
  filter: drop-shadow(0 0 3px rgba(255, 224, 96, 0.8)); }
.rare-mark.inline { width: 20px; height: 20px; }
.rare-mark.inline svg { width: 13px; }
@keyframes grassRustle { 0%, 100% { transform: none; } 25% { transform: translateX(-1px) rotate(-6deg); } 50% { transform: none; } 75% { transform: translateX(1px) rotate(6deg); } }
@media (prefers-reduced-motion: reduce) { .map-rare, .rare-mark svg, .map-sparkle::before, .map-grass::before { animation: none; } }
/* a friend's grave (js/graves.js, drawGraves() in js/map.js): a pixel tombstone by its room's foot, a wisp drifting over
   it till you've left flowers; on the Sky Pillar (.tw-grave) by the door they went through */
.map-grave, .tw-grave { position: absolute; z-index: 2; padding: 0; border: 0; background: none; cursor: pointer; filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, 0.4)); }
.map-grave { transform: translate(-50%, -50%); width: calc(var(--tile) * 2.4); aspect-ratio: 12 / 14; }
.map-grave svg, .tw-grave svg { display: block; width: 100%; height: 100%; }
.map-grave:disabled { cursor: default; }
.map-grave:not(:disabled):is(:hover, :focus-visible) { transform: translate(-50%, -50%) scale(1.15); }
.tw-grave:is(:hover, :focus-visible) { scale: 1.15; transform-origin: 50% 100%; }
.map-grave-wisp { position: absolute; left: 50%; top: -45%; width: 45%; aspect-ratio: 1; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(220, 240, 255, 0.95) 0 28%, rgba(140, 190, 255, 0.45) 55%, transparent 72%);
  translate: -50% 0; opacity: 0.6; animation: graveWisp 3.2s ease-in-out infinite; }
.map-grave.flowers .map-grave-wisp, .tw-grave.flowers .map-grave-wisp { display: none; }
@keyframes graveWisp { 0%, 100% { translate: -50% 0; opacity: 0.3; } 50% { translate: -50% -45%; opacity: 0.9; } }
@media (prefers-reduced-motion: reduce) { .map-grave-wisp { animation: none; } }
.calm-fx .map-grave-wisp { animation: none; }
.grave-dialog .grave-keys { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.grave-dialog .grave-keys form { margin: 0; }
.grave-dialog .grave-keys .btn {
  border: 0; background: var(--shell-lo); color: #fff; text-shadow: 1px 1px 0 var(--shell-deep);
  box-shadow: inset 0 0 0 2px var(--shell-rim), 0 3px 0 var(--shell-deep);
}
.grave-dialog .grave-keys .btn:disabled { opacity: 0.6; }
.grave-dialog .grave-said { min-height: 1.2em; margin: 10px 0 0; }
.grave-dialog .grave-said:empty { display: none; }
/* Kenmatta's face for his dojo's room once he's been beaten: a 26x26 crop of Alder's sprite (62x66), head and spiky hair */
.ken-face { display: block; width: 1.25em; aspect-ratio: 1; background: url(../assets/trainers/alder.png) 47.22% 12.5% / 238.46% 253.85% no-repeat;
  image-rendering: pixelated; }
.ken-face[hidden] { display: none; }
.map-node.read .map-town { border-color: #8cc8c0; }
/* Tracker's Eye (Thornwood's page): a wild fight's type in a red ring when it beats yours, green when yours beats it */
.map-match { position: absolute; top: -6px; right: -8px; z-index: 2; display: grid; place-items: center; width: 22px; height: 22px; border: 2px solid #f04038; border-radius: 50%; background: #2a1818; font-size: 12px; line-height: 1; pointer-events: none; }
.map-match.weak { border-color: #58c058; background: #18281a; }
.map-node.ken .map-town { background: #f8e8c8; overflow: hidden; }
.map-node.ken .ken-face { width: 100%; }
.unlock-stage .ken-face { width: 104px; animation: unlockHop 0.9s ease-in-out infinite; transform-origin: 50% 100%; }
@media (prefers-reduced-motion: reduce) { .unlock-stage .ken-face { animation: none; } }
.map-revealed {
  position: absolute;
  z-index: 1;
  width: calc(var(--tile) * 7);   /* on the figure, not the img: --tile is a share of the map's width */
  transform: translate(-50%, -100%);
  margin-top: calc(var(--tile) * 0.9);   /* the GIFs pad their Pokémon's feet: this stands them on the room's top edge */
  pointer-events: none;
}
.map-revealed-sprite { display: block; width: 100%; image-rendering: pixelated; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.35)); }
.map-revealed-type {
  position: absolute;
  right: 12%;
  bottom: 22%;
  font-size: calc(100cqw / var(--grid-w, 37) * 1.5);
  line-height: 1;
  filter: drop-shadow(1px 0 0 #181010) drop-shadow(-1px 0 0 #181010) drop-shadow(0 1px 0 #181010) drop-shadow(0 -1px 0 #181010);
}
/* Poké Marts and Pokémon Centers stand on the map as little buildings (js/buildings.js) instead of a framed square */
.map-node.type-shop, .map-node.type-rest { width: calc(var(--tile) * 4); }
.map-building { display: block; width: 100%; filter: drop-shadow(2px 3px 0 rgba(0, 0, 0, 0.35)); transition: transform 0.1s; }
.map-building svg { display: block; width: 100%; height: auto; }
.map-node.reachable .map-building { animation: houseBlink 0.9s steps(1) infinite; }
@keyframes houseBlink { 50% { filter: brightness(1.2) drop-shadow(0 0 1px #fff) drop-shadow(0 0 1px #fff) drop-shadow(0 0 1px #fff); } }
.map-node.reachable:hover .map-building, .map-node.reachable:focus-visible .map-building { transform: scale(1.08); }
.map-node.visited .map-building { filter: grayscale(0.8) brightness(0.75); opacity: 0.85; }
.map-node.current .map-building { filter: drop-shadow(0 0 1px var(--gold)) drop-shadow(0 0 1px var(--gold)) drop-shadow(0 0 1px var(--gold)); }

/* Your Pokémon stands on the room you're in, like the trainer's head on the Pokégear */
/* The biome's boss as a grey silhouette standing just above its room, in front of the map's rocks and lava */
.map-boss-shadow {
  position: absolute;
  z-index: 3;
  width: calc(var(--tile) * 9);
  margin-top: calc(var(--tile) * -2.2);
  transform: translate(-50%, -90%);
  pointer-events: none;
  image-rendering: pixelated;
  filter: brightness(0) invert(0.3) drop-shadow(0 2px 0 rgba(0, 0, 0, 0.35));
  transition: filter 0.45s ease;
}
/* the boss reveal (js/transition.js): the silhouette colours in and rears up */
.map-boss-shadow.revealed {
  z-index: 3;
  filter: brightness(1) invert(0) opacity(1) drop-shadow(0 2px 0 rgba(0, 0, 0, 0.35));
  animation: boss-rear 0.5s ease-out both;
}
@keyframes boss-rear {
  0% { scale: 1; }
  50% { scale: 1.18; }
  100% { scale: 1.1; }
}
body.battle-intro { pointer-events: none; }
/* battle transitions (js/transition.js): two white flashes, then each fight kind's own wipe to black */
.battle-wipe {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: grid;
  overflow: hidden;
  pointer-events: auto;
}
.battle-wipe::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: #fff;
  opacity: 0;
  animation: wipe-flash 0.4s steps(1) both;
}
@keyframes wipe-flash {
  0%, 50% { opacity: 1; }
  25%, 75%, 100% { opacity: 0; }
}
/* wild: bars slide in from alternate sides */
.wipe-fight { grid-template-rows: repeat(8, 1fr); }
.wipe-fight i {
  background: #000;
  margin: -1px 0;   /* a hair of overlap so no seams show */
  translate: calc(var(--from) * 100%) 0;
  animation: wipe-bar 0.24s ease-in both;
  animation-delay: calc(0.4s + var(--delay));
}
@keyframes wipe-bar {
  to { translate: 0 0; }
}
/* elite: an iris closes on the middle of the screen */
.wipe-elite i {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  border-radius: 50%;
  box-shadow: 0 0 0 150vmax #000;
  /* its size animates rather than its scale, which would shrink the black shadow with it */
  animation: wipe-iris 0.5s ease-in 0.4s both;
}
@keyframes wipe-iris {
  from { width: 120vmax; height: 120vmax; }
  to { width: 0; height: 0; }
}
/* boss: the screen shatters to black from the centre */
.wipe-boss {
  grid-template-columns: repeat(var(--cols), 1fr);
  grid-template-rows: repeat(var(--rows), 1fr);
}
.wipe-boss i {
  background: #000;
  scale: 0;
  rotate: calc(var(--spin) * 45deg);
  margin: -1px;
  animation: wipe-tile 0.22s ease-in both;
  animation-delay: calc(0.4s + var(--delay));
}
@keyframes wipe-tile {
  to { scale: 1; rotate: 0deg; }
}
/* ...and each opens back up onto the battle the way it closed: the bars carry on off the far side,
   the iris opens, the tiles fall away from the centre first */
.wipe-fight.out i { animation: wipe-bar-out 0.24s ease-out var(--delay) both; }
@keyframes wipe-bar-out {
  from { translate: 0 0; }
  to { translate: calc(var(--from) * -100%) 0; }
}
.wipe-elite.out i { animation: wipe-iris-open 0.45s ease-out both; }
@keyframes wipe-iris-open {
  from { width: 0; height: 0; }
  to { width: 120vmax; height: 120vmax; }
}
.wipe-boss.out i { animation: wipe-tile-out 0.2s ease-out calc(var(--delay) * 0.6) both; }
@keyframes wipe-tile-out {
  from { scale: 1; rotate: 0deg; }
  to { scale: 0; rotate: calc(var(--spin) * -45deg); }
}
.map-trainer {
  position: absolute;
  z-index: 2;
  width: calc(var(--tile) * 5);
  transform: translate(-50%, -96%) scaleX(var(--face, 1));
  pointer-events: none;
  image-rendering: pixelated;
  filter: drop-shadow(0 0 1px #fff) drop-shadow(0 0 1px #fff) drop-shadow(1px 2px 0 rgba(0, 0, 0, 0.5));
  animation: trainerHop 1s ease-in-out infinite;
}
@keyframes trainerHop { 50% { translate: 0 -2px; } }   /* translate, not a margin: no layout on every frame of the map */
.map-trainer.at-start { transform: translate(-50%, -62%); }   /* at the foot of the start road, so the road shows above it */
.map-trainer.walking { animation: none; will-change: translate; }   /* walkTo() in js/map.js glides it along the route */
.map-trainer.ow { aspect-ratio: 1; transform: translate(-50%, -94%); width: calc(var(--tile) * 9); }   /* an overworld sheet paints about half its square frame, so it needs a bigger box than a GIF to stand a room tall */
.map-trainer.ow.at-start { transform: translate(-50%, -60%); }
.ow-steps {
  position: absolute;
  inset: 0;
  background-position: 0 0;
  background-size: 400% 400%;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  animation: owStep 1.1s steps(4) infinite;
}
.map-trainer.walking .ow-steps { animation-duration: 0.5s; }
.map-trainer[data-dir="left"] .ow-steps { background-position-y: 33.333%; }
.map-trainer[data-dir="right"] .ow-steps { background-position-y: 66.667%; }
.map-trainer[data-dir="up"] .ow-steps { background-position-y: 100%; }
@keyframes owStep { to { background-position-x: 133.333%; } }   /* steps(4) lands on 0, 33, 67 and 100%: the row's four frames */

/* ---------- rewards (choose one) ---------- */
#reward-screen { display: flex; flex-direction: column; align-items: center; gap: 16px; max-width: 900px; --log-w: 440px; }
@media (max-width: 720px) { #reward-screen { --log-w: 300px; } }
/* the screen's name on a small Pokégear plate, like a menu header in the games */
.reward-title {
  margin: 0;
  padding: 10px 18px 9px;
  border: 3px solid #b8b8c8;
  border-radius: var(--round);
  background: var(--win-bg);
  color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 3px 3px 0 2px rgba(0, 0, 0, 0.4);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 1.2rem;
  font-weight: 400;
  text-align: center;
}
.reward-coins { margin: 0; text-align: center; font-family: var(--pixel-font); font-synthesis-weight: none; font-size: 1.25rem; white-space: pre; color: #fff; text-shadow: 2px 2px 0 #000; }
/* the screen's text: the battle's Gold/Silver text box, stuck to the bottom so it stays in view (tap through it),
   with the confirm button for a picked option beside it */
.reward-bottom {
  position: sticky;
  bottom: max(10px, env(safe-area-inset-bottom));
  z-index: 3;
  width: min(100%, var(--log-w));   /* a narrow, centred box rather than one stretched across the screen */
  margin-top: auto;
  display: flex;
  align-items: stretch;
  gap: 10px;
}
/* a picked reward, blown up in the middle (rewards.js openFocus); the confirm sits under it like battle's "Tap to play" */
.card-focus.reward-focus { justify-content: center; padding-bottom: 16px; background: rgba(8, 10, 24, 0.6); }
.reward-focus .card.focus-card { --card-w: min(64vw, 260px, 45vh); }
/* deckNote(): a little parchment tag between the picked card and its button */
.focus-note {
  margin: 0;
  padding: 5px 10px 4px;
  border: 2px solid #181010;
  border-radius: 4px;
  background: var(--win-bg);
  color: var(--win-ink);
  font-family: var(--pixel-font);
  font-size: 0.75rem;
  line-height: 1.2;
}
/* Reward buttons ("Add to deck", Skip): End Turn's striped panel and white pill, in their own colours
   (green to take, blue to pass) and with the menus' blinking ▶ cursor in the pill */
.ds-btn {
  --stripe-a: #58b858; --stripe-b: #78d070; --rim: #2f8a3a;
  position: relative;
  padding: 6px 7px;
  border: 0;
  border-radius: 999px;
  background: repeating-linear-gradient(var(--stripe-a) 0 4px, var(--stripe-b) 4px 8px);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px var(--rim), 4px 4px 0 2px rgba(0, 0, 0, 0.45);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}
.ds-btn.ds-skip { --stripe-a: #6890e0; --stripe-b: #88a8f0; --rim: #3858b0; }
.ds-btn.ds-play { --stripe-a: #f07068; --stripe-b: #f8887c; --rim: #c84840; padding: 5px 6px; }   /* battle's Play / Use: End Turn's own colours, kept small under the card */
.ds-btn .pp-pill { gap: 0; padding: 13px 24px 12px 38px; position: relative; font-size: 1.2rem; }
.ds-btn .pp-pill::before { content: '▶'; position: absolute; left: 16px; top: 50%; translate: 0 -50%; font-size: 0.6em; animation: cursorBlink 1s steps(1) infinite; }
.ds-btn.ds-play .pp-pill { font-size: 0.85rem; padding: 8px 14px 7px 26px; }
.ds-btn.ds-play .pp-pill::before { left: 11px; }
/* the menus' capsules (How to play, See deck, Begin run, Back): a size down, so they sit lighter than a reward pick */
.ds-btn.ds-gold { --stripe-a: #e8b820; --stripe-b: #f8d048; --rim: #b08010; }
.ds-btn.ds-sm { padding: 5px 6px; }
.ds-btn.ds-sm .pp-pill { font-size: 0.9rem; padding: 10px 18px 9px 30px; color: #283060; white-space: nowrap; }
.ds-btn.ds-sm .pp-pill::before { left: 13px; }
.ds-btn:hover .pp-pill { background: #fff; }
.ds-btn:active { transform: translate(2px, 2px); box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px var(--rim), 2px 2px 0 1px rgba(0, 0, 0, 0.45); }
.ds-btn:focus-visible { outline: 3px solid #f8d030; outline-offset: 3px; }
/* Mouse hover on PP, End Turn and the striped buttons: the capsule lifts and its stripes scroll in pixel steps.
   Touch screens skip it (a tap leaves :hover stuck). The 8px tile is one stripe pair, so the scroll loops seamlessly;
   `translate` leaves the press-in `transform` and PP's shake alone. */
@media (hover: hover) {
  :is(.battle-controls .energy-orb, #end-turn-btn, .ds-btn) { background-size: 100% 8px; transition: translate 0.12s ease-out, filter 0.25s; }
  :is(.battle-controls .energy-orb:not(.shake), #end-turn-btn:not(:disabled), .ds-btn):hover {
    translate: 0 -3px;
    animation: stripeScroll 0.5s steps(4) infinite;
    filter: brightness(1.06);
  }
  :is(.battle-controls .energy-orb, #end-turn-btn:not(:disabled)):hover:not(:active) { box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #c84840, 5px 7px 0 2px rgba(0, 0, 0, 0.4); }
  .ds-btn:hover:not(:active) { box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px var(--rim), 5px 7px 0 2px rgba(0, 0, 0, 0.4); }
  :is(#end-turn-btn, .ds-btn):hover:active { translate: 0; }   /* pressing sinks it back down, into the press-in shadow */
}
@keyframes stripeScroll { to { background-position: 0 8px; } }
@media (prefers-reduced-motion: reduce) { :is(.battle-controls .energy-orb, #end-turn-btn, .ds-btn):hover { animation: none; } }

/* The controls' look (2026-10-28, branch button-look, the user's ask: the buttons to look different, to match the move
   effects): dark glass plates with a rim in the turn banner's gold, leaning like its stripe, the PP in its slanted
   numeral over a gold fill (below), End Turn in Chakra Petch with a » that runs
   while it's the move. Throw keeps the Safari's green rim and Mulligan its violet. Ids in the selectors: the hover rules
   above match through #end-turn-btn and would win otherwise. */
.battle-controls :is(#player-energy, #end-turn-btn, .throw-btn) {
  --rim: #e8b830; --glow: rgba(255, 196, 60, 0.28);
  padding: 0; border-radius: 12px;
  background: linear-gradient(180deg, #3c3858 0%, #24213a 55%, #15131e 100%); background-size: auto;
  box-shadow: 0 0 0 2px #0c0b12, inset 0 0 0 2px var(--rim), inset 0 4px 0 2px rgba(255, 255, 255, 0.1), 0 4px 0 2px rgba(0, 0, 0, 0.45), 0 0 14px var(--glow);
  transform: skewX(-8deg);
}
.battle-controls #throw-btn { --rim: #6cd048; --glow: rgba(108, 208, 72, 0.3); }
.battle-controls #mulligan-btn { --rim: #a880f0; --glow: rgba(168, 128, 240, 0.3); }
#player-energy.empty { --rim: #e85040; --glow: rgba(232, 80, 64, 0.3); }
.battle-controls :is(#player-energy, #end-turn-btn, .throw-btn) .pp-pill {
  background: none; box-shadow: none; transform: skewX(8deg);
  color: #fff; text-shadow: 2px 2px 0 #0c0b12;
}
#player-energy .pp-pill { position: relative; display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
#player-energy .pp-label { color: #fff8e0; font-size: 1rem; text-shadow: 2px 2px 0 #0c0b12, -1px -1px 0 #0c0b12, 1px -1px 0 #0c0b12, -1px 1px 0 #0c0b12; }
/* PP as a glass filling (2026-10-28, the user's idea: "fill up the background of it like you're filling a glass of
   water"): gold liquid to --lvl of the plate (the PP left of the turn's), right to the top when full, with a flat bright
   surface (a wave and bubbles were tried first; the user: no "wavy" stuff). It rises after the refill's motes land and
   drops as PP is spent. */
#player-energy .pp-fill { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none; contain: strict; }
#player-energy .pp-liquid {
  position: absolute; left: 0; right: 0; bottom: 0; height: calc(var(--lvl, 0) * 100%);
  background: linear-gradient(180deg, #ffcc40 0%, #f0a020 45%, #b85c08 100%);
  box-shadow: inset 0 2px 0 rgba(255, 244, 190, 0.8), inset 0 -6px 10px rgba(80, 30, 0, 0.35);
  transition: height 0.45s cubic-bezier(0.3, 0.7, 0.3, 1);
}
#player-energy.refill .pp-liquid { transition-duration: 0.8s; transition-delay: 0.3s; }
#player-energy.gain .pp-liquid { transition-delay: 0.2s; }
#player-energy .pp-count { display: flex; align-items: baseline; }
#player-energy .pp-count b {
  font: italic 700 2.1rem/0.8 "Chakra Petch", var(--pixel-font); color: #fffbe8;   /* white over the gold liquid: gold on gold didn't read */
  text-shadow: 2px 2px 0 #0c0b12, -1px -1px 0 #0c0b12, 1px -1px 0 #0c0b12, -1px 1px 0 #0c0b12, 0 0 10px rgba(255, 196, 60, 0.6);
  padding-right: 2px; font-variant-numeric: tabular-nums;
}
#player-energy .pp-count small { font-size: 0.85rem; color: #ece8ff; text-shadow: 2px 2px 0 #0c0b12, -1px -1px 0 #0c0b12, 1px -1px 0 #0c0b12, -1px 1px 0 #0c0b12; }
#player-energy.empty .pp-count b { color: #ff6a5a; text-shadow: 2px 2px 0 #0c0b12, -1px -1px 0 #0c0b12, 1px -1px 0 #0c0b12, -1px 1px 0 #0c0b12, 0 0 10px rgba(255, 80, 60, 0.6); }
.battle-controls :is(#end-turn-btn, .throw-btn) .pp-pill { font: italic 700 1.3rem/1 "Chakra Petch", var(--pixel-font); text-transform: uppercase; letter-spacing: 0.5px; }
.et-arrow { display: inline-block; margin-left: 8px; font-style: normal; color: #ffd84a; text-shadow: 2px 2px 0 #0c0b12, 0 0 8px rgba(255, 196, 60, 0.7); }
#end-turn-btn:disabled .et-arrow { color: #8a86a0; text-shadow: 2px 2px 0 #0c0b12; }
.battle-controls #end-turn-btn:hover:not(:disabled) .pp-pill { background: none; }
.battle-controls :is(#end-turn-btn, .throw-btn):active:not(:disabled) {
  transform: skewX(-8deg) translateY(3px);
  box-shadow: 0 0 0 2px #0c0b12, inset 0 0 0 2px var(--rim), inset 0 4px 0 2px rgba(0, 0, 0, 0.25), 0 1px 0 2px rgba(0, 0, 0, 0.45), 0 0 14px var(--glow);
}
.battle-controls #end-turn-btn.nudge { background-size: auto; animation: turnHop 1.4s ease-in-out infinite, rimGlow 1.4s ease-in-out infinite; }
#end-turn-btn.nudge .et-arrow { animation: etRun 0.7s ease-in-out infinite; }
@keyframes etRun { 50% { translate: 5px 0; } }
@keyframes rimGlow { 50% { box-shadow: 0 0 0 2px #0c0b12, inset 0 0 0 2px #fff0a0, inset 0 4px 0 2px rgba(255, 255, 255, 0.1), 0 4px 0 2px rgba(0, 0, 0, 0.45), 0 0 24px 6px rgba(255, 200, 60, 0.6); } }
@keyframes ppCharge { 30% { box-shadow: 0 0 0 2px #0c0b12, inset 0 0 0 2px #fff0a0, inset 0 4px 0 2px rgba(255, 255, 255, 0.1), 0 4px 0 2px rgba(0, 0, 0, 0.45), 0 0 28px 8px rgba(255, 200, 60, 0.7); } }
@keyframes ppFill { 35% { transform: translateY(-5px) scale(1.25); color: #fffbe0; } }
@keyframes ppShake { 0%, 100% { transform: skewX(-8deg); } 20%, 60% { transform: skewX(-8deg) translateX(-5px); } 40%, 80% { transform: skewX(-8deg) translateX(5px); } }
@media (hover: hover) {
  .battle-controls :is(#player-energy:not(.shake), #end-turn-btn:not(:disabled):not(.nudge)):hover { animation: none; filter: brightness(1.12); }
  .battle-controls :is(#player-energy, #end-turn-btn:not(:disabled)):hover:not(:active) {
    box-shadow: 0 0 0 2px #0c0b12, inset 0 0 0 2px #fff0a0, inset 0 4px 0 2px rgba(255, 255, 255, 0.1), 0 7px 0 2px rgba(0, 0, 0, 0.4), 0 0 20px var(--glow);
  }  .battle-controls :is(#throw-btn, #mulligan-btn):not(.spent):not(:disabled):hover { filter: brightness(1.12); }
}
@media (max-width: 720px) {
  .battle-controls :is(#player-energy, #end-turn-btn, .throw-btn) { padding: 0; border-radius: 10px; }
  .battle-controls .pp-pill { min-width: 6.4rem; height: 2.6rem; padding: 4px 12px; }
  #player-energy .pp-pill { gap: 8px; }
  #player-energy .pp-label { font-size: 0.75rem; }
  #player-energy .pp-count b { font-size: 1.6rem; }
  #player-energy .pp-count small { font-size: 0.75rem; }
  .battle-controls :is(#end-turn-btn, .throw-btn) .pp-pill { font-size: 0.95rem; }
  .et-arrow { margin-left: 5px; }
  /* the Safari's row of three: the capsules' rules for it (above) outrank the plates', :has counting its argument */
  .battle-controls:has(.throw-btn:not([hidden])) :is(#player-energy, #throw-btn, #mulligan-btn, #end-turn-btn) { padding: 0; }
  .battle-controls:has(.throw-btn:not([hidden])) .pp-pill { height: 2.6rem; padding: 4px 8px; }
}
@media (prefers-reduced-motion: reduce) { #end-turn-btn.nudge .et-arrow { animation: none; } }
.reward-option.picked { transform: translateY(-10px) scale(1.04); }
.reward-option.picked .card-face { --ring: 0 0 0 1cqw #fff, 0 0 0 2.8cqw #f8d030, 0 0 6cqw 2cqw rgba(248, 208, 48, 0.7); }   /* like a picked card in battle */
.reward-option.picked > .relic { outline: 4px solid #f8d030; outline-offset: 2px; }
.reward-log {
  position: relative;
  flex: 1;
  min-width: 0;
  min-height: 3.4em;
  padding: 9px 28px 9px 28px;
  border: 3px solid #b8b8c8;
  border-radius: var(--round);
  background: var(--win-bg);
  color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 3px 3px 0 2px rgba(0, 0, 0, 0.4);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 0.95rem;
  line-height: 1.4;
  text-align: center;
  cursor: pointer;
}
.log-rest { visibility: hidden; }
/* the map's copy of the box, for news that lands you back on the map (rewards.js tell()): narrow, centred, pinned to the bottom */
.map-bottom {
  position: fixed;
  left: 50%;
  bottom: max(10px, env(safe-area-inset-bottom));
  z-index: 5;
  display: flex;
  width: min(calc(100% - 32px), 440px);
  translate: -50% 0;
  pointer-events: none;
}
.map-bottom .reward-log { pointer-events: auto; }
@media (max-width: 720px) { .map-bottom { width: min(calc(100% - 32px), 300px); } }
.reward-log.more::after {
  content: '▼';
  position: absolute;
  right: 10px;
  bottom: 6px;
  font-size: 0.75rem;
  color: #c02020;
  animation: cursorBlink 1s steps(1) infinite;
}
.reward-options { display: flex; flex-wrap: wrap; justify-content: center; gap: 22px; width: 100%; padding: 12px 0; }
.reward-option { background: none; border: 0; padding: 0; width: clamp(130px, 28vw, 200px); transition: transform 0.15s; }
.reward-option:hover, .reward-option:focus-visible { transform: translateY(-8px) scale(1.04); }
.reward-option:disabled { opacity: 0.5; transform: none; cursor: not-allowed; }

/* ---------- relics ---------- */
/* Relic, item and choice tiles (Pokémon Center, events, Forget a move): a Pokégear window, like the
   text box and the menus: parchment in a grey frame, pixel-font name, dark text. */
.relic {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 190px;
  padding: 16px 12px;
  border: 3px solid #b8b8c8;
  border-radius: var(--round);
  background: var(--win-bg);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 3px 3px 0 2px rgba(0, 0, 0, 0.4);
  text-align: center;
  color: var(--win-ink);
}
.relic-icon { font-size: 3rem; line-height: 1; filter: drop-shadow(2px 2px 0 rgba(0, 0, 0, 0.25)); }
.relic-name { font-family: var(--pixel-font); font-synthesis-weight: none; font-weight: 400; font-size: 0.95rem; line-height: 1.3; }
.relic-text { font-size: 0.88rem; font-weight: 700; line-height: 1.3; color: var(--win-muted); }
.relic-terms { display: flex; flex-direction: column; gap: 3px; margin-top: 4px; }
.relic-term {
  display: block; padding: 3px 6px; font-size: 0.75rem; line-height: 1.35; text-align: left; color: var(--win-muted);
  background: rgba(255, 255, 255, 0.45); border-left: 3px solid var(--win-edge); border-radius: var(--round-xs);
}
.relic-term b { font-weight: 400; }
/* Skip / Leave sits centred right under the options, not off in a corner by the text box */
.reward-actions:not(:has(> :not([hidden]))) { display: none; }
.reward-actions { flex: none; display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; margin-top: -4px; }
.reward-option > .relic { height: 100%; }   /* tiles side by side share one height */
@media (max-width: 720px) {
  .reward-actions .pp-pill { font-size: 0.85rem; padding: 8px 14px 7px 26px; }
  .reward-actions .pp-pill::before { left: 11px; }
}

/* ---------- evolution and deck dialogs ---------- */
/* The evolution scene (js/evolution.js), after Gold/Silver's: two quick white flashes like battleWipe(), then it holds
   white; the Pokémon stands alone on its feet line, with the text box at the bottom. */
.evo-scene { position: fixed; inset: 0; z-index: 950; overflow: hidden; }
.evo-scene::before { content: ''; position: absolute; inset: 0; background: #f8f8f8; animation: evoWash 0.9s both; }
@keyframes evoWash {
  0% { opacity: 1; animation-timing-function: steps(1, end); }
  11% { opacity: 0; animation-timing-function: steps(1, end); }
  22% { opacity: 1; animation-timing-function: steps(1, end); }
  33% { opacity: 0; animation-timing-function: ease-in; }
  100% { opacity: 1; }
}
.evo-scene.still::before { animation: evoFade 0.4s ease-in both; }
@keyframes evoFade { from { opacity: 0; } }
.evo-scene.out { opacity: 0; transition: opacity 0.6s ease-out; }
.evo-mon { position: absolute; left: 50%; top: 58%; width: 0; height: 0; opacity: 0; transition: opacity 0.6s; }
.evo-mon.shown { opacity: 1; }
.evo-mon img { position: absolute; left: 0; bottom: 0; max-width: none; image-rendering: pixelated; }
.evo-mon.dark img { filter: brightness(0); }
.evo-mon.white img { filter: brightness(0) invert(1) drop-shadow(0 0 3px #a8b0d0) drop-shadow(0 0 1px #8890b0); }
.evo-flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; }
.evo-flash.go { animation: evoFlash 0.9s ease-out; }
@keyframes evoFlash { 0% { opacity: 0; } 12% { opacity: 1; } 30% { opacity: 1; } 100% { opacity: 0; } }
.evo-bottom {
  position: absolute;
  left: 50%;
  bottom: max(16px, env(safe-area-inset-bottom));
  display: flex;
  width: min(calc(100% - 32px), 440px);
  translate: -50% 0;
}
@media (max-width: 720px) { .evo-bottom { width: min(calc(100% - 32px), 300px); } }
.evo-scene.waiting, .evo-scene.skippable { cursor: pointer; }
.evo-skip { position: absolute; right: max(12px, env(safe-area-inset-right)); bottom: max(12px, env(safe-area-inset-bottom));
  font-size: 12px; color: rgba(0, 0, 0, 0.45); pointer-events: none; visibility: hidden; }
.evo-scene.skippable .evo-skip { visibility: visible; }
/* The evolution scene's comic intro (js/evo-comic.js): manga panels cut out of the white, each a clipped full-page
   layer with a halftone in its type's colour, focus lines, a zoomed face and a black frame; the gutters are the white. */
.evc { position: absolute; inset: max(10px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right)) max(10px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left)); overflow: hidden; pointer-events: none; }
.evc-panel {
  position: absolute; inset: 0; overflow: hidden;
  background: radial-gradient(circle, rgba(0, 0, 0, 0.17) 30%, transparent 34%) 0 0 / 7px 7px,
    radial-gradient(ellipse at var(--at), #fffdf4 0%, #fffdf4 22%, var(--tone) 80%);
  translate: -106% 0;
  transition: translate 0.34s cubic-bezier(0.2, 1.25, 0.4, 1);
}
.evc-panel.from-right { translate: 106% 0; }
.evc-panel.in { translate: 0 0; }
.evc-lines, .evc-frame { position: absolute; inset: 0; width: 100%; height: 100%; }
.evc-frame { overflow: visible; }
.evc-frame polygon { fill: none; stroke: #111; stroke-width: 10px; vector-effect: non-scaling-stroke; stroke-linejoin: miter; }
.evc-face { position: absolute; width: 0; height: 0; }
.evc-face.flip { scale: -1 1; }
.evc-face img { position: absolute; left: 0; top: 0; max-width: none; image-rendering: pixelated; }
.evc-panel.in .evc-face { animation: evcPush 5s ease-out both; }
@keyframes evcPush { from { transform: scale(1); } to { transform: scale(1.1); } }
.evc-bubble {
  position: absolute; max-width: min(46%, 260px); padding: 10px 14px;
  background: #fff; color: #111; border: 3px solid #111; border-radius: 50% / 46%;
  font-size: 16px; line-height: 1.35; text-align: center;
  animation: evcPop 0.28s cubic-bezier(0.2, 1.6, 0.4, 1) both;
}
.evc-bubble::before, .evc-bubble::after { content: ''; position: absolute; border-style: solid; border-color: transparent; }
.evc-bubble::before { bottom: -19px; left: 38%; border-width: 18px 6px 0 10px; border-top-color: #111; }
.evc-bubble::after { bottom: -12px; left: calc(38% + 4px); border-width: 12px 3px 0 6px; border-top-color: #fff; }
.evc-bubble.b0 { left: 5%; top: 33%; }
.evc-bubble.duo.b0 { left: 4%; top: 5%; }
.evc-bubble.duo.b1 { right: 4%; top: 57%; }
.evc-bubble.duo.b1::before { left: auto; right: 38%; border-width: 18px 10px 0 6px; }
.evc-bubble.duo.b1::after { left: auto; right: calc(38% + 4px); border-width: 12px 6px 0 3px; }
@keyframes evcPop { from { opacity: 0; transform: scale(0.3); } }
.evc-sfx {
  position: absolute; right: 5%; top: 17%; rotate: -10deg;
  font-size: clamp(56px, 15vw, 120px); line-height: 1; letter-spacing: -0.05em;
  text-shadow: 4px 0 #111, -4px 0 #111, 0 4px #111, 0 -4px #111, 4px 4px #111, -4px -4px #111, 4px -4px #111, -4px 4px #111, 9px 9px 0 rgba(0, 0, 0, 0.3);
  animation: evcStamp 0.3s cubic-bezier(0.3, 1.5, 0.5, 1) both;
}
.evc.duo .evc-sfx { right: auto; left: 5%; top: 39%; }
@keyframes evcStamp { from { opacity: 0; scale: 2.6; } }
.evc.shake { animation: evcShake 0.32s linear; }
@keyframes evcShake { 20% { translate: -7px 4px; } 40% { translate: 6px -5px; } 60% { translate: -4px -3px; } 80% { translate: 3px 3px; } }
.evc::after { content: ''; position: absolute; left: -20%; top: 50%; width: 140%; height: 10px; background: #fff; box-shadow: 0 0 12px #fff;
  rotate: -24deg; scale: 0 1; transform-origin: left; opacity: 0; }
.evc.slash::after { opacity: 1; scale: 1 1; transition: scale 0.18s ease-in; }
.evc.slash .evc-panel { transition: translate 0.3s cubic-bezier(0.6, 0, 0.9, 0.4) 0.1s; }
.evc.slash .evc-panel.from-left { translate: -110% -8%; }
.evc.slash .evc-panel.from-right { translate: 110% 8%; }
.evc.slash .evc-bubble, .evc.slash .evc-sfx { opacity: 0; transition: opacity 0.12s; }
.evc.still .evc-panel { translate: 0 0; opacity: 0; transition: opacity 0.3s; }
.evc.still .evc-panel.in { opacity: 1; }
.evc.still .evc-face, .evc.still .evc-bubble, .evc.still .evc-sfx { animation: none; }
.evc.gone { opacity: 0; transition: opacity 0.35s; }
/* a duo evolves side by side, each on its own feet */
.evo-scene.duo .evo-mon:first-of-type { left: 30%; }
.evo-scene.duo .evo-mon + .evo-mon { left: 70%; }
/* The Hall of Fame (js/halloffame.js), after a Level 5 win: a white flash, then a starry night; your Pokémon slides onto
   a pedestal under a spotlight, its plate pops up, and its final deck rises along the bottom above the text box. */
.hof-scene { position: fixed; inset: 0; z-index: 950; overflow: hidden; background: radial-gradient(ellipse at 50% 38%, #34489a, #18205a 55%, #0a0e2c); }
.hof-sky {
  position: absolute; inset: 0;
  background:
    radial-gradient(2px 2px at 12% 18%, #fff 50%, transparent 51%), radial-gradient(2px 2px at 78% 12%, #fff 50%, transparent 51%),
    radial-gradient(2px 2px at 36% 8%, #ffe890 50%, transparent 51%), radial-gradient(2px 2px at 88% 40%, #fff 50%, transparent 51%),
    radial-gradient(2px 2px at 6% 52%, #ffe890 50%, transparent 51%), radial-gradient(2px 2px at 62% 26%, #fff 50%, transparent 51%),
    radial-gradient(3px 3px at 22% 36%, #fff 50%, transparent 51%), radial-gradient(3px 3px at 92% 70%, #ffe890 50%, transparent 51%),
    radial-gradient(2px 2px at 48% 18%, #fff 50%, transparent 51%), radial-gradient(2px 2px at 16% 80%, #fff 50%, transparent 51%);
  animation: hofTwinkle 1.6s steps(2) infinite;
}
.hof-sky::after {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(2px 2px at 28% 22%, #fff 50%, transparent 51%), radial-gradient(2px 2px at 70% 6%, #ffe890 50%, transparent 51%),
    radial-gradient(3px 3px at 84% 26%, #fff 50%, transparent 51%), radial-gradient(2px 2px at 8% 30%, #fff 50%, transparent 51%),
    radial-gradient(2px 2px at 54% 44%, #ffe890 50%, transparent 51%), radial-gradient(2px 2px at 96% 54%, #fff 50%, transparent 51%);
  animation: hofTwinkle 1.6s steps(2) infinite reverse;
}
@keyframes hofTwinkle { 50% { opacity: 0.35; } }
.hof-flash { position: absolute; inset: 0; background: #f8f8f8; pointer-events: none; animation: hofWash 0.9s both; }
@keyframes hofWash {
  0% { opacity: 1; animation-timing-function: steps(1, end); }
  15% { opacity: 0; animation-timing-function: steps(1, end); }
  30% { opacity: 1; animation-timing-function: ease-out; }
  100% { opacity: 0; }
}
.hof-scene.still .hof-flash { display: none; }
.hof-scene.out { opacity: 0; transition: opacity 0.6s ease-out; }
.hof-layout {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: max(14px, env(safe-area-inset-top)) 0 max(16px, env(safe-area-inset-bottom));
}
.hof-title {
  margin: 0;
  font: 1.6rem/1.2 var(--pixel-font); font-synthesis-weight: none;
  color: #f8d048;
  text-shadow: 2px 0 0 #6a3a08, -2px 0 0 #6a3a08, 0 2px 0 #6a3a08, 0 -2px 0 #6a3a08, 0 5px 0 #0a0e2c;
  animation: hofTitle 0.6s cubic-bezier(0.22, 1, 0.36, 1) both 0.5s;
}
@keyframes hofTitle { from { opacity: 0; translate: 0 -24px; } }
.hof-stage { position: relative; flex: 1 1 0; min-height: 140px; width: 100%; }
.hof-light {
  position: absolute; left: 50%; top: -10%; bottom: 18px; width: min(360px, 80vw); translate: -50% 0;
  background: linear-gradient(rgba(255, 248, 200, 0.05), rgba(255, 240, 170, 0.32));
  clip-path: polygon(42% 0, 58% 0, 100% 100%, 0 100%);
  opacity: 0; transition: opacity 0.8s;
}
.hof-pedestal {
  position: absolute; left: 50%; bottom: 0; width: min(220px, 56vw); height: 44px; translate: -50% 0;
  background: linear-gradient(#f0e0b0 0 8px, #d0b068 8px 12px, #f8d048 12px 17px, #9a6a28 17px 21px, #7a5424 21px 36px, #4a3014 36px);
  clip-path: polygon(0 0, 100% 0, 100% 8px, calc(100% - 8px) 8px, calc(100% - 8px) calc(100% - 8px), 100% calc(100% - 8px), 100% 100%,
    0 100%, 0 calc(100% - 8px), 8px calc(100% - 8px), 8px 8px, 0 8px);
}
.hof-mon { position: absolute; left: 50%; bottom: 40px; width: 0; height: 0; transform: translate3d(60vw, 0, 0); }
.hof-mon img { position: absolute; left: 0; bottom: 0; max-width: none; image-rendering: pixelated; }
.hof-scene.mon-in .hof-mon { transform: translate3d(0, 0, 0); transition: transform 0.8s cubic-bezier(0.2, 0.8, 0.3, 1); }
.hof-scene.mon-in .hof-light { opacity: 1; }
.hof-plate-slot { min-height: 64px; width: min(calc(100% - 32px), 440px); }
/* the plate is a green LCD in a ring of the device's shell (D2, 2026-10-07); the Depths' and the summit's ring is gold */
.hof-plate {
  padding: 8px 14px;
  border: 3px solid #2a2a30; border-radius: var(--round);
  background: radial-gradient(circle, rgba(31, 58, 20, 0.1) 1px, transparent 1.5px) 0 0 / 8px 8px, #a8c884; color: #1f3a14;
  box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), 0 0 0 5px var(--shell), 0 0 0 8px var(--shell-rim), 3px 5px 0 8px rgba(0, 0, 0, 0.35);
}
.hof-scene .hof-plate { opacity: 0; scale: 0.8; transition: opacity 0.3s, scale 0.3s cubic-bezier(0.2, 1.6, 0.4, 1); }
.hof-scene.plate-in .hof-plate { opacity: 1; scale: 1; }
.hof-plate-head { display: flex; align-items: baseline; gap: 10px; }
.hof-no { font-size: 0.75rem; color: #a02c2c; }
.hof-name { font-size: 0.95rem; font-weight: 400; }
.hof-plate-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin-top: 6px; font-size: 0.75rem; }
.hof-deck-slot { width: 100%; min-height: 96px; }
.hof-deck {
  display: flex; gap: 8px; justify-content: safe center;
  overflow-x: auto; padding: 4px 16px 14px;
  animation: hofRise 0.4s ease-out both;
}
@keyframes hofRise { from { opacity: 0; transform: translate3d(0, 30px, 0); } to { transform: translate3d(0, 0, 0); } }
/* the run's numbers, before the deck: small dark pixel panels that pop in one after another */
.hof-scene-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; width: min(calc(100% - 32px), 620px); margin: 0 auto; }
.hof-stat {
  display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 5px 2px 6px;
  border: 2px solid #8890c8; border-radius: var(--round-xs);
  background: rgba(10, 14, 44, 0.78); box-shadow: 0 0 0 2px #0a0e2c;
  color: #fff8e0; text-align: center;
  opacity: 0;
}
.hof-scene.deck-in .hof-stat { animation: hofPop 0.25s ease-out both calc(var(--i) * 70ms); }
@keyframes hofPop { from { opacity: 0; scale: 0.6; } to { opacity: 1; scale: 1; } }
.hof-stat-icon { font-size: 0.95rem; line-height: 1; }
.hof-stat b { font-size: 0.95rem; font-weight: 400; color: #f8d048; }
.hof-stat-label { font-size: 0.75rem; line-height: 1.3; color: #c8d0f0; }
/* a Level 5 win's pedestal is gold; any other win's is silver */
.hof-scene:not(.fame) .hof-pedestal {
  background: linear-gradient(#f0f0f8 0 8px, #b8bcd0 8px 12px, #e0e4f0 12px 17px, #7a7e98 17px 21px, #5a5e78 21px 36px, #34384e 36px);
}
.hof-scene:not(.fame) .hof-title { color: #fff8e0; text-shadow: 2px 0 0 #14275e, -2px 0 0 #14275e, 0 2px 0 #14275e, 0 -2px 0 #14275e, 0 5px 0 #0a0e2c; }
.hof-deck .card { --card-w: 62px; flex: none; }
.hof-deck .in-deck { top: auto; bottom: -9px; right: 50%; translate: 50% 0; font-size: 15cqw; }
.hof-bottom { display: flex; width: min(calc(100% - 32px), 440px); }
.hof-scene.waiting { cursor: pointer; }
.hof-scene.still .hof-title, .hof-scene.still .hof-sky, .hof-scene.still .hof-sky::after { animation: none; }
.hof-scene.still .hof-mon, .hof-scene.still .hof-plate { transition: none; }
.hof-scene.still .hof-deck { animation: none; }
.hof-scene.still.deck-in .hof-stat { animation: none; opacity: 1; }
/* A Level 5 win's party (js/celebrate.js draws the fireworks, confetti and sweeping spotlights on .hof-fx, a low-res
   canvas behind the layout): the title's letters flash in one by one and a rainbow sweeps across them, the Pokémon hops
   as it lands, and the finale's big firework flashes the screen and shakes it. All in whole steps, no soft glows. */
.hof-fx { position: absolute; left: 0; top: 0; image-rendering: pixelated; pointer-events: none; }
.hof-boom { position: absolute; inset: 0; background: #f8f8f8; pointer-events: none; opacity: 0; }
.hof-scene.boom .hof-boom { animation: hofBoom 0.45s steps(1, end) both; }
@keyframes hofBoom { 0% { opacity: 0.95; } 20% { opacity: 0; } 40% { opacity: 0.6; } 60%, 100% { opacity: 0; } }
.hof-scene.boom .hof-layout, .hof-scene.boom .hof-fx { animation: hofShake 0.5s linear; }
@keyframes hofShake {
  0% { translate: 6px 0; } 12% { translate: -6px 3px; } 24% { translate: 4px -4px; } 36% { translate: -4px 2px; }
  48% { translate: 3px 0; } 60% { translate: -2px 2px; } 72% { translate: 2px 0; } 84%, 100% { translate: 0 0; }
}
.hof-scene.party .hof-title { animation: hofTitleFlash 0.6s steps(1, end) both 1.5s; }
@keyframes hofTitleFlash { 0% { filter: brightness(2.2); } 25% { filter: none; } 50% { filter: brightness(2.2); } 75%, 100% { filter: none; } }
.hof-letter {
  display: inline-block; white-space: pre;
  animation: hofLetter 0.4s ease-out both calc(0.5s + var(--i) * 70ms), hofShimmer 2.6s steps(1, end) infinite calc(2.2s + var(--i) * 60ms);
}
@keyframes hofLetter {
  0% { opacity: 0; scale: 2.6; color: #f8f8f8; }
  50% { opacity: 1; scale: 1.5; color: #f8f8f8; }
  100% { opacity: 1; scale: 1; }
}
@keyframes hofShimmer {
  0% { color: #f8d048; } 60% { color: #f85858; } 64% { color: #f8a038; } 68% { color: #f8f070; } 72% { color: #58d858; }
  76% { color: #58b0f8; } 80% { color: #c080f8; } 84% { color: #f8f8f8; } 88%, 100% { color: #f8d048; }
}
.hof-scene.party.hop .hof-mon { animation: hofHop 0.6s ease-in-out both; }
@keyframes hofHop {
  0% { transform: translateY(0); } 35% { transform: translateY(-26px); } 65% { transform: translateY(0); }
  80% { transform: translateY(-8px); } 100% { transform: translateY(0); }
}
.hof-scene.party .hof-stat { background: rgba(10, 14, 44, 0.92); }
@media (max-width: 720px) {
  .hof-bottom { width: min(calc(100% - 32px), 300px); }
  .hof-title { font-size: 1.15rem; }
  .hof-name { font-size: 0.8rem; }
  .hof-deck .card { --card-w: 52px; }
  .hof-deck-slot { min-height: 84px; }
  .hof-scene-stats { grid-template-columns: repeat(5, 1fr); gap: 4px; }
  .hof-stat { padding: 4px 1px 5px; }
  .hof-stat b { font-size: 0.78rem; }
  .hof-stat-label { font-size: 0.75rem; }
  .hof-stat-icon { font-size: 0.8rem; }
}
@media (max-height: 600px) {
  .hof-layout { gap: 6px; }
  .hof-deck .card { --card-w: 46px; }
  .hof-deck-slot { min-height: 74px; }
}

/* A Mewtwo win, the Champion of the Depths (v1.0 part D): the scene in the Crystal Depths, violet light, crystal clusters
   either side and stalactites above, a crystal pedestal trimmed in gold; then the credits roll (js/credits.js). */
.hof-scene.depths { background: radial-gradient(ellipse at 50% 42%, #5a2c8a, #2a1050 55%, #0c0418); }
.hof-scene.depths .hof-sky { filter: hue-rotate(250deg) saturate(1.4); }
.hof-cave { position: absolute; inset: 0; pointer-events: none; display: none; }
.hof-scene.depths .hof-cave { display: block; }
.hof-cave::before, .hof-cave::after {
  content: ''; position: absolute; bottom: 0; width: min(46vw, 340px); height: min(46vh, 360px);
  background: linear-gradient(90deg, #7848c8 0 18%, #b088f0 18% 30%, #5830a0 30% 52%, #9868e0 52% 64%, #3a1c70 64%);
  clip-path: polygon(0 100%, 0 30%, 8% 8%, 16% 34%, 22% 46%, 28% 14%, 36% 0, 42% 22%, 46% 52%, 54% 36%, 60% 60%, 68% 44%,
    74% 70%, 82% 62%, 88% 84%, 100% 100%);
  opacity: 0.85;
}
.hof-cave::before { left: 0; }
.hof-cave::after { right: 0; scale: -1 1; height: min(38vh, 300px); }
.hof-scene.depths .hof-layout::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 64px; pointer-events: none;
  background: #1a0a34;
  clip-path: polygon(0 0, 100% 0, 100% 30%, 96% 70%, 92% 30%, 86% 90%, 80% 34%, 74% 60%, 68% 26%, 60% 100%, 54% 30%, 48% 56%,
    42% 22%, 36% 80%, 30% 30%, 24% 64%, 18% 24%, 12% 86%, 6% 32%, 0 54%);
}
.hof-scene.depths .hof-light { background: linear-gradient(rgba(220, 180, 255, 0.05), rgba(200, 140, 255, 0.36)); }
.hof-scene.depths .hof-pedestal {
  background: linear-gradient(#fff0a0 0 4px, #e8d0ff 4px 8px, #b088f0 8px 12px, #f8d048 12px 16px, #7848c8 16px 21px, #5830a0 21px 36px, #2a1050 36px);
}
.hof-scene.depths .hof-title { color: #f8d048; text-shadow: 2px 0 0 #4a1880, -2px 0 0 #4a1880, 0 2px 0 #4a1880, 0 -2px 0 #4a1880, 0 5px 0 #0c0418; }
.hof-scene.depths .hof-plate { box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), 0 0 0 5px #d8b048, 0 0 0 8px #4a1880, 3px 5px 0 8px rgba(0, 0, 0, 0.35); }
.hof-scene.depths .hof-stat { border-color: #b088f0; background: rgba(28, 8, 52, 0.85); }
.hof-scene.depths .hof-mon img { filter: drop-shadow(0 0 10px rgba(190, 120, 255, 0.7)); }
@media (max-width: 720px) { .hof-scene.depths .hof-title { font-size: 0.95rem; } }

/* A Sky Pillar summit (Rayquaza beaten on floor 100): the top floor itself, painted by js/tower-art.js's paintSummit() as the
   climb and Rayquaza's fight show it (stars, the planet's curve far below with dawn breaking along it, the broken pillars,
   the mossy flagstones), the Pillar's own mossy stone for the pedestal, trimmed in Rayquaza's green and gold. */
.hof-scene.summit { background: #02030c; }
.hof-summit-bg { position: absolute; left: 0; top: 0; image-rendering: pixelated; pointer-events: none; }
.hof-scene.summit .hof-sky { display: none; }
.hof-scene.summit .hof-light { background: linear-gradient(rgba(255, 240, 200, 0.05), rgba(255, 220, 150, 0.32)); }
.hof-scene.summit .hof-pedestal {
  background: linear-gradient(#f8e078 0 4px, #48c070 4px 8px, #a8b0a0 8px 12px, #d8b048 12px 16px, #788878 16px 21px, #586858 21px 36px, #304030 36px);
}
.hof-scene.summit .hof-title { color: #f8e078; text-shadow: 2px 0 0 #186838, -2px 0 0 #186838, 0 2px 0 #186838, 0 -2px 0 #186838, 0 5px 0 #141a48; }
.hof-scene.summit .hof-plate { box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), 0 0 0 5px #d8b048, 0 0 0 8px #186838, 3px 5px 0 8px rgba(0, 0, 0, 0.35); }
.hof-scene.summit .hof-stat { border-color: #58c080; background: rgba(20, 26, 72, 0.88); }
.hof-scene.summit .hof-mon img { filter: drop-shadow(0 0 10px rgba(255, 220, 140, 0.7)); }
@media (max-width: 720px) { .hof-scene.summit .hof-title { font-size: 1rem; } }

/* A Pokémon Master's win (Trainer Level 10, js/halloffame.js's isMasterWin()): a crystal pedestal, ice-clear with a
   rainbow band like the rainbow star, its facets catching the light, under a prism-tinted spotlight. Still: no frame cost. */
.hof-scene.master .hof-pedestal {
  background:
    repeating-linear-gradient(115deg, rgba(255, 255, 255, 0.32) 0 6px, transparent 6px 14px, rgba(255, 255, 255, 0.12) 14px 18px, transparent 18px 30px) 0 21px / 100% 15px no-repeat,
    linear-gradient(90deg, #ff5a5a, #ffd84a, #6ee86e, #5ac8ff, #b07af0, #ff7ad0) 0 12px / 100% 4px no-repeat,
    linear-gradient(#ffffff 0 4px, #d8f4ff 4px 8px, #a0e0f8 8px 12px, #f8d048 12px 16px, #7ac4ec 16px 21px, #4a90d0 21px 36px, #284a8a 36px);
}
.hof-scene.master .hof-light { background: linear-gradient(rgba(220, 245, 255, 0.05), rgba(200, 235, 255, 0.34)); }
.hof-scene.master .hof-title { color: #ffffff; text-shadow: 2px 0 0 #2a5ab0, -2px 0 0 #2a5ab0, 0 2px 0 #2a5ab0, 0 -2px 0 #2a5ab0, 0 5px 0 #0a0e2c; }
.hof-scene.master .hof-plate { box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), 0 0 0 5px #a0e0f8, 0 0 0 8px #2a5ab0, 3px 5px 0 8px rgba(0, 0, 0, 0.35); }
.hof-scene.master .hof-stat { border-color: #a0e0f8; }
.hof-scene.master .hof-mon img { filter: drop-shadow(0 0 10px rgba(190, 235, 255, 0.75)); }

.hof-credits {
  position: absolute; inset: 0; z-index: 5; overflow: hidden; cursor: pointer;
  background: rgba(8, 2, 20, 0.7); color: #f0e8ff; text-align: center;
  opacity: 0; transition: opacity 0.8s;
}
.hof-credits.in { opacity: 1; }
.hof-scene:has(.hof-credits.in) .hof-layout { opacity: 0; transition: opacity 0.8s; }
.hof-credits.out { opacity: 0; transition-duration: 0.5s; }
.credits-roll { position: absolute; left: 0; right: 0; top: 100%; padding: 0 16px; }
.credits-roll.rolling { animation: creditsRoll var(--secs, 38s) linear forwards; }
.credits-roll.rolling { will-change: transform; }
@keyframes creditsRoll { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(0, calc(-100% - 100vh), 0); } }
.hof-credits.ended .credits-roll { opacity: 0; transition: opacity 0.5s; }
.credits-logo { margin: 0; font: 2rem/1.2 var(--pixel-font); color: #f8d048; text-shadow: 3px 3px 0 #4a1880; }
.credits-version { margin: 6px 0 0; font-size: 0.75rem; color: #c8a8f0; }
.credits-part { margin: 64px auto 0; max-width: 440px; }
.credits-head { margin: 0 0 10px; font: 0.75rem/1.4 var(--pixel-font); font-weight: 400; color: #f8d048; letter-spacing: 0.08em; text-transform: uppercase; }
.credits-line { margin: 4px 0; font-size: 0.8rem; line-height: 1.5; }
.credits-cast { display: flex; justify-content: center; align-items: flex-end; gap: 14px; }
.credits-cast img { height: 72px; width: auto; image-rendering: pixelated; }
.credits-cast.big img { height: 150px; filter: drop-shadow(0 0 10px rgba(190, 120, 255, 0.7)); }
.credits-caption { margin: 8px 0 0; font-size: 0.75rem; color: #c8a8f0; }
.credits-end {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  opacity: 0; pointer-events: none;
}
.hof-credits.ended .credits-end { opacity: 1; transition: opacity 0.9s 0.3s; }
.credits-end h2 { margin: 0; font: 2.2rem/1.2 var(--pixel-font); color: #f8d048; text-shadow: 3px 3px 0 #4a1880; }
.credits-end p { margin: 0; font-size: 0.85rem; }
.credits-tap { animation: hofTwinkle 1s steps(2) infinite; color: #f8d048; }
@media (prefers-reduced-motion: reduce) {
  .credits-roll { position: static; padding: 24px 16px 40vh; }
  .hof-credits { overflow-y: auto; }
}

/* after the credits: the dark, and Mewtwo's last word (js/credits.js) */
.hof-credits.coda { background: #000; transition: background 1s; }
.hof-credits.coda .credits-end { opacity: 0; transition: opacity 0.6s; }
.credits-coda {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  padding: 0 24px; opacity: 0; transition: opacity 1.2s; pointer-events: none;
}
.credits-coda.in { opacity: 1; }
.credits-coda small { font: 0.75rem/1 var(--pixel-font); color: #c890ff; letter-spacing: 0.1em; }
.credits-coda p { margin: 0; max-width: 26em; font-size: 1rem; line-height: 1.6; color: #f0e8ff; }
.credits-true { font: 0.85rem/1 var(--pixel-font); color: #e8f0ff; letter-spacing: 0.2em; text-shadow: 0 0 10px #8ab8f0, 2px 2px 0 #1a2c4a; }
/* a Well only closed: Eternatus's eye opening in the dark */
.credits-eye {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  padding: 0 24px; opacity: 0; transition: opacity 0.8s; pointer-events: none;
}
.credits-eye.in { opacity: 1; }
.credits-eye-lid {
  position: relative; width: 132px; height: 40px; margin-bottom: 18px; border-radius: 50%;
  background: radial-gradient(ellipse at 50% 50%, #ffd0a0 0 12%, #ff3048 34%, #7a0c24 78%);
  box-shadow: 0 0 24px 6px rgba(255, 48, 72, 0.55); transform: scaleY(0.04); transition: transform 1.8s 0.4s cubic-bezier(0.2, 0.8, 0.3, 1);
}
.credits-eye-lid::after { content: ''; position: absolute; left: 50%; top: 8%; width: 8px; height: 84%; margin-left: -4px; border-radius: 50%; background: #1c0410; }
.credits-eye.in .credits-eye-lid { transform: scaleY(1); }
.credits-eye p { margin: 0; font: 1rem/1.4 var(--pixel-font); color: #ff6070; text-align: center; }
.credits-eye small { max-width: 26em; font-size: 0.8rem; line-height: 1.5; color: #e8c8d0; text-align: center; }
@media (prefers-reduced-motion: reduce) { .credits-eye-lid { transition: none; } }

/* the Energy Well, after Eternatus (js/well.js): one low-res canvas, Eternatus curled at the bottom, the Waystones' star */
.well-scene { position: fixed; inset: 0; z-index: 949; overflow: hidden; background: #000; }
.well-scene.waiting { cursor: pointer; }
.well-world { position: absolute; inset: 0; }
.well-canvas, .well-slide-art { position: absolute; left: 0; top: 0; width: 100%; height: 100%; image-rendering: pixelated; }
.well-scene.shaking .well-world { animation: descentShake 0.12s linear infinite alternate; }
.well-mon {
  position: absolute; left: 50%; top: 66%; width: auto; max-width: none; translate: -50% -78%; image-rendering: pixelated;
  filter: drop-shadow(0 0 12px rgba(255, 60, 90, 0.8)); transition: filter 2.5s, scale 2.5s, translate 2.5s;
}
.well-scene.spent .well-mon { filter: brightness(0.45) saturate(0.6) drop-shadow(0 0 8px rgba(176, 112, 240, 0.6)); scale: 0.82; translate: -50% -62%; animation: wellSleep 3.2s ease-in-out infinite; }
@keyframes wellSleep { 50% { translate: -50% -58%; } }
.well-star {
  position: absolute; left: 50%; top: 40%; width: min(70vw, 46vh); height: auto; translate: -50% -50%; overflow: visible;
  opacity: 0; pointer-events: none; transition: opacity 0.4s;
}
.well-scene.star .well-star { opacity: 1; }
.well-ring { fill: none; stroke: rgba(224, 200, 255, 0.5); stroke-width: 1.5; }
.well-stroke { stroke: var(--glow); stroke-width: 3; stroke-linecap: round; filter: drop-shadow(0 0 4px var(--glow)); stroke-dasharray: 160; stroke-dashoffset: 160; }
.well-scene.star .well-stroke { stroke-dashoffset: 0; transition: stroke-dashoffset 0.35s ease-out calc(var(--i) * 0.26s); }
.well-gem { fill: var(--glow); stroke: #fff; stroke-width: 1.5; filter: drop-shadow(0 0 6px var(--glow)); opacity: 0; }
.well-scene.star .well-gem { opacity: 1; transition: opacity 0.3s calc(var(--i) * 0.26s); }
.well-scene.sink .well-star { top: 66%; scale: 0.15; opacity: 0; transition: top 1.4s cubic-bezier(.5, 0, .8, .4), scale 1.4s cubic-bezier(.5, 0, .8, .4), opacity 0.5s 1.1s; }
.well-flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; transition: opacity 1.8s ease-out; }
.well-scene.white .well-flash { opacity: 1; transition: none; }
.well-scene.flash .well-flash { animation: descentFlash 0.7s ease-out; }
.well-dark { position: absolute; inset: 0; background: #000; opacity: 0; pointer-events: none; }
.well-scene.dark .well-dark { opacity: 1; transition: opacity 0.7s ease-in; }
.well-slide { position: absolute; inset: 0; opacity: 0; transition: opacity 0.6s; }
.well-slide.in { opacity: 1; }
.well-slide-cast { position: absolute; inset: 0; pointer-events: none; }
.well-cast { position: absolute; width: auto; max-width: none; translate: -50% -100%; image-rendering: pixelated; filter: drop-shadow(0 4px 0 rgba(0, 0, 0, 0.35)); }
.well-cast.wave { transform-origin: 50% 100%; animation: wellWave 1.4s ease-in-out infinite; }
@keyframes wellWave { 50% { rotate: -4deg; } }
.well-cast.ghost { opacity: 0.45; filter: drop-shadow(0 0 8px rgba(192, 112, 255, 0.8)); }
.well-cast.drift { translate: -50% -50%; filter: drop-shadow(0 0 6px rgba(255, 80, 110, 0.5)); animation: wellDrift 9s ease-in-out infinite alternate; }
@keyframes wellDrift { from { left: 22%; top: 34%; } to { left: 78%; top: 26%; } }
.well-scene.still .well-mon, .well-scene.still .well-cast, .well-scene.still .well-star { animation: none; transition: none; }
.calm-fx .well-scene.flash .well-flash { animation: calmFlash 0.7s ease-out; }
.calm-fx .well-scene.white .well-flash { opacity: 0.55; }

/* a run's full page (the books' sheet, the loss recap) */
.hof-body { display: flex; flex-direction: column; gap: 8px; }
.hof-entry {
  display: flex; align-items: center; gap: 12px; padding: 6px 10px;
  border-left: 6px solid #777; border-radius: var(--round-sm); background: rgba(48, 48, 56, 0.07);
}
.hof-entry.type-fire { border-left-color: #c8402a; }
.hof-entry.type-grass { border-left-color: #2e8a40; }
.hof-entry.type-water { border-left-color: #2a68c8; }
.hof-entry.type-psychic { border-left-color: #8a45c0; }
.hof-entry.type-electric { border-left-color: #c89a10; }
.hof-entry.type-ice { border-left-color: #3aa0c8; }
.hof-entry.type-fighting { border-left-color: #b8442c; }
.hof-entry.type-ground { border-left-color: #a87c38; }
.hof-entry.type-flying { border-left-color: #7a70d8; }
.hof-entry.type-dark { border-left-color: #6a5444; }
.hof-entry-pic { display: grid; place-items: center; flex: none; width: 96px; height: 96px; }
.hof-entry-pic img { max-width: 96px; max-height: 96px; image-rendering: pixelated; }
.hof-entry .hof-plate { flex: 1; min-width: 0; padding: 0; border: 0; background: none; box-shadow: none; }
.hof-cards { margin-top: 6px; }
/* the loss recap (lossPage()): a grey Pokémon, the blow that ended it, HP over the run */
.hof-entry.lost .hof-entry-pic img { filter: grayscale(1); opacity: 0.85; }
.loss-blow { margin: 8px 0 0; font-size: 0.75rem; line-height: 1.6; color: #a02020; }
.loss-chart {
  margin: 14px 0 0; padding: 8px 12px 6px;
  border-radius: var(--round-sm); background: rgba(48, 48, 56, 0.07); box-shadow: inset 0 0 0 2px rgba(48, 48, 56, 0.15);
  --hp: #2e8a40;
}
.loss-chart.type-fire { --hp: #c8402a; }
.loss-chart.type-water { --hp: #2a68c8; }
.loss-chart.type-psychic { --hp: #8a45c0; }
.loss-chart.type-electric { --hp: #c89a10; }
.loss-chart.type-ice { --hp: #3aa0c8; }
.loss-chart.type-fighting { --hp: #b8442c; }
.loss-chart.type-ground { --hp: #a87c38; }
.loss-chart.type-flying { --hp: #7a70d8; }
.loss-chart.type-dark { --hp: #6a5444; }
.loss-plot { position: relative; height: 84px; }
.loss-plot svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.loss-line { fill: none; stroke: var(--hp); stroke-width: 3px; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.loss-area { fill: var(--hp); opacity: 0.18; stroke: none; }
.loss-max { fill: none; stroke: rgba(48, 48, 56, 0.35); stroke-width: 1.5px; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
.loss-biome { stroke: rgba(48, 48, 56, 0.4); stroke-width: 1.5px; stroke-dasharray: 2 3; vector-effect: non-scaling-stroke; }
.loss-biome-tag { position: absolute; top: 2px; translate: 4px 0; font-size: 0.75rem; color: var(--muted); pointer-events: none; }
.loss-end { position: absolute; bottom: 0; translate: -50% 40%; font-size: 0.8rem; pointer-events: none; }
.loss-caption { margin: 6px 0 0; font-size: 0.75rem; color: var(--muted); }
/* a Champion of the Depths: gold and violet */
.hof-entry.depths {
  border-left-color: #d8b048;
  background: linear-gradient(90deg, rgba(248, 208, 72, 0.22), rgba(150, 90, 230, 0.2));
  box-shadow: inset 0 0 0 2px rgba(150, 90, 230, 0.45);
}
.dex-perk-mon { width: 56px; height: 56px; object-fit: contain; flex: none; image-rendering: pixelated; }
.dex-depths { border-color: rgba(150, 90, 230, 0.5); }
.dex-depths.earned { background: linear-gradient(90deg, rgba(248, 208, 72, 0.14), rgba(150, 90, 230, 0.14)); }
.hof-lv { font-size: 0.75rem; }
.hof-rule { margin: 6px 0 0; font-size: 0.75rem; line-height: 1.6; color: var(--muted); }
.hof-stats, .stat-grid.hof-stats { grid-template-columns: repeat(3, 1fr); gap: 6px; }
.hof-stats .stat-tile { padding: 6px 4px; gap: 2px; }
.hof-stats .stat-value { font-size: 0.95rem; }
.hof-stats .stat-icon { font-size: 1.2rem; }
.hof-stats .stat-label { font-size: 0.75rem; line-height: 1.4; }
.hof-things { display: flex; flex-wrap: wrap; gap: 8px; }
.hof-thing {
  display: flex; align-items: center; gap: 6px; padding: 4px 10px 4px 4px;
  border-radius: var(--round-sm); background: rgba(48, 48, 56, 0.07); box-shadow: inset 0 0 0 2px rgba(48, 48, 56, 0.12);
  font-size: 0.75rem; cursor: help;
}
.hof-thing.ability { background: rgba(248, 208, 72, 0.2); }
.hof-thing-icon .item-sprite { display: block; width: 32px; height: 32px; image-rendering: pixelated; }

.wide-dialog { width: min(900px, 94vw); }
.wide-dialog .card-pool { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
/* the deck view's filter and sort (js/deckpreview.js) */
.deck-tools { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px; margin: 0 0 12px; }
.deck-seg { display: flex; border: 3px solid var(--win-edge); border-radius: var(--round-sm); box-shadow: 2px 2px 0 var(--win-shadow); overflow: hidden; }
.deck-seg button {
  padding: 6px 10px 5px; border: 0; border-left: 2px solid var(--win-edge); background: var(--win-panel); color: var(--win-ink);
  font-family: var(--pixel-font); font-synthesis-weight: none; font-size: 0.75rem; cursor: pointer;
}
.deck-seg button:first-child { border-left: 0; }
.deck-seg button:hover { background: var(--win-tile); }
.deck-seg button[aria-pressed="true"] { background: #9aa2c8; color: #fff; text-shadow: 1px 1px 0 #565d84; }
.deck-empty { margin: 12px 0; text-align: center; color: var(--muted); }
@media (max-width: 420px) { .deck-seg button { padding: 6px 7px 5px; font-size: 0.75rem; } }

/* ---------- the Sealed Gate's scene (js/gatescene.js): your Pokémon attacks the gate after a run; the last blow frees
   Mewtwo. The cavern, gate and effects are one low-res canvas; it fades in from black and out again. ---------- */
.gate-scene { position: fixed; inset: 0; z-index: 950; overflow: hidden; background: #05020c; animation: gateIn 0.8s ease-out both; }
@keyframes gateIn { from { opacity: 0; } }
.gate-scene.out { opacity: 0; transition: opacity 0.7s ease-in; }
.gate-scene.waiting { cursor: pointer; }
.gate-canvas { position: absolute; left: 0; top: 0; width: 100%; height: 100%; image-rendering: pixelated; }
/* its HP, a boss bar: the name between two diamonds, the seal bar (base.css), the number under its right end */
.gate-plate {
  position: absolute; left: 50%; top: var(--gate-top, 16px); width: min(calc(100% - 32px), 320px); translate: -50% 0;
  display: flex; flex-direction: column; gap: 6px; padding: 8px 14px 6px 10px;
  background: linear-gradient(rgba(34, 18, 62, 0.92), rgba(12, 6, 24, 0.92));
  box-shadow: 0 0 0 2px #0e0818, 0 0 0 4px #544a78, 0 0 0 6px #0e0818, 0 0 24px 4px rgba(224, 42, 112, 0.25);
  font-family: var(--pixel-font); font-synthesis-weight: none; color: #ffd0e8;
  opacity: 0; animation: gatePlateIn 0.3s ease-out 0.9s forwards;
}
@keyframes gatePlateIn { from { opacity: 0; translate: -50% 8px; } to { opacity: 1; translate: -50% 0; } }
.gate-plate-name { display: flex; align-items: center; justify-content: center; gap: 10px; }
.gate-plate-name strong { font-size: 0.85rem; font-weight: normal; letter-spacing: 0.18em; text-transform: uppercase; text-shadow: 2px 2px 0 #0e0818, 0 0 8px #e02a70; }
.gate-plate-name i { width: 6px; height: 6px; rotate: 45deg; background: #ff6aa8; box-shadow: 0 0 0 1px #0e0818, 0 0 6px #ff6aa8; }
.gate-plate-num { align-self: flex-end; font-size: 0.75rem; color: #c8b8e8; text-shadow: 1px 1px 0 #0e0818; }
.gate-plate.jolt { animation: gateJolt 0.45s linear; opacity: 1; }
@keyframes gateJolt { 0%, 100% { translate: -50% 0; } 20% { translate: calc(-50% - 5px) 2px; } 40% { translate: calc(-50% + 4px) -2px; } 60% { translate: calc(-50% - 3px) 1px; } 80% { translate: calc(-50% + 2px) 0; } }
/* your Pokémon, from behind: it rises into place, lunges as it attacks */
.gate-mon {
  position: absolute; left: 30%; bottom: calc(max(16px, env(safe-area-inset-bottom)) + 74px);
  max-width: none; translate: -50% calc(var(--foot, 0px) + 40px); opacity: 0;
  transition: translate 0.5s cubic-bezier(0.2, 1.4, 0.4, 1), opacity 0.3s; image-rendering: pixelated;
}
.gate-scene.mon-in .gate-mon { translate: -50% var(--foot, 0px); opacity: 1; }
.gate-mon.lunge { animation: gateLunge 0.6s ease-out both; }
@keyframes gateLunge { 0%, 100% { scale: 1; } 30% { scale: 1.08; translate: -40% calc(var(--foot, 0px) - 18px); } 60% { scale: 1; } }
@media (min-width: 900px) { .gate-mon { left: 36%; } }
/* the damage, popping up off the seal like battle's numbers */
.gate-dmg {
  position: absolute; translate: -50% -50%; opacity: 0; pointer-events: none;
  font: 2rem/1 var(--pixel-font); font-synthesis-weight: none; color: #fff;
  text-shadow: 3px 0 0 #8a1040, -3px 0 0 #8a1040, 0 3px 0 #8a1040, 0 -3px 0 #8a1040, 3px 3px 0 #2a0414;
}
.gate-dmg.go { animation: gateDmg 1.4s ease-out both; }
@keyframes gateDmg { 0% { opacity: 1; translate: -50% -50%; scale: 0.6; } 15% { scale: 1.3; } 25% { scale: 1; } 75% { opacity: 1; } 100% { opacity: 0; translate: -50% -180%; } }
/* the break: the screen whites out, then Mewtwo steps out of the arch, a silhouette until its colours flood in */
.gate-flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; }
.gate-scene.white .gate-flash { opacity: 1; transition: opacity 0.22s ease-in; }
.gate-scene.after-white .gate-flash { opacity: 0; transition: opacity 1.4s ease-out; }
.gate-scene.white .gate-mon, .gate-scene.after-white .gate-mon { filter: brightness(0.6); }
.gate-free { position: fixed; width: 0; height: 0; }
.gate-free img { position: absolute; left: 0; bottom: 0; max-width: none; translate: calc(-50% + var(--dx, 0px)) var(--foot, 0px); scale: 0.55; transform-origin: 50% 100%; image-rendering: pixelated; }
.gate-free.step img { scale: 1; translate: calc(-50% + var(--dx, 0px)) calc(var(--foot, 0px) + 6vh); transition: scale 1s ease-out, translate 1s ease-out; }
.gate-free.dark img { filter: brightness(0) drop-shadow(0 0 2px #e0c0ff) drop-shadow(0 0 1px #b070ff); }
.gate-free.flash img { animation: gateFreeFlash 0.5s steps(1, end); }
@keyframes gateFreeFlash { 0%, 40% { filter: brightness(0) invert(1); } 20%, 60% { filter: brightness(0); } 100% { filter: none; } }
/* the strike card (strikeCard() in js/gatescene.js): hold it to charge the move, let go and it flies into the seal. A long
   press on a phone would select text, pop the image callout or scroll the page, so all three are off on it */
.gate-strike {
  --charge: 0;
  position: absolute; z-index: 2; right: max(16px, 7vw); bottom: calc(max(16px, env(safe-area-inset-bottom)) + 124px);
  width: min(46vw, 210px, 28vh); display: flex; flex-direction: column; align-items: center; gap: 10px;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; touch-action: none; -webkit-tap-highlight-color: transparent;
  cursor: pointer; outline: none; animation: strikeIn 0.5s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}
.gate-strike * { pointer-events: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
@keyframes strikeIn { from { transform: translate3d(0, 60vh, 0); rotate: 12deg; } to { transform: translate3d(0, 0, 0); } }
.gate-strike .card {
  scale: calc(1 + var(--charge) * 0.1); transition: none;
  filter: drop-shadow(0 0 calc(4px + var(--charge) * 24px) var(--c1)) brightness(calc(1 + var(--charge) * 0.35));
  animation: strikeBob 1.6s ease-in-out infinite;
}
@keyframes strikeBob { 50% { translate: 0 -6px; } }
.gate-strike.held .card, .gate-strike.full .card { animation: strikeShake 0.09s linear infinite alternate; }
@keyframes strikeShake { 0% { translate: calc(var(--charge) * -3px) calc(var(--charge) * 2px); } 100% { translate: calc(var(--charge) * 3px) calc(var(--charge) * -2px); } }
.gate-strike:focus-visible .card-face { outline: 3px solid #ffd0e8; outline-offset: 4px; }
/* the charge: a ring filling round, and HOLD turning to LET GO! once it's full */
.gate-strike-hint { display: flex; align-items: center; gap: 8px; font: 0.8rem/1 var(--pixel-font); font-synthesis-weight: none; color: #ffd0e8; text-shadow: 2px 2px 0 #0e0818; }
.gate-strike-ring {
  width: 30px; height: 30px; border-radius: 50%;
  background: conic-gradient(#ff6aa8 calc(var(--charge) * 360deg), rgba(255, 255, 255, 0.16) 0);
  -webkit-mask: radial-gradient(circle, transparent 9px, #000 10px); mask: radial-gradient(circle, transparent 9px, #000 10px);
}
.gate-strike:not(.held):not(.full) .gate-strike-label { animation: strikeBlink 1s steps(1) infinite; }
@keyframes strikeBlink { 50% { opacity: 0.35; } }
.gate-strike.full .gate-strike-ring { background: #ffd040; box-shadow: 0 0 12px #ffd040; }
.gate-strike.full .gate-strike-label { color: #fff8c0; text-shadow: 2px 2px 0 #0e0818, 0 0 8px #ffd040; }
/* the breaking blow's card is gold foil; a lost run's is grey and cracked */
.gate-strike.gold .card-face { --edge: #ffd34a; --halo: 0 0 18px 4px rgba(255, 208, 64, 0.6); }
.gate-foil {
  position: absolute; inset: 0; border-radius: inherit; mix-blend-mode: screen;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 240, 170, 0.75) 48%, rgba(255, 255, 255, 0.9) 50%, rgba(255, 200, 80, 0.6) 53%, transparent 65%) 0 0 / 300% 100%;
  animation: strikeFoil 2s linear infinite;
}
@keyframes strikeFoil { from { background-position: 100% 0; } to { background-position: -50% 0; } }
.gate-strike.weak .card-face::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; opacity: 0.8;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 74' fill='none' stroke='%23202028' stroke-width='1.2'%3E%3Cpath d='M30 0 L26 14 L32 22 L24 34 L28 44 L20 58 L23 74'/%3E%3Cpath d='M32 22 L42 28 M24 34 L12 38 M28 44 L38 52'/%3E%3C/svg%3E") 0 0 / 100% 100%;
}
/* let go: it flies into the seal, shrinking and burning white */
.gate-strike.thrown { animation: strikeThrow 0.4s ease-in forwards; }
.gate-strike.thrown .gate-strike-hint { visibility: hidden; }
@keyframes strikeThrow { from { translate: 0 0; } 25% { translate: 0 18px; scale: 1.05; } to { translate: var(--tx) var(--ty); scale: 0.12; rotate: -30deg; opacity: 0; filter: brightness(4); } }
/* your Pokémon glows brighter and trembles as the charge builds */
.gate-scene.charging .gate-mon { filter: brightness(calc(1 + var(--charge) * 0.7)); animation: strikeTremble 0.08s linear infinite alternate; }
@keyframes strikeTremble { 0% { transform: translateX(calc(var(--charge) * -2px)); } 100% { transform: translateX(calc(var(--charge) * 2px)); } }
.gate-scene.still .gate-strike, .gate-scene.still .gate-strike .card, .gate-scene.still .gate-strike-label, .gate-scene.still .gate-foil, .gate-scene.still.charging .gate-mon { animation: none; }
.gate-scene.still .gate-strike.thrown { opacity: 0; }
.gate-scene.still, .gate-scene.still .gate-plate, .gate-scene.still .gate-plate.jolt { animation: none; opacity: 1; }
.gate-scene.still .gate-mon, .gate-scene.still .gate-free img { transition: none; }
.gate-scene.still .gate-mon.lunge, .gate-scene.still .gate-dmg.go, .gate-scene.still .gate-free.flash img { animation: none; }
.gate-scene.still .gate-dmg.go { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .gate-scene.white .gate-flash { opacity: 0.6; } }

/* ---------- enemy portraits: pixel sprites, elites and bosses ---------- */
/* pixel sprites stand in the scene frameless, like your Pokémon; the glow marks elites and bosses */
.enemy-portrait.sprite { border: 0; border-radius: 0; box-shadow: none; overflow: visible; }
.enemy-portrait.sprite img { object-fit: contain; object-position: 50% 100%; translate: calc(var(--shift, 0) * 100%) calc(var(--drop, 0) * 100%); --rest: drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); filter: var(--rest); }
/* one shadow layer, the glow only: two blurred drop-shadows on an animated GIF are redrawn every frame, and an Alpha
   (Linoone) lagged on the user's phone; the glow already sits round the feet */
.enemy-portrait.sprite.elite img { --rest: drop-shadow(0 0 10px #ff3b3b); }
.enemy-portrait.sprite.boss img  { --rest: drop-shadow(0 0 12px var(--gold)); }
/* a boss's second form (Eternamax, rebirth() in js/battle.js): a crimson glow in place of the gold, breathing; it pulses
   hot while it charges a huge hit; the first form sinks into the Well, brightening, and the second comes down from the
   rift in the roof (bossRebirth() in js/scene.js), a black silhouette taking on its colours as it lands */
.enemy-portrait.sprite.boss.max img { --rest: drop-shadow(0 0 14px #ff2a6a) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); animation: maxBreath 2.4s ease-in-out infinite; }
@keyframes maxBreath { 50% { filter: drop-shadow(0 0 22px #ff2a6a) drop-shadow(0 0 4px #fff0f6) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); } }
.enemy-portrait.sprite.boss.charging img { animation: maxCharge 0.5s ease-in-out infinite; }
@keyframes maxCharge { 50% { filter: brightness(1.6) drop-shadow(0 0 26px #ff5a8a) drop-shadow(0 0 8px #fff) drop-shadow(0 8px 6px rgba(0, 0, 0, 0.5)); } }
.enemy-portrait.sinking { animation: bossSink 1.8s ease-in forwards; }
@keyframes bossSink {
  0%, 30% { transform: none; filter: none; opacity: 1; }
  10%, 20% { transform: translateX(-6px); }
  15%, 25% { transform: translateX(6px); }
  100% { transform: translateY(40px) scale(0.5, 0.2); filter: brightness(3) saturate(0) drop-shadow(0 0 20px #ff2a6a); opacity: 0; }
}
.enemy-zone.emerging .enemy-portrait { animation: bossEmerge 1.4s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
@keyframes bossEmerge {
  from { transform: translateY(-70%) scale(1.5); filter: brightness(0) drop-shadow(0 0 10px #ff2a6a); }
  55% { filter: brightness(0) drop-shadow(0 0 14px #ff2a6a); }
  80% { filter: brightness(2) saturate(0.5) drop-shadow(0 0 18px #ff2a6a); }
  to { transform: none; filter: none; }
}
/* The enemy's body language (renderPose() in js/battle.js), on its own wrapper so it never fights the box's lunge, sink
   and drop-in or the GIF's recoil and glow. Both pivot on the feet, which sizeSprite() puts at the box's bottom middle:
   a raised attack makes it crouch and flinch back (transform), low HP makes it sway (rotate), so the two stack. */
.enemy-pose { position: relative; width: 100%; height: 100%; transform-origin: 50% 100%; transition: transform 0.16s ease-out; }
.enemy-pose.bracing { transform: translateX(4px) skewX(-3deg) scale(1.05, 0.9); }
.enemy-pose.swaying { animation: lowSway 2.8s ease-in-out infinite; }
@keyframes lowSway {
  0%, 100% { rotate: 0deg; }
  25% { rotate: -3.5deg; }
  50% { rotate: 0.5deg; }
  75% { rotate: 2.5deg; }
}
.enemy-portrait:is(.defeated, .sinking, .captured, .ran) .enemy-pose { transform: none; animation: none; }
@media (prefers-reduced-motion: reduce) { .enemy-pose { transform: none !important; animation: none !important; transition: none; } }
/* Kenmatta's Super Saiyan aura (js/aura.js): a canvas laid over his sprite, hidden while he's still a silhouette */
.aura-fx { position: absolute; image-rendering: pixelated; pointer-events: none; }
.enemy-zone.entering .aura-fx, .enemy-zone.boss-waiting .aura-fx { visibility: hidden; }
.enemy-portrait.elite:not(.sprite) { border-color: #ff5a5a; box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.5), 0 0 30px #ff3b3b, 0 10px 24px rgba(0, 0, 0, 0.6); }
.enemy-portrait.boss:not(.sprite)  { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.5), 0 0 36px var(--gold), 0 10px 24px rgba(0, 0, 0, 0.6); }

/* ---------- phones (kept last so it wins over the rules above) ---------- */
@media (max-width: 720px) {
  .reward-options { gap: 12px; }
  /* relic, item and choice tiles become short rows (icon | name over text), stacked, instead of tall windows */
  .reward-options:not(.mart-window) > .reward-option:has(> .relic) { width: min(100%, 420px); }
  .reward-options:not(.mart-window) > .reward-option > .relic {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "icon name" "icon text";
    align-content: center;
    justify-items: start;
    gap: 4px 14px;
    min-height: 0;
    padding: 12px 14px;
    text-align: left;
  }
  .reward-options:not(.mart-window) .relic > .relic-icon { grid-area: icon; font-size: 2.4rem; }
  .reward-options:not(.mart-window) .relic > .relic-name { grid-area: name; }
  .reward-options:not(.mart-window) .relic > :not(.relic-icon, .relic-name) { grid-column: 2; }
}

/* phones: a gap between the two columns, so a nameplate never touches the sprite beside it */
@media (max-width: 720px) {
  .arena { column-gap: 10px; padding-bottom: calc(2.125rem + 34px); }   /* the phones' smaller text box */
}
/* short phones (iPhone SE): the scene is tight, so make the nameplates compact, shrink the enemy and let
   your nameplate and Pokémon sit lower, so your nameplate clears the enemy's feet */
@media (max-width: 720px) and (max-height: 700px) {
  .arena { padding-bottom: calc(2.125rem + 30px); }
  .nameplate { padding: 4px 7px 4px; gap: 2px; }
  .nameplate-title strong { font-size: 0.78rem; }
  .nameplate .gb-hp-num { font-size: 0.75rem; }
  .enemy-zone { --base: clamp(70px, 12.5vh, 100px); }
  .player-zone { padding-bottom: 4px; }
  .enemy-zone { gap: 3px; }
  .intent { margin-bottom: 5px; }
}

.panel > .hint { margin-top: 12px; }


.run-name { display: flex; align-items: center; gap: 8px; }
.level-chip { background: #6b4b00; color: #ffe27a; border: 1px solid var(--gold); }
.level-chip.replay { background: #1f3a5a; color: #cfe8ff; border-color: #6aa8e0; }

/* ---------- coin display (topbar + shop) ---------- */
.coin-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 6px;
  font-family: var(--pixel-font);
  font-size: 1.25rem;
  color: #f8d030;
  text-shadow: 2px 2px 0 #181010, -1px -1px 0 #181010, 1px -1px 0 #181010, -1px 1px 0 #181010;   /* floats on the scenery like the Poké Mart, so a hard pixel outline keeps it readable */
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5));
  white-space: nowrap;
}

/* The Game Corner (the home shop, spent in PokéCoins): a pixel slot machine (🎰 in js/icons.js), kept apart
   from the run's blue Poké Mart building, which is spent in ₽. Sized by font-size, like every pixel icon. */
.gc-icon { display: inline-block; vertical-align: middle; line-height: 0; }
.shop-btn .gc-icon { font-size: 30px; }
/* the PokéCoins slide opens on coin ▶ slot machine: what they're for, before how to earn them */

/* No button chrome: the slot machine itself is the button, with a shadow so it reads over any backdrop */
.icon-btn.shop-btn {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border: 0;
  background: none;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.6));
  transition: transform 0.12s, filter 0.2s;
}
.icon-btn.shop-btn:hover { background: none; transform: translateY(-2px) scale(1.08); }
.icon-btn.shop-btn:active { transform: scale(0.92); }
/* while the shop is open: pressed in, with a soft white halo */
.icon-btn.shop-btn[aria-expanded="true"] { transform: scale(0.92); filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.8)); }
/* narrow phones: tighten the floating buttons so they all fit on one row */
@media (max-width: 420px) {
  .topbar { padding: 0 max(10px, env(safe-area-inset-left)); }
  .topbar-actions { gap: 5px; }
  .icon-btn { width: 32px; height: 32px; }
  .shop-btn .gc-icon { font-size: 24px; }
  .coin-pill { padding: 4px; }
  /* in battle the piles would crowd the row out, so the PokéCoins (which can't change mid-fight) step aside for the ₽ */
  body[data-screen="battle-screen"] .coin-pill:not(.money-pill) { display: none; }
  /* the HP plate squeezes in beside the Poké Ball: its bar's HP: tag goes, the numbers shrink */
  .hp-plate { gap: 4px; margin-left: 4px; }
  .hp-plate .gb-hp { width: 50px; }
  .hp-plate .gb-hp-tag { display: none; }
  .hp-plate .gb-hp-track { border-radius: 6px; }
  .hp-plate .gb-hp-num { font-size: 0.75rem; letter-spacing: 0; }
}
@media (max-width: 340px) {
  .topbar-actions { gap: 3px; }
  body[data-screen="reward-screen"] .coin-pill:not(.money-pill) { display: none; }   /* room for the HP plate */
  .icon-btn { width: 30px; height: 30px; }
  .coin-pill { padding: 3px; }
}

/* ---------- 6. GAME CORNER (the home shop) ---------- */
/* Non-modal (.show(), not .showModal()) so it floats above the current
   screen like a PiP window instead of blocking it - no ::backdrop dims the
   page, and the map/battle/reward screen underneath stays fully clickable. */
#shop-dialog {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  z-index: 90;
}
/* opened modally over the Safari's prep window: undo the top layer's inset: 0, or it stretches down to the bottom */
#shop-dialog:modal { right: auto; bottom: auto; }
/* An arcade cabinet in pixel art (after the user's reference photo): a charcoal body between brass side trims, two
   speaker grilles round the sign, a teal CRT in a curved black bezel, and a control deck with one red ball-top
   joystick and two round buttons. Hard-edged bands everywhere instead of soft gradients, to match the 8-bit look. */
#shop-dialog.gc-cabinet {
  --cab: #2c2c34;
  --cab-dark: #1c1c22;
  --brass: #d8a830;
  --crt-ink: #e8fff4;
  width: min(360px, 94vw);
  max-height: 96dvh;
  padding: 10px 18px 14px;
  border: 0;
  border-radius: var(--round) var(--round) var(--round-xs) var(--round-xs);
  background:
    linear-gradient(90deg, transparent 11px, rgba(255, 255, 255, 0.06) 11px 15px, transparent 15px calc(100% - 15px), rgba(0, 0, 0, 0.3) calc(100% - 15px) calc(100% - 11px), transparent calc(100% - 11px)),
    var(--cab);
  box-shadow:
    inset 3px 0 0 #181010, inset -3px 0 0 #181010,
    inset 6px 0 0 #f8e088, inset -6px 0 0 #8a5c10,
    inset 9px 0 0 var(--brass), inset -9px 0 0 var(--brass),
    inset 11px 0 0 #181010, inset -11px 0 0 #181010,
    0 0 0 3px #181010, 0 20px 60px rgba(0, 0, 0, 0.6);
  color: var(--crt-ink);
  overflow: auto;
}
.gc-marquee { display: grid; grid-template-columns: 44px 1fr 44px; align-items: center; gap: 8px; margin: 2px 0 12px; }
.gc-grille svg { display: block; width: 44px; height: 44px; }
#shop-dialog .gc-sign {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 0 4px;
  padding: 6px 8px;
  border: 0;
  border-radius: var(--round-xs);
  background: linear-gradient(#6a2890 0 50%, #4a1870 50%);
  box-shadow: 0 0 0 3px #181010, 0 0 0 5px var(--brass), 0 0 0 7px #181010;
}
.gc-sign .gc-icon { font-size: 26px; }
#shop-dialog .gc-title {
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 0.95rem;
  font-weight: 400;
  line-height: 1.25;
  text-transform: uppercase;
  color: #f8d030;
  text-shadow: 2px 0 0 #181010, -2px 0 0 #181010, 0 2px 0 #181010, 0 -2px 0 #181010, 0 4px 0 #8a4c06;
  animation: signGlow 1.6s steps(2) infinite;
}
@keyframes signGlow { 50% { color: #fff0a0; } }

/* the screen: a black bezel with curved corners round a teal tube, scanlines over it and a glow at its middle */
.gc-bezel { padding: 10px; border-radius: 22px; background: #0c0c10; box-shadow: 0 0 0 3px #181010, inset 0 2px 0 #3a3a44; }
.gc-crt {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 10px 12px;
  border-radius: 16px / 22px;
  background: radial-gradient(ellipse at 50% 45%, #2a9c86 0%, #1a7464 55%, #0e4a40 100%);
  box-shadow: inset 0 0 18px rgba(0, 0, 0, 0.55), inset 0 0 0 2px #0a3a32;
  overflow: hidden;
}
#shop-dialog .gc-crt * { text-shadow: 2px 2px 0 rgba(0, 20, 16, 0.6); }   /* a hard shadow: the old soft glow blurred the pixel letters */
.gc-crt::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(rgba(0, 0, 0, 0.1) 0 1px, transparent 1px 3px);
  pointer-events: none;
}
.gc-crt-head { display: flex; justify-content: space-between; align-items: center; font-size: 0.75rem; text-transform: uppercase; color: #e8fff4; }
.gc-coins { color: #f8e070; }

/* the highlighted choice, big, character-select style */
.gc-pick { display: grid; justify-items: center; align-content: start; gap: 5px; min-height: 180px; text-align: center; }
.gc-pick-art { display: grid; place-items: center; height: 88px; }
.gc-pick-sprite { width: 96px; height: 96px; object-fit: contain; image-rendering: pixelated; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.35)); }
.gc-pick-icon { font-size: 60px; line-height: 0; }
/* the words on a dark plate, above the scanlines (the ::after), so they read cleanly */
.gc-pick-plate {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  gap: 7px;
  width: 100%;
  padding: 8px 10px 9px;
  border-radius: var(--round-sm);
  background: rgba(4, 30, 26, 0.72);
  box-shadow: inset 0 0 0 2px rgba(152, 240, 210, 0.25);
}
.gc-pick-name { font-size: 1rem; font-weight: 400; color: #fff; }
.gc-pick-text { font-size: 0.75rem; line-height: 1.6; color: #e0fff0; max-width: 30ch; }
.gc-news { font-size: 0.75rem; line-height: 1.6; color: #f8e070; max-width: 30ch; animation: gcNews 0.8s steps(1) infinite; }
@keyframes gcNews { 50% { color: #fff; } }
.gc-pick-foot { display: flex; align-items: center; gap: 12px; margin-top: 2px; font-size: 0.85rem; }
.gc-level { color: #e0fff0; }
.gc-price { color: #f8e070; }
.gc-price.short { color: #ffa898; }
.gc-pick .shop-owned { color: #98f8a8; font-weight: 400; }
.gc-pick .shop-owned .pokeball { font-size: 1.8em; }
.gc-pick.won { animation: gcFlash 0.6s steps(2) 2; }
.gc-pick.flash { animation: gcFlash 0.4s steps(2) 3; }
@keyframes gcFlash { 50% { filter: brightness(2.2); } }
@keyframes twinkle { 50% { opacity: 0.2; transform: scale(0.6); } }

/* the roster: Pokémon on top, perks under, with a blinking cursor frame round the pick */
.gc-roster { display: grid; gap: 6px; }
.gc-row { display: flex; justify-content: center; gap: 5px; }
.gc-cell {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 2px solid #0a3a32;
  border-radius: var(--round-xs);
  background: rgba(8, 48, 42, 0.6);
  cursor: pointer;
}
.gc-cell img { width: 36px; height: 36px; object-fit: contain; image-rendering: pixelated; }
.gc-cell-icon { font-size: 24px; line-height: 0; }
.gc-cell .shop-owned { position: absolute; right: -4px; bottom: -4px; }
.gc-cell .shop-owned .pokeball { font-size: 20px; }
.gc-cell.on { border-color: #f8e070; box-shadow: 0 0 0 2px #181010, 0 0 8px #f8e070; animation: gcCursor 0.8s steps(1) infinite; }
@keyframes gcCursor { 50% { border-color: #e83828; } }
.gc-more { align-self: center; width: 8px; font-size: 0.75rem; color: #b8f0dc; }   /* more cells past the row's window */
.gc-more.none { visibility: hidden; }
.gc-cell img.dark, .gc-pick-sprite.dark { filter: brightness(0) opacity(0.55); }   /* a shiny for a starter you haven't unlocked */

/* the control deck: a brass lip, then the joystick on the left and the two buttons on the right */
.gc-deck {
  display: flex;
  align-items: center;
  justify-content: space-around;
  gap: 12px;
  margin: 14px -4px 0;
  padding: 10px 8px 8px;
  border-radius: var(--round-xs);
  background: linear-gradient(#3a3a44 0 4px, var(--cab-dark) 4px);
  box-shadow: 0 -3px 0 var(--brass), 0 -5px 0 #181010, 0 0 0 2px #181010;
}
/* the stick: a dark washer with four printed arrows (tap them), a shaft and a red ball you can drag */
.gc-stick {
  --tx: 0px;
  --ty: 0px;
  position: relative;
  flex: none;
  width: 104px;
  height: 104px;
  border-radius: 50%;
  background: radial-gradient(circle, #101014 0 24%, #3a3a44 25% 27%, #26262e 28%);
  box-shadow: 0 0 0 3px #181010, inset 0 3px 0 #4a4a54;
  touch-action: none;
  cursor: pointer;
}
.gc-pad {
  position: absolute;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  background: none;
  pointer-events: none;   /* a press lands on the stick itself (initDrag()); the pads are for keyboards */
}
.gc-pad::before {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 16px;
  height: 13px;
  background: #b8b8c2;
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}
.gc-pad:focus-visible::before { background: #f8e070; }
.gc-stick.held .gc-pad::before { background: #d8d8e0; }
.gc-pad.up { top: 0; left: 37px; }
.gc-pad.down { bottom: 0; left: 37px; rotate: 180deg; }
.gc-pad.left { left: 0; top: 37px; rotate: -90deg; }
.gc-pad.right { right: 0; top: 37px; rotate: 90deg; }
.gc-shaft {
  position: absolute;
  left: 49px;
  bottom: 52px;
  width: 6px;
  height: 22px;
  background: linear-gradient(90deg, #d0d0d8 0 2px, #888890 2px 4px, #505058 4px);
  transform-origin: 50% 100%;
  transform: rotate(calc(var(--tx) / 1px * 2.4deg)) scaleY(calc(1 - var(--ty) / 30px));
  pointer-events: none;
}
.gc-ball {
  position: absolute;
  left: 34px;
  top: 14px;
  width: 36px;
  height: 33px;
  translate: var(--tx) var(--ty);
  touch-action: none;
  cursor: grab;
  filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.45));
}
.gc-stick.held .gc-ball { cursor: grabbing; }
.gc-stick:not(.held) .gc-ball { transition: translate 0.08s ease-out; }
.gc-stick:not(.held) .gc-shaft { transition: transform 0.08s ease-out; }
.gc-ball svg { display: block; width: 100%; height: 100%; }

/* the arcade buttons: a pink Buy and a blue Exit, pressed in while held; Buy blinks once armed */
.gc-buttons { display: flex; align-items: flex-start; gap: 14px; }
.gc-btn-wrap { display: grid; justify-items: center; gap: 8px; margin: 0; }
.gc-btn {
  --face: #f878b0;
  --edge: #a83870;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 3px solid #181010;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff 0 4px, var(--face) 5px);
  box-shadow: 0 5px 0 var(--edge), 0 5px 0 3px #181010;
  cursor: pointer;
  transition: translate 0.06s, box-shadow 0.06s;
}
.gc-btn.exit { --face: #58a8f8; --edge: #1848a0; width: 38px; height: 38px; margin-top: 4px; }
.gc-btn:active:not(:disabled) { translate: 0 4px; box-shadow: 0 1px 0 var(--edge), 0 1px 0 3px #181010; }
.gc-btn:focus-visible { outline: 3px solid #f8e070; outline-offset: 6px; }
.gc-btn:disabled { --face: #888890; --edge: #505058; cursor: default; }
.gc-btn.armed { animation: gcArmed 0.5s steps(1) infinite; }
@keyframes gcArmed { 50% { background: radial-gradient(circle at 35% 30%, #fff 0 4px, #fff0a0 5px); } }
.gc-btn-label { font-size: 0.75rem; text-transform: uppercase; color: #c8c8d0; }
#gc-buy:disabled + .gc-btn-label { color: #707078; }

@media (max-height: 700px) {
  #shop-dialog.gc-cabinet { padding-top: 8px; }
  .gc-marquee { grid-template-columns: 34px 1fr 34px; margin-bottom: 10px; }
  .gc-grille svg { width: 34px; height: 34px; }
  .gc-pick { min-height: 160px; }
  .gc-pick-art { height: 72px; }
  .gc-pick-sprite { width: 80px; height: 80px; }
  .gc-deck { margin-top: 12px; padding-top: 8px; }
}
/* an iPhone SE (568px): the bigger, readable text needs the room, so the art and the sign shrink instead */
@media (max-height: 600px) {
  .gc-marquee { grid-template-columns: 28px 1fr 28px; margin-bottom: 6px; }
  .gc-grille svg { width: 28px; height: 28px; }
  #shop-dialog .gc-sign { padding: 3px 8px; }
  .gc-pick { min-height: 0; gap: 3px; }
  .gc-pick-art { height: 46px; }
  .gc-pick-sprite { width: 56px; height: 56px; }
  .gc-pick-icon { font-size: 40px; }
  .gc-pick-plate { gap: 4px; padding: 6px 8px; }
  .gc-crt { gap: 5px; }
  .gc-deck { margin-top: 8px; padding-top: 6px; zoom: 0.8; }   /* zoom, unlike scale, gives the room back to the layout */
}
@media (prefers-reduced-motion: reduce) {
  #shop-dialog .gc-title, .gc-cell.on, .gc-btn.armed, .gc-pick.won, .gc-pick.flash, .gc-news { animation: none; }
  .gc-btn.armed { background: radial-gradient(circle at 35% 30%, #fff 0 4px, #fff0a0 5px); }
}
.shop-owned { display: inline-flex; align-items: center; gap: 6px; font-weight: 800; color: #1f7a38; }
.shop-owned .pokeball { font-size: 2.2em; margin: 0; border-width: 0.06em; box-shadow: none; animation: none; }

/* ---------- 7. ICON ROWS (the Bag's pockets: relics, items, augments, the map key) ---------- */
/* How to play itself is an app on the Pokédex device now (js/howto.js, on shelfApp()'s styles) */
.pdx-banner .howto-banner-art.bdx-banner-things { right: 6px; top: 50%; bottom: auto; translate: 0 -50%; gap: 0; align-items: center; }
.pdx-banner .howto-banner-art .bdx-banner-thing { width: 68px; height: 68px; padding: 0; translate: none; }
.pdx-banner .howto-banner-art > * + * { margin-left: -18px; }
.pdx-banner .howto-banner-art > :nth-child(2) { width: 90px; height: 90px; z-index: 1; }
.pdx-banner .howto-banner-art .bdx-banner-mon { width: 104px; height: 104px; margin: 0 -10px 0 -22px; object-position: center; }
.pdx-banner:has(.howto-banner-art) .pdx-banner-sub { max-width: 34%; }
.howto-tricard { display: flex; align-items: flex-end; padding: 0 6px 4px 0; }
.howto-minicard {
  position: relative; display: grid; place-items: center; width: 60px; height: 82px; margin: 0 -6px;
  border: 3px solid #fff; border-radius: 8px; box-shadow: 0 3px 0 rgba(0, 0, 0, 0.3);
}
.howto-minicard .smooth-icon { width: 40px; height: 40px; }
.howto-minicard.fire  { background: linear-gradient(160deg, #ffa070, #e0602c); rotate: -12deg; translate: 0 6px; }
.howto-minicard.grass { background: linear-gradient(160deg, #98d880, #4ea040); z-index: 1; }
.howto-minicard.water { background: linear-gradient(160deg, #8ab0ff, #3c70d8); rotate: 12deg; translate: 0 6px; }
.howto-minicost {
  position: absolute; top: -8px; left: -8px; width: 20px; height: 20px; display: grid; place-items: center;
  border: 2px solid #e06058; border-radius: 50%; background: #fff; color: #2a2a3a; font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none;
}
.howto-about { display: block; width: 100%; margin: 0 0 10px; padding: 9px 12px; border: 0; text-align: center; cursor: pointer; }

/* icon + name + one-line explanation */
.howto-list { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; text-align: left; }
/* a lone last row gets its own line but stays the others' width, centred */
.howto-li:last-child:nth-child(odd) { grid-column: 1 / -1; justify-self: center; width: calc((100% - 8px) / 2); }
.howto-li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--panel-edge);
}
.howto-li .howto-node { flex: none; }
.howto-li-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.howto-li-text b { font-size: 0.92rem; }
.howto-li-text small { font-size: 0.8rem; line-height: 1.25; color: var(--muted); }

/* bare icons (map rooms, relics, items): no chip or frame, the user's call */
.howto-node {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  font-size: 1.5rem;
}
.howto-node.building svg { width: 100%; height: auto; display: block; }

@media (max-width: 560px) {
  .howto-list { grid-template-columns: 1fr; gap: 6px; }
  .howto-li:last-child:nth-child(odd) { width: auto; justify-self: stretch; }
  .howto-li { padding: 5px 10px; gap: 10px; }
  .howto-li .howto-node { width: 34px; height: 34px; font-size: 1.35rem; }
}

/* ---------- a move not met yet in the Moves app: a greyed card, its art a black silhouette, ??? for the rest (lockedCard() in js/cardindex.js) ---------- */
.card.index-locked { filter: grayscale(1) brightness(0.7); cursor: default; }
.card.index-locked .card-art > * { filter: brightness(0) opacity(0.6); }
.card.index-locked .card-text { display: grid; place-items: center; font-size: 1.4em; color: #707078; }
.index-only { font-family: var(--pixel-font); font-synthesis-weight: none; font-size: 0.75rem; padding: 3px 6px; border-radius: var(--round-xs); color: #fff; background: #777; }
.index-only.type-fire { background: #c8402a; }
.index-only.type-grass { background: #2e8a40; }
.index-only.type-water { background: #2a68c8; }
.index-only.type-psychic { background: #7138a8; }
.index-only.type-electric { background: #b88a00; }
/* the Safari's real types (js/data/real-types.js) */
.index-only.type-normal { background: #86866a; }
.index-only.type-electric { background: #b08a00; }
.index-only.type-ice { background: #2f98a8; }
.index-only.type-fighting { background: #a83028; }
.index-only.type-poison { background: #84389a; }
.index-only.type-ground { background: #9a7434; }
.index-only.type-flying { background: #6a62c0; }
.index-only.type-bug { background: #6e8c14; }
.index-only.type-rock { background: #8a7630; }
.index-only.type-ghost { background: #56468a; }
.index-only.type-dragon { background: #5434c8; }
.index-only.type-dark { background: #584636; }
.index-only.type-steel { background: #6a6a88; }
.index-only.type-fairy { background: #c05a90; }
#dex-total { white-space: nowrap; }
@media (max-width: 720px) { #dex-total { font-size: 0.75rem; } }

/* ---------- 8. STATS & ACHIEVEMENTS (from the Poké Ball menu) ---------- */
.records-dialog { width: min(560px, 94vw); }
.records-dialog h2 { outline: none; }
.records-sub { margin: -6px 0 14px; color: var(--muted); font-size: 0.9rem; }
.records-label {
  margin: 18px 0 8px;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.records-empty { color: var(--muted); font-size: 0.9rem; }
.records-close { margin-top: 18px; text-align: center; }

/* the Patch notes window (js/patchnotes.js) */
.patch-dialog { max-height: 88vh; flex-direction: column; }
.patch-dialog[open] { display: flex; }
.patch-body { overflow-y: auto; min-height: 0; padding-right: 4px; }
.patch-title { margin: 0; font-size: 0.9rem; line-height: 1.5; color: var(--gold); }
.patch-date { margin: 2px 0 6px; font-size: 0.75rem; color: var(--muted); }
.patch-head { margin: 14px 0 6px; font-size: 0.75rem; display: flex; align-items: center; gap: 6px; }
.patch-list li { margin: 0; }
.patch-list { margin: 0; padding-left: 1.4em; display: flex; flex-direction: column; gap: 6px; font-size: 0.75rem; line-height: 1.6; }
.patch-game { display: flex; flex-direction: column; gap: 10px; }
.patch-row { display: grid; grid-template-columns: 26px 1fr; gap: 8px; align-items: start; }
.patch-row-icon { display: grid; place-items: center; padding-top: 2px; }
.patch-row-text { display: flex; flex-direction: column; gap: 3px; font-size: 0.75rem; line-height: 1.6; }
.patch-row-text b { font-size: 0.75rem; }

.stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.stat-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 12px 6px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--panel-edge);
  text-align: center;
}
.stat-icon { font-size: 1.3rem; }
.stat-value { font-size: 1.6rem; font-weight: 900; color: var(--gold); line-height: 1.1; }
.stat-label { font-size: 0.75rem; font-weight: 700; }
.stat-note { font-size: 0.75rem; color: var(--muted); }

/* the Stats window's Collection: icon | name | bar | n/total */
.stat-rows { display: flex; flex-direction: column; gap: 8px; }
.stat-row { display: grid; grid-template-columns: 22px minmax(0, 9.5em) 1fr auto; align-items: center; gap: 8px; font-size: 0.75rem; }
.stat-row-icon { display: grid; place-items: center; }
.stat-row b { color: var(--gold); white-space: nowrap; }
.stat-bar { height: 10px; border: 2px solid #303038; border-radius: 3px; background: #f0f0e8; overflow: hidden; }
.stat-bar i { display: block; height: 100%; background: #48c848; box-shadow: inset 0 2px 0 #98f080; }

.champions { display: flex; flex-wrap: wrap; gap: 8px; }
.champion {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 4px 8px 6px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.06);
  font-weight: 800;
  font-size: 0.8rem;
}
.champion img { width: 48px; height: 48px; object-fit: contain; }

.ach-bar { flex: 1; height: 10px; border-radius: 999px; background: rgba(0, 0, 0, 0.4); overflow: hidden; }
.ach-fill { height: 100%; border-radius: inherit; background: linear-gradient(90deg, #ffcb05, #ff9a2e); }

@media (max-width: 420px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---------- soft corners for the pixel windows that don't set their own (sizes in :root) ---------- */
.nameplate, .battle-log, .biome-sign, .map, .map-terrain { border-radius: var(--round); }
.intent, .focus-hint, .bag-head, .bag-pocket b { border-radius: var(--round-sm); }
.map-town { border-radius: var(--round-xs); }

/* ---------- Poké Mart (map room) and Pokédollars ---------- */
.map-node.type-shop .map-town { border-color: #3878f0; }
.map-node.type-event .map-town { border-color: #b058d8; }
.money-pill { color: #f8f8f8; }
/* The Poké Mart, Zelda-shop style (the user's sketch), the same on every screen: Kecleon at the left end of a
   glass counter, and behind the counter one shelf unit: the moves (small cards, tap one to see it full size)
   on the top shelf, the items on the next, the relics on the bottom. Forgetting a move is the PC on the
   counter. The room around it is the scene's PLACE_ART.mart, barely dimmed. */
body[data-screen="reward-screen"]:has(.mart-window) #backdrop::after { background: rgba(10, 12, 32, 0.12); }
.reward-options.mart-window {
  flex: none;                /* the screen is a flex column: without this the shop gets squeezed shut */
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "cards" "items" "relics" "counter";
  width: min(100%, 620px);
  gap: 0;
  padding: 0;
}
/* the shelf unit: a grey metal cabinet, narrower than the counter in front of it, drawn in hard-edged pixel bands
   for depth: a lit left post and a shaded right one, the inner side walls and the shadow under each board going
   back into the cabinet, and each board showing its pale top surface above its white front edge */
.mart-window :is(.group-cards, .group-items, .group-relics) {
  --board: linear-gradient(to top, #6a6a80 0 3px, #ffffff 3px 7px, #e8e8f0 7px 11px, #c4c4d4 11px 13px, transparent 13px);
  --walls: linear-gradient(to right, #a8a8b8 0 6px, #bcbccc 6px 10px, transparent 10px calc(100% - 10px), #bcbccc calc(100% - 10px) calc(100% - 6px), #a8a8b8 calc(100% - 6px));
  --light: linear-gradient(transparent 0 4px, #fff8d0 4px 6px, rgba(255, 240, 170, 0.45) 6px 12px, rgba(255, 240, 170, 0.2) 12px 20px, transparent 20px);   /* a strip light under the shelf above */
  position: relative;
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: flex-end;
  gap: 8px;
  margin: 0 12px;
  padding: 18px 16px 20px;
  border-left: 6px solid #d8d8e4;
  border-right: 6px solid #9898a8;
  background: var(--board), var(--light), var(--walls), linear-gradient(#8e8ea0 0 4px, #aeaebe 4px 8px, #cdcddb 8px);
  box-shadow: -2px 0 0 #303038, 2px 0 0 #303038;
}
.mart-window .group-cards {
  grid-area: cards;
  margin-top: 38px;
  padding-top: 16px;
  border-top: 6px solid #e0e0ea;
  background: var(--board), var(--light), var(--walls), linear-gradient(#9e9eb0 0 4px, #b6b6c6 4px 8px, #cdcddb 8px);
  box-shadow: -2px 0 0 #303038, 2px 0 0 #303038, 0 -2px 0 #303038;
}
/* the cabinet's crown: a Mart-blue sign board with a Poké Ball on it */
.mart-window .group-cards::before {
  content: "";
  position: absolute;
  left: -14px;
  right: -14px;
  top: -34px;
  height: 26px;
  border-radius: var(--round-sm) var(--round-sm) 0 0;
  background: linear-gradient(#78a8f8 0 3px, #3878f0 3px 19px, #1848a0 19px);
  box-shadow: 0 0 0 2px #303038, 0 3px 0 2px rgba(0, 0, 0, 0.25);
}
.mart-window .group-cards::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -31px;
  width: 20px;
  height: 20px;
  translate: -50% 0;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0 3px, #303038 3px 5px, transparent 5px), linear-gradient(#e04030 0 8px, #303038 8px 12px, #f8f8f8 12px);
  box-shadow: 0 0 0 2px #303038;
}
.mart-window :is(.group-items, .group-relics) { padding-top: 48px; }
.mart-window .group-items { grid-area: items; gap: 18px; }
/* the relics sit in the gaps between the items (a 3-2 pyramid), over a tall band where Kecleon's head and the PC's sign go */
.mart-window .group-relics { grid-area: relics; gap: 18px; padding-bottom: 68px; }
.mart-window .group-cards .reward-option { width: calc((100% - 32px) / 5); max-width: 90px; flex: none; }
.mart-window :is(.group-items, .group-relics) .reward-option { width: 60px; flex: none; }
/* items and relics are bare icons on the shelf (the name and text show when you tap one), bobbing one after another */
.mart-window :is(.group-items, .group-relics) .relic { min-height: 0; padding: 0; border: 0; background: none; box-shadow: none; }
.mart-window :is(.group-items, .group-relics) :is(.relic-name, .relic-text, .relic-terms) { display: none; }
.mart-window :is(.group-items, .group-relics) .relic-icon { font-size: 2.4rem; filter: drop-shadow(2px 3px 0 rgba(0, 0, 0, 0.25)); animation: wareBob 2.4s ease-in-out infinite; }
.mart-window :is(.group-items, .group-relics) .reward-option:nth-child(2) .relic-icon { animation-delay: -0.8s; }
.mart-window :is(.group-items, .group-relics) .reward-option:nth-child(3) .relic-icon { animation-delay: -1.6s; }
.mart-window .group-relics .relic-icon { animation-delay: -0.4s; }
@keyframes wareBob { 50% { translate: 0 -3px; } }
/* a pixel shine sweeping across each card now and then, one card after another */
.mart-window .group-cards .card-face { overflow: hidden; }
.mart-window .group-cards .card-face::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, 0.75) 38% 46%, transparent 46% 52%, rgba(255, 255, 255, 0.5) 52% 55%, transparent 55%);
  translate: -110% 0;
  animation: wareShine 6s ease-in-out infinite;
  pointer-events: none;
}
.mart-window .group-cards .reward-option:nth-child(2) .card-face::after { animation-delay: 0.6s; }
.mart-window .group-cards .reward-option:nth-child(3) .card-face::after { animation-delay: 1.2s; }
.mart-window .group-cards .reward-option:nth-child(4) .card-face::after { animation-delay: 1.8s; }
.mart-window .group-cards .reward-option:nth-child(5) .card-face::after { animation-delay: 2.4s; }
@keyframes wareShine { 0%, 80% { translate: -110% 0; } 100% { translate: 110% 0; } }
@media (prefers-reduced-motion: reduce) {
  .mart-window .relic-icon, .mart-window .card-face::after { animation: none; }
}
/* prices are just printed on the shelf edge: no tag */
.mart-window .mart-ware { gap: 4px; }
.mart-window .mart-price { padding: 0; border: 0; background: none; box-shadow: none; font-size: 0.75rem; white-space: nowrap; color: #283060; text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7); }
.mart-window .mart-price.too-dear { color: #c02020; }
.mart-window .reward-option:is(:disabled, .locked) { opacity: 0.55; }
/* the glass counter, like the Gen 3 Marts', in front of the shelf's foot and hiding Kecleon's */
.reward-options.mart-window::after {
  content: "";
  grid-area: counter;
  z-index: 2;
  height: 58px;
  border-radius: var(--round-sm) var(--round-sm) 0 0;
  background: linear-gradient(#e8fcfc 0 6px, #58c0c8 6px 9px, #a8e4e8 9px 70%, #88d0d8 70%);
  box-shadow: 0 0 0 2px #303038, 0 8px 10px rgba(0, 0, 0, 0.35);
}
.mart-window .group-service { grid-area: counter; z-index: 3; justify-self: end; align-self: start; margin: -46px 12px 0 0; }
.mart-window .group-service .reward-option { position: relative; }
.mart-window .group-service .reward-option:is(:hover, :focus-visible) { transform: none; filter: brightness(1.1); }
.mart-pc { display: block; }
.mart-pc-icon { display: block; font-size: 2.8rem; line-height: 1; filter: drop-shadow(2px 2px 0 rgba(0, 0, 0, 0.3)); }
.mart-pc .center-label { border-color: #3878f0; bottom: calc(100% + 6px); font-size: 0.75rem; padding: 5px 8px; }
/* Leave sits on the floor just above the text box */
#reward-screen:has(.mart-window) .reward-actions { margin-top: auto; }
#reward-screen:has(.mart-window) .reward-bottom { margin-top: 0; }
.mart-window .reward-option:disabled .center-label { animation: none; color: #5a6a50; border-color: #909098; }
@media (max-width: 420px) {
  .mart-window :is(.group-cards, .group-items, .group-relics) { margin: 0 6px; padding-inline: 12px; }
  .mart-window :is(.group-items, .group-relics) .reward-option { width: 54px; }
  .mart-window :is(.group-items, .group-relics) .relic-icon { font-size: 2.1rem; }
}
.mart-ware { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.mart-ware > * { width: 100%; }
.mart-price {
  width: auto;
  padding: 3px 8px;
  font-family: var(--pixel-font);
  font-size: 1rem;
  color: #181010;
  background: #f8f0d8;
  border: 2px solid #3878f0;
  border-radius: var(--round-xs);
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.35);
}

/* ---------- the Pokémon Center: no tiles, you tap the healing machine or the PC in the scene ---------- */
/* the scene shows at full strength here, like a battle, so the counter reads as the place you're standing in */
body[data-screen="reward-screen"]:has(:is(.center-room, .event-room)) #backdrop::after { background: none; }
.reward-options:is(.center-room, .event-room) { padding: 0; }
/* the text box sits on the floor just under the counter (--counter-foot, placeCenterSpots()), and Leave at the bottom */
#reward-screen:has(:is(.center-room, .event-room)) .reward-bottom {
  position: fixed;
  top: calc(var(--counter-foot, 70vh) + 12px - var(--log-lift, 0px));
  bottom: auto;
  left: 50%;
  translate: -50% 0;
  width: min(calc(100% - 32px), var(--log-w));
}
#reward-screen:has(:is(.center-room, .event-room)) .reward-actions { margin-top: auto; margin-bottom: calc(max(0px, env(safe-area-inset-bottom)) - 14px); }
/* each choice is a see-through button laid over its machine (placeCenterSpots() in js/run.js) */
:is(.center-room, .event-room) .reward-option {
  position: fixed;
  z-index: 2;
  border-radius: var(--round-sm);
  cursor: pointer;
}
:is(.center-room, .event-room) .reward-option:is(:hover, :focus-visible) { transform: none; background: rgba(255, 255, 255, 0.18); }
:is(.center-room, .event-room) .reward-option:focus-visible { outline: 3px solid #f8d030; outline-offset: 2px; }
:is(.center-room, .event-room) .reward-option:is(:disabled, .locked) { opacity: 1; cursor: not-allowed; }
/* the patient monitor (centerVitals()): your Pokémon's HP in green phosphor over the scene's monitor screen, the heal
   Rest would give blinking on the end of the bar, and the bar filling up in real time while you rest */
.center-vitals {
  position: fixed;
  z-index: 1;
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas: "face name name" "bar bar bar" "hp hp plus";
  align-items: center;
  gap: 0.25em 0.4em;
  padding: 0.35em 0.5em;
  background: repeating-linear-gradient(#0e2a1c 0 3px, #12321f 3px 4px);
  color: #58f888;
  font-family: var(--pixel-font); font-synthesis-weight: none;
  line-height: 1;
  text-shadow: 0 0 4px rgba(88, 248, 136, 0.6);
  cursor: help;
}
.vitals-face { grid-area: face; width: 2em; height: 2em; object-fit: contain; image-rendering: pixelated; filter: sepia(1) hue-rotate(70deg) saturate(3) brightness(0.95) drop-shadow(0 0 3px rgba(88, 248, 136, 0.5)); }
.vitals-name { grid-area: name; font-size: 0.8em; overflow: hidden; white-space: nowrap; }
.vitals-bar { grid-area: bar; position: relative; height: 0.8em; border: 1px solid #58f888; background: #0a1e14; overflow: hidden; }
.vitals-fill, .vitals-gain { position: absolute; top: 0; bottom: 0; left: 0; }
.vitals-fill { background: #58f888; box-shadow: 0 0 5px #58f888; }
.vitals-gain { background: #c8ffd8; animation: cursorBlink 1s steps(1) infinite; }
.vitals-hp { grid-area: hp; font-size: 0.85em; white-space: nowrap; }
.vitals-plus { grid-area: plus; font-size: 0.85em; color: #c8ffd8; animation: cursorBlink 1s steps(1) infinite; }
.center-vitals.healing .vitals-gain { animation: none; opacity: 0.5; }
.center-vitals.healing .vitals-hp { color: #c8ffd8; }
@media (prefers-reduced-motion: reduce) { .vitals-gain, .vitals-plus { animation: none; } }
/* Chansey behind the counter: a window whose bottom edge is the counter top (placeCenterSpots()), so its feet are hidden */
.center-nurse {
  position: fixed;
  z-index: 1;
  width: 122px;
  height: 70px;
  translate: -50% -100%;
  overflow: hidden;
  pointer-events: none;
}
.center-nurse img { position: absolute; left: 0; top: 0; width: 122px; image-rendering: pixelated; }
/* the floating sign over each, a small green LCD in a ring of the device's shell (D2, 2026-10-07; a cream Pokégear bubble
   before) with a pixel tail, bobbing to say "tap me"; its border is the choice's colour */
.center-label {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 12px);
  translate: -50% 0;
  padding: 6px 10px;
  border: 2px solid #e05838;
  background: radial-gradient(circle, rgba(31, 58, 20, 0.1) 1px, transparent 1.5px) 0 0 / 8px 8px, #a8c884;
  color: #1f3a14;
  box-shadow: 0 0 0 2px #2a2a30, 0 0 0 5px var(--shell), 0 0 0 7px var(--shell-rim), 2px 4px 0 7px rgba(0, 0, 0, 0.35);
  border-radius: var(--round-sm);
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 0.8rem;
  line-height: 1;
  white-space: nowrap;
  animation: spotBounce 0.9s ease-in-out infinite;
}
:is(.center-room, .event-room) .reward-option + .reward-option .center-label { border-color: #3878f0; animation-delay: -0.45s; }
.center-room .reward-option:nth-child(3) .center-label { border-color: #b058d8; animation-delay: -0.2s; }   /* PP Up, over Chansey */
.center-label::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  width: 10px;
  height: 6px;
  margin-top: 7px;
  transform: translateX(-50%);
  background: var(--shell-rim);
  clip-path: polygon(0 0, 100% 0, 100% 50%, 70% 50%, 70% 100%, 30% 100%, 30% 50%, 0 50%);
}
@keyframes spotBounce { 50% { transform: translateY(-7px); } }
:is(.center-room, .event-room) .reward-option:is(:disabled, .locked) .center-label { animation: none; color: #5a6a50; border-color: #909098; filter: grayscale(1); }
:is(.center-room, .event-room).resting .center-label { visibility: hidden; }
/* the gym has no Battle sign over its leader (the user's call, 2026-10-13): walking up or a tap on them is the challenge */
.gym-room .center-label { visibility: hidden; }
/* an event sign tapped once (spotOption()): it holds still, raised, in a gold ring, while the text box says what it does
   and a second tap takes it */
.event-room .reward-option.picked .center-label {
  animation: none; transform: translateY(-7px);
  box-shadow: 0 0 0 2px #2a2a30, 0 0 0 5px #f8d030, 0 0 0 7px #a07818, 0 0 12px 8px rgba(248, 208, 48, 0.55);
}
/* the ? events with a scene of their own (eventRoom()) work the same way over their props; the well's two tosses are
   its two halves, so their signs lean apart */
.well-room .reward-option:first-child .center-label { translate: -80% 0; }
.well-room .reward-option + .reward-option .center-label { translate: -20% 0; }
/* people and Pokémon standing in an event's scene (eventFigure(), placed by placeEventSpots()); an Alpha glows red
   like an elite in battle. The grunt hops when the coins land (the scene's pay act) and shakes a fist as you run. */
.event-figure {
  position: fixed;
  z-index: 1;
  pointer-events: none;
}
.event-figure img { display: block; width: 100%; image-rendering: pixelated; }
.event-figure.alpha { filter: drop-shadow(0 0 6px #ff3b3b); }
.event-figure.flip { scale: -1 1; }
.event-figure.hop { animation: figureHop 0.5s ease-in-out 1s 2; }
.event-figure.shake { animation: figureShake 0.25s linear 0.25s 4; }
@keyframes figureHop { 50% { translate: 0 -10px; } }
@keyframes figureShake { 25% { translate: -4px 0; } 75% { translate: 4px 0; } }
/* the event trainers (NPCS in js/data/events.js) are stills in three layers (legs, upper body, head) that move a whole
   sprite pixel at a time (--h / --w are the sprite's size, so 100% / var(--h) is one of its pixels): the upper body
   breathes, the head bobs while the text box types and nods or shakes, and an eyes-closed head blinks in */
.npc-upper, .npc-head { position: absolute; inset: 0; }
.npc-upper img, .npc-head img { position: absolute; left: 0; top: 0; }
.npc-shut { visibility: hidden; }
.event-figure.npc-blink .npc-shut { visibility: visible; }
.npc-upper { animation: npcBreathe 2.8s steps(1) var(--phase, 0s) infinite; }
:where(#reward-screen:has(#reward-log.typing)) .event-figure.npc .npc-head { animation: npcDip 0.3s steps(1) infinite; }
.event-figure.npc.npc-nod .npc-head { animation: npcNod 0.8s steps(1) 2; }
.event-figure.npc.npc-no .npc-head { animation: npcNo 0.3s steps(1) 0.2s 3; }
.event-figure.npc-jump { animation: figureHop 0.5s ease-in-out 0.2s 2; }
.event-figure.npc-turn { scale: -1 1; }
.event-figure.flip.npc-turn { scale: 1 1; }
@keyframes npcBreathe { 50% { translate: 0 calc(100% / var(--h, 64)); } }
@keyframes npcDip { 50% { translate: 0 calc(100% / var(--h, 64)); } }
@keyframes npcNod { 20% { translate: 0 calc(100% / var(--h, 64)); } 40% { translate: 0 calc(200% / var(--h, 64)); } 70% { translate: 0 calc(100% / var(--h, 64)); } }
@keyframes npcNo { 25% { translate: calc(-100% / var(--w, 32)) 0; } 75% { translate: calc(100% / var(--w, 32)) 0; } }
@media (prefers-reduced-motion: reduce) { .event-figure, .event-figure * { animation: none !important; } }
@media (prefers-reduced-motion: reduce) { .center-label { animation: none; } }

/* ---------- the treasure grotto (treasureRoom() in js/run.js): a Poké Ball chest on the scene's dais, sized in the
   scene's own pixels (--px), and the relics floating out of it with no tiles round them ---------- */
body[data-screen="reward-screen"]:has(.treasure-room) #backdrop::after { background: none; }
.reward-options.treasure-room { padding: 0; }
#reward-screen:has(.treasure-room) :is(.reward-title, .reward-actions) { position: relative; z-index: 2; }
/* the floating-thing screens (the grotto, a found item): the text box sits with the thing you tap and Skip / Leave goes
   to the very bottom, out of the way (the user's call: nothing should pull you off the item) */
#reward-screen:has(:is(.treasure-room, .item-found)) .reward-actions { order: 2; margin-top: auto; margin-bottom: calc(max(0px, env(safe-area-inset-bottom)) - 14px); }
#reward-screen:has(:is(.treasure-room, .item-found)) .reward-bottom { order: 1; margin-top: 0; }
#reward-screen:has(.item-found) .reward-bottom { position: static; }
#reward-screen:has(.treasure-room) .reward-bottom { margin-top: auto; }   /* the chest fills the middle: the box waits just above Leave */
#reward-screen:has(.treasure-room) .reward-actions { margin-top: 0; }
.treasure-stage { position: fixed; inset: 0; z-index: 1; pointer-events: none; }
.treasure-stage > button { pointer-events: auto; }
.treasure-chest {
  position: fixed;
  translate: 0 -100%;
  width: calc(var(--px) * 36);
  height: calc(var(--px) * 28);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transform-origin: 50% 100%;
  animation: chestHop 2.6s ease-in-out infinite;
}
.treasure-chest:focus-visible { outline: 3px solid #f8d030; outline-offset: 4px; }
.chest-part { position: absolute; left: 0; width: calc(var(--px) * var(--w)); height: calc(var(--px) * var(--h)); image-rendering: pixelated; pointer-events: none; }
.chest-body { bottom: 0; }
.chest-lid { bottom: calc(var(--px) * 15); }
.chest-open { bottom: calc(var(--px) * 14); visibility: hidden; }
.treasure-chest .center-label { bottom: calc(100% + 14px); }
/* now and then it hops, like an item ball waiting on the ground */
@keyframes chestHop { 0%, 78%, 100% { transform: none; } 84% { transform: translateY(-6px); } 90% { transform: none; } 94% { transform: translateY(-2px); } }
/* tapped, it wobbles three times like a Poké Ball before it pops open */
.treasure-chest.shaking { animation: chestWobble 1.1s ease-in-out; }
.treasure-chest.shaking .center-label, .treasure-chest.opened .center-label { visibility: hidden; }
@keyframes chestWobble {
  0%, 24%, 36%, 60%, 72%, 100% { transform: none; }
  8% { transform: rotate(-9deg); } 16% { transform: rotate(8deg); }
  44% { transform: rotate(-7deg); } 52% { transform: rotate(6deg); }
  80% { transform: rotate(-5deg); } 88% { transform: translateY(-4px) scale(1.04, 0.96); }
}
.treasure-chest.opened { animation: chestPop 0.4s ease-out; cursor: default; }
.treasure-chest.opened .chest-lid { visibility: hidden; }
.treasure-chest.opened .chest-open { visibility: visible; }
@keyframes chestPop { 30% { transform: scale(1.08, 0.9); } 60% { transform: scale(0.96, 1.06) translateY(-4px); } }
/* the light pouring out of the open chest, and the rays turning behind it */
.chest-glow {
  position: absolute;
  left: 50%;
  bottom: calc(var(--px) * 18);
  width: calc(var(--px) * 48);
  height: calc(var(--px) * 40);
  translate: -50% 0;
  background: radial-gradient(ellipse 50% 60% at 50% 100%, rgba(255, 248, 200, 0.9), rgba(255, 216, 100, 0.4) 45%, transparent 75%);
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: screen;
}
.chest-rays {
  position: absolute;
  left: 50%;
  bottom: calc(var(--px) * 18);
  width: min(160vmin, 900px);
  aspect-ratio: 1;
  translate: -50% 50%;
  height: auto;
  opacity: 0;
  pointer-events: none;
}
.treasure-chest.opened .chest-glow { animation: glowIn 0.5s ease-out forwards, glowPulse 2s ease-in-out 0.5s infinite; }
.treasure-chest.opened .chest-rays { animation: raysIn 0.7s ease-out forwards, raysTurn 40s linear infinite; }
@keyframes glowIn { from { opacity: 0; scale: 0.3; } to { opacity: 1; } }
@keyframes glowPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } }
@keyframes raysIn { from { opacity: 0; scale: 0.2; } to { opacity: 1; } }
@keyframes raysTurn { to { rotate: 1turn; } }
.treasure-flash { position: fixed; inset: 0; background: #fff; pointer-events: none; animation: flashOut 0.5s ease-out forwards; }
@keyframes flashOut { from { opacity: 0.85; } to { opacity: 0; visibility: hidden; } }
/* a relic: just its sprite, bobbing in the light over a soft glow, arcing up out of the chest when it opens */
.treasure-relic {
  position: fixed;
  translate: -50% -50%;
  width: var(--size);
  height: var(--size);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transition: opacity 0.3s, filter 0.3s;
  animation: relicRise 0.9s cubic-bezier(0.25, 0.8, 0.35, 1) calc(0.1s + var(--i) * 0.18s) backwards;
}
@keyframes relicRise {
  0% { transform: translate(var(--from-x), var(--from-y)) scale(0.15); opacity: 0; }
  20% { opacity: 1; }
  55% { transform: translate(calc(var(--from-x) * 0.3), calc(var(--from-y) * 0.3 - 40px)) scale(1.15); }
  100% { transform: none; }
}
.relic-float { position: absolute; inset: 0; animation: relicBob 2.4s ease-in-out calc(var(--i) * -0.8s) infinite; transition: scale 0.25s; }
@keyframes relicBob { 50% { transform: translateY(-8px); } }
.treasure-sprite .item-sprite { width: 100%; height: 100%; filter: drop-shadow(0 0 6px rgba(255, 244, 180, 0.8)) drop-shadow(2px 2px 0 rgba(0, 0, 0, 0.35)); }
/* two pixel sparkles twinkling round it */
.relic-float::before, .relic-float::after {
  content: "";
  position: absolute;
  width: 10px;
  height: 10px;
  background: #fffbe0;
  clip-path: polygon(40% 0, 60% 0, 60% 40%, 100% 40%, 100% 60%, 60% 60%, 60% 100%, 40% 100%, 40% 60%, 0 60%, 0 40%, 40% 40%);
  animation: sparkle 1.6s ease-in-out calc(var(--i) * -0.5s) infinite;
}
.relic-float::before { left: 4%; top: 10%; }
.relic-float::after { right: 2%; bottom: 20%; animation-delay: calc(var(--i) * -0.5s - 0.8s); }
@keyframes sparkle { 0%, 60%, 100% { scale: 0; } 20% { scale: 1; } 40% { scale: 0.5; } }
.relic-halo {
  position: absolute;
  left: 10%;
  right: 10%;
  bottom: -14px;
  height: 16px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 240, 170, 0.55), transparent);
  animation: haloPulse 2.4s ease-in-out calc(var(--i) * -0.8s) infinite;
}
@keyframes haloPulse { 50% { scale: 0.75; opacity: 0.6; } }
.relic-label {
  position: absolute;
  left: 50%;
  top: calc(100% + 10px);
  translate: -50% 0;
  color: #fff;
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 0.75rem;
  white-space: nowrap;
  text-shadow: 2px 2px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000;
  visibility: hidden;
}
.treasure-relic.chosen .relic-label { visibility: visible; }
.treasure-relic.chosen .relic-float { scale: 1.3; }
.treasure-relic:is(:hover, :focus-visible) .relic-float { scale: 1.15; }
.treasure-relic.chosen:is(:hover, :focus-visible) .relic-float { scale: 1.3; }
.treasure-relic:focus-visible { outline: none; }
.treasure-relic:focus-visible .relic-halo { background: radial-gradient(closest-side, rgba(248, 208, 48, 0.9), transparent); }
.treasure-stage.choosing .treasure-relic:not(.chosen) { opacity: 0.55; filter: grayscale(0.6); }
/* taken: it shrinks away into the Bag, and the others sink back into the light */
.treasure-relic.taken { animation: relicToBag 0.7s ease-in forwards; }
@keyframes relicToBag { 20% { transform: scale(1.3); } to { transform: translate(var(--to-x), var(--to-y)) scale(0.2); opacity: 0.2; } }
.treasure-stage.taking .treasure-relic:not(.taken) { opacity: 0; }
/* a found item (offerItem) or an event's gift (revealGift): floating like a treasure relic, its name always under it */
.reward-options.item-found { display: block; }
.float-stage { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 24px 0 4px; }
.float-row { display: flex; justify-content: center; gap: 34px; }
.float-thing {
  position: relative;
  width: var(--size);
  height: var(--size);
  margin-bottom: 34px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transition: opacity 0.3s, filter 0.3s;
}
.float-label {
  position: absolute;
  left: 50%;
  top: calc(100% + 12px);
  translate: -50% 0;
  color: #fff;
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 0.75rem;
  white-space: nowrap;
  text-shadow: 2px 2px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000;
}
.float-caption { margin: 0; color: #fff; font-family: var(--pixel-font); font-size: 0.75rem; text-shadow: 2px 2px 0 #000; opacity: 0.85; }
.float-thing:is(:hover, :focus-visible) .relic-float { scale: 1.12; }
.float-thing.chosen .relic-float { scale: 1.25; }
.float-thing:focus-visible { outline: none; }
.float-thing:focus-visible .relic-halo { background: radial-gradient(closest-side, rgba(248, 208, 48, 0.9), transparent); }
/* the Bag item you'd toss: greyed, with a red pixel ✕ over it */
.float-thing.tossing .relic-float { filter: grayscale(0.7) brightness(0.8); }
.float-thing.tossing::after {
  content: "";
  position: absolute;
  inset: 18%;
  background: #e03030;
  clip-path: polygon(0 12%, 12% 0, 50% 38%, 88% 0, 100% 12%, 62% 50%, 100% 88%, 88% 100%, 50% 62%, 12% 100%, 0 88%, 38% 50%);
  filter: drop-shadow(2px 2px 0 #000);
}
.float-thing.tossing .float-label { color: #ffb0a8; }
.float-thing.gone { opacity: 0; }
.float-thing.taken { animation: relicToBag 0.7s ease-in forwards; }
/* a Satchel thing has no sprite, only its icon, glowing like one */
.satchel-glyph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: calc(var(--size, 56px) * 0.72);
  line-height: 1;
  filter: drop-shadow(0 0 6px rgba(255, 244, 180, 0.8)) drop-shadow(2px 2px 0 rgba(0, 0, 0, 0.35));
}
/* a material or key item found on a run (js/satchel-pop.js): a small device window, half an achievement's, with what
   was found big on its stage, then it flies into the Bag; it never takes a tap */
.satchel-pop {
  position: fixed;
  left: 50%;
  top: 18%;
  translate: -50% 0;
  z-index: 950;
  width: min(200px, calc(100vw - 32px));
  padding: 8px 8px 10px;
  border-radius: 18px;
  color: #1f3a14;
  text-align: center;
  background: linear-gradient(180deg, var(--shell-hi), var(--shell) 40%, var(--shell-lo));
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset 6px 0 0 rgba(255, 255, 255, 0.08), 0 16px 48px rgba(0, 0, 0, 0.6);
  pointer-events: none;
  animation: unlockIn 0.45s ease-out both;
}
.satchel-pop.many { width: min(280px, calc(100vw - 32px)); }
.satchel-pop-note {
  margin: 0 0 8px;
  padding: 6px 8px 5px;
  background: repeating-linear-gradient(90deg, #f0b828 0 12px, #f8c848 12px 24px);
  border: 3px solid var(--shell-rim);
  border-radius: var(--round-sm);
  color: #3a2408;
  font-family: var(--pixel-font); font-synthesis-weight: none;
  font-size: 0.75rem;
  white-space: nowrap;
  animation: unlockFlash 0.9s steps(2) 2;
}
.satchel-stage {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 14px;
  height: 104px;
  margin: 0 4px;
  border: 4px solid #2a2a30;
  border-radius: 10px;
  box-shadow: 0 0 0 3px var(--shell-rim), inset 0 0 0 2px rgba(255, 255, 255, 0.35);
  background:
    radial-gradient(circle at 50% 50%, #fff6d0 0 30%, transparent 31%),
    radial-gradient(circle, rgba(255, 255, 255, 0.22) 1px, transparent 1.5px) 0 0 / 10px 10px,
    linear-gradient(150deg, #5cbcff, #1d58b8);
}
.satchel-find { --size: 72px; position: relative; flex: none; width: var(--size); height: var(--size); animation: itemRise 0.6s cubic-bezier(0.25, 0.8, 0.35, 1) calc(var(--i) * 0.12s) backwards; }
.satchel-pop.many .satchel-find { --size: 56px; }
.satchel-names {
  margin: 10px 4px 4px;
  padding: 6px 8px;
  border: 3px solid #2a2a30; border-radius: 6px 6px 6px 14px;
  background: radial-gradient(circle, rgba(31, 58, 20, 0.1) 1px, transparent 1.5px) 0 0 / 8px 8px, #a8c884;
  box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), 0 0 0 4px #e4e4ea, 0 0 0 6px var(--shell-rim);
}
.satchel-name { margin: 0; font-family: var(--pixel-font); font-synthesis-weight: none; font-size: 0.8rem; line-height: 1.6; }
.satchel-pop.taken { transition: opacity 0.3s 0.4s; opacity: 0; }
.satchel-pop.taken .satchel-find { animation: relicToBag 0.7s ease-in forwards; }
@media (prefers-reduced-motion: reduce) {
  .satchel-pop, .satchel-pop-note, .satchel-find, .satchel-pop.taken .satchel-find { animation: none; }
  .satchel-pop.taken { transition: opacity 0.2s; }
}
/* an event's gift floats in the middle of the scene, over the props */
.float-gift { position: fixed; left: 50%; top: 42%; translate: -50% -50%; z-index: 3; padding: 0; }
/* before the item shows, it lies in a Poké Ball in the middle (offerItem): tapped, it hops and wobbles like the treasure
   chest, its top pops off in a flash with the chest's rays, and the item rises out where the ball was */
.reward-options.item-found { overflow-x: clip; }
.item-found > .float-stage { padding-top: max(24px, 12vh); }
.ball-spot { position: relative; display: grid; place-items: center; }
.ball-spot > * { grid-area: 1 / 1; }
.item-ball {
  --px: 5px;
  position: relative;
  align-self: start;
  width: calc(var(--px) * 22);
  height: calc(var(--px) * 22);
  margin-top: -8px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transform-origin: 50% 100%;
  animation: chestHop 2.6s ease-in-out infinite;
}
.item-ball:focus-visible { outline: 3px solid #f8d030; outline-offset: 4px; border-radius: 50%; }
.ball-half { position: absolute; left: 0; width: 100%; height: 50%; image-rendering: pixelated; pointer-events: none; filter: drop-shadow(3px 3px 0 rgba(0, 0, 0, 0.35)); }
.ball-top { top: 0; transform-origin: 20% 100%; }
.ball-bottom { bottom: 0; }
.item-ball .chest-glow { bottom: 40%; width: 140%; height: 120%; }
.item-ball.shaking { animation: chestWobble 1.1s ease-in-out; }
.item-ball.opened { animation: ballGone 0.45s ease-in 0.35s forwards; cursor: default; pointer-events: none; }
.item-ball.opened .ball-top { animation: ballTopPop 0.45s ease-out forwards; }
.item-ball.opened .chest-glow { animation: glowIn 0.3s ease-out forwards; }
@keyframes ballTopPop { to { transform: translate(-6px, -60%) rotate(-40deg); opacity: 0; } }
@keyframes ballGone { to { transform: scale(0.4); opacity: 0; visibility: hidden; } }
.ball-spot > .chest-rays { position: absolute; left: 50%; top: calc(var(--size, 96px) / 2); bottom: auto; width: min(120vmin, 560px); translate: -50% -50%; }
.float-stage.open .ball-spot > .chest-rays { animation: raysIn 0.7s ease-out forwards, raysTurn 40s linear infinite; }
.float-stage.sealed .ball-spot > .float-thing, .float-stage.sealed > :not(.ball-spot) { visibility: hidden; }
.float-stage.open .ball-spot > .float-thing:not(.taken) { animation: itemRise 0.8s cubic-bezier(0.25, 0.8, 0.35, 1) 0.2s backwards; }
@keyframes itemRise { 0% { transform: translateY(30px) scale(0.15); opacity: 0; } 25% { opacity: 1; } 60% { transform: translateY(-16px) scale(1.15); } 100% { transform: none; } }
.float-stage.open > :is(.float-caption, .float-row, .swap-found) { animation: bagRowIn 0.4s ease-out 0.7s backwards; }
@keyframes bagRowIn { from { opacity: 0; } }
@media (max-width: 720px) { .item-ball { --px: 4px; } }
/* a relic reward (showRelics): the relics burst out in a flash one after another and float in a row in the rays; the
   ones you didn't pick dim, and a boss's are gold */
.relic-stage { padding-top: max(24px, 14vh); }
.relic-stage .float-row { gap: clamp(16px, 5vw, 48px); }
.relic-stage .float-row.tiers { flex-direction: column; align-items: center; gap: 0; }
.float-tier { display: flex; justify-content: center; gap: clamp(44px, 14vw, 96px); }
.relic-stage:has(.float-tier + .float-tier) { padding-top: max(12px, 6vh); }
.relic-stage .ball-spot > .chest-rays { top: calc(var(--size, 72px) / 2 + 12px); animation: raysIn 0.7s ease-out forwards, raysTurn 40s linear infinite; }
.relic-stage .float-thing { margin-bottom: 52px; animation: relicPop 0.8s cubic-bezier(0.25, 0.8, 0.35, 1) calc(0.15s + var(--i) * 0.15s) backwards; }
.relic-stage .float-label { width: calc(var(--size) + 36px); white-space: normal; text-align: center; line-height: 1.5; font-size: 0.75rem; }
@keyframes relicPop { 0% { transform: translateY(40px) scale(0.15); opacity: 0; } 25% { opacity: 1; } 60% { transform: translateY(-14px) scale(1.15); } 100% { transform: none; } }
.relic-stage .float-thing.taken { animation: relicToBag 0.7s ease-in forwards; }
.relic-stage.choosing .float-thing:not(.chosen) { opacity: 0.55; filter: grayscale(0.6); }
.relic-stage.taking .float-thing:not(.taken) { opacity: 0; }
.relic-stage.boss .relic-halo { background: radial-gradient(closest-side, rgba(248, 192, 40, 0.85), transparent); }
.relic-stage.boss .treasure-sprite .item-sprite { filter: drop-shadow(0 0 8px rgba(248, 192, 40, 0.95)) drop-shadow(2px 2px 0 rgba(0, 0, 0, 0.35)); }
.relic-stage.boss .float-label { color: #f8d860; }
@media (prefers-reduced-motion: reduce) {
  .treasure-chest, .treasure-chest.opened, .treasure-relic, .float-thing.taken, .item-ball, .item-ball.opened .ball-top, .float-stage.open :is(.float-thing, .float-caption, .float-row, .swap-found), .relic-stage .float-thing, .relic-float, .relic-float::before, .relic-float::after, .relic-halo, .treasure-flash { animation: none; }
  .treasure-chest.opened :is(.chest-glow, .chest-rays), .float-stage.open .ball-spot > .chest-rays, .relic-stage .ball-spot > .chest-rays { animation: none; opacity: 1; }
  .item-ball.opened { display: none; }
  .treasure-flash { display: none; }
}

/* ---------- items: the Bag's one-use items, used from its Items pocket and confirmed like a card ---------- */
.relic.focus-item { width: min(70vw, 240px); min-height: 0; cursor: pointer; animation: focusIn 0.18s ease-out; }
.relic.focus-item.unplayable { filter: grayscale(0.6) brightness(0.8); }
.relic.item-tile { border-color: #3878f0; }
.item-full { font-family: var(--pixel-font); font-size: 0.75rem; color: #c02020; }
.item-row .howto-li-text { flex: 1; }
.item-actions { display: flex; flex-direction: column; gap: 4px; flex: none; }
.bag .item-actions .btn { padding: 4px 8px 4px 16px; font-size: 0.75rem; min-height: 0; }

/* ---------- the pixel scene behind every screen (js/scene.js), dimmed by #backdrop outside battles ---------- */
#scene-bg { position: fixed; inset: 0; z-index: -2; width: 100%; height: 100%; image-rendering: pixelated; display: none; }
body.has-scene #scene-bg { display: block; }
/* the grassy pads the Pokémon stand on, like the Gen 3/4 games; behind the sprites, and they don't lunge with them */
.has-scene .enemy-zone::after,
.has-scene .player-zone::before {
  content: "";
  position: absolute;
  left: 50%;
  z-index: -1;
  aspect-ratio: 48 / 16;
  translate: -50% 0;
  background: var(--pad) center / 100% 100% no-repeat;
  image-rendering: pixelated;
  pointer-events: none;
}
.has-scene .enemy-zone::after { width: calc(var(--base) * 1.5); bottom: calc(var(--base) * -0.2); }   /* the feet land just below the pad's middle; horizonRow() assumes this */
.has-scene .player-zone::before { width: clamp(130px, 25vh, 290px); bottom: -4%; }
/* the smooth Clearing (?smooth, js/smooth-clearing.js) is painted at the screen's resolution, its pads too */
body.smooth-scene #scene-bg,
body.smooth-scene .enemy-zone::after,
body.smooth-scene .player-zone::before { image-rendering: auto; }
/* the hybrid look (?hybrid, js/hybrid-light.js): the pixel scene, with smooth light screened over it */
#scene-light { position: fixed; inset: 0; z-index: -2; width: 100%; height: 100%; pointer-events: none; display: none; mix-blend-mode: screen; }
body.has-scene.hybrid-scene #scene-light { display: block; }

/* ---------- POKÉDEX (js/pokedex.js): a page per biome, entries ??? until fought ---------- */
.ds-btn.ds-dex { --stripe-a: #e05858; --stripe-b: #f07878; --rim: #a83030; }
#reward-reroll .pp-pill { gap: 8px; align-items: center; }
.dex-body { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 12px; }
.dex-perk {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 12px;
  padding: 10px 12px;
  border: 3px dashed var(--win-edge);
  border-radius: var(--round);
  background: var(--win-panel);
  color: var(--win-ink);
}
.dex-perk.earned { border-style: solid; border-color: #c89a18; background: #fbf0c8; }
.dex-perk.mastered { border-color: #e0a800; box-shadow: inset 0 0 0 2px #ffe27a; }
.dex-perk-icon { font-size: 2rem; line-height: 1; flex: none; }
.dex-perk:not(.earned) .dex-perk-icon { filter: grayscale(1) opacity(0.6); }
.dex-perk-text { flex: 1; display: flex; flex-direction: column; gap: 3px; font-size: 0.85rem; min-width: 0; }
.dex-perk-text strong { font-family: var(--pixel-font); font-synthesis-weight: none; font-weight: 400; font-size: 0.8rem; }
.dex-perk-text small { color: var(--win-muted); }
.dex-bar { flex: none; height: 8px; margin-top: 4px; background: rgba(0, 0, 0, 0.18); }
.dex-perk-count { font-family: var(--pixel-font); font-synthesis-weight: none; font-weight: 400; font-size: 0.9rem; }
/* the Rewards tab: the complete-Pokédex jackpot lists its three prizes as rows */
.dex-goal { align-items: flex-start; }
.dex-goal-how { color: var(--win-muted); font-size: 0.8rem; }
.dex-prize { display: flex; align-items: center; gap: 8px; }
.dex-prize-text { font-size: 0.85rem; }
.dex-prize-icon, .dex-prize-sprite { flex: none; width: 32px; height: 32px; display: grid; place-items: center; font-size: 1.3rem; object-fit: contain; }
.dex-prize-icon .item-sprite { width: 28px; height: 28px; image-rendering: pixelated; }
.dex-prize-icon > .smooth-icon { width: 26px; height: 26px; }
.dex-perk-icon > .smooth-icon { width: 1.1em; height: 1.1em; }
.dex-jackpot:not(.earned) .dex-prize-sprite { filter: brightness(0) opacity(0.45); }
.dex-entry {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 6px 10px;
  border: 3px solid #b8b8c8;
  border-radius: var(--round-sm);
  background: var(--win-bg);
  box-shadow: 0 0 0 2px #303038, 3px 3px 0 1px rgba(0, 0, 0, 0.3);
  color: var(--win-ink);
  font: inherit;
  cursor: pointer;
}
.dex-entry:disabled, .dex-entry[aria-disabled="true"] { cursor: default; }
.dex-entry:not(:disabled):not([aria-disabled="true"]):hover { background: var(--win-tile); }
.dex-entry:focus-visible { outline: 3px solid #f8d030; outline-offset: 2px; }
.dex-no { font-family: var(--pixel-font); font-synthesis-weight: none; font-size: 0.8rem; color: var(--win-ink); align-self: flex-start; }   /* the user found 0.6rem too small to read */
.dex-sprite { width: 72px; height: 72px; object-fit: contain; image-rendering: pixelated; }
.dex-entry.locked .dex-sprite { filter: brightness(0) opacity(0.55); }   /* a silhouette until you've fought it */
.dex-name { font-family: var(--pixel-font); font-synthesis-weight: none; font-weight: 400; font-size: 0.75rem; line-height: 1.3; text-align: center; }
.dex-entry.locked .dex-name { color: var(--win-muted); }
.dex-mark.pokeball { position: absolute; top: 5px; right: 6px; margin: 0; font-size: 1.1rem; animation: none; }   /* beaten: the games' caught mark */
.dex-mark.pokeball.gold { background: linear-gradient(180deg, #f8d030 0 44%, #1b1f3a 44% 56%, #fff4c0 56%); border-color: #a07010; box-shadow: 0 0 6px 1px rgba(248, 208, 48, 0.8); }   /* Research complete */
.dex-entry.researched { border-color: #d8a820; background: #fbf3d0; }
.dex-research { font-family: var(--pixel-font); font-synthesis-weight: none; font-size: 0.8rem; color: var(--win-ink); }
.dex-entry.researched .dex-research { color: #8a6000; }
.dex-detail-research { margin: 4px 0; font-size: 0.82rem; font-weight: 700; color: var(--win-muted); }
.dex-detail-research.done { color: #8a6000; font-family: var(--pixel-font); font-synthesis-weight: none; font-weight: 400; font-size: 0.75rem; }
.dex-detail-hp { margin: 4px 0; font-size: 0.82rem; font-weight: 700; }
.dex-zoom { cursor: pointer; }
.dex-detail {
  width: min(92vw, 380px);
  max-height: 78vh;
  overflow-y: auto;
  padding: 16px;
  border: 3px solid #b8b8c8;
  border-radius: var(--round);
  background: var(--win-bg);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 4px 4px 0 2px rgba(0, 0, 0, 0.45);
  color: var(--win-ink);
  animation: focusIn 0.18s ease-out;
}
.dex-detail-head { display: flex; align-items: center; gap: 14px; }
.dex-detail-sprite { width: 112px; height: 112px; object-fit: contain; image-rendering: pixelated; flex: none; background: radial-gradient(closest-side, rgba(0, 0, 0, 0.12), transparent); }
/* an opened entry hops as its cry plays, then idles with a small bounce; object-position moves the Pokémon, not its shadow */
.dex-zoom .dex-detail-sprite { animation: dexHop 0.42s ease-in-out both, dexIdle 1.2s ease-in-out 0.5s infinite; }
@keyframes dexHop { 0%, 100% { object-position: 50% 50%; } 50% { object-position: 50% calc(50% - 10px); } }
@keyframes dexIdle { 0%, 100% { object-position: 50% 50%; } 50% { object-position: 50% calc(50% - 3px); } }
@media (prefers-reduced-motion: reduce) { .dex-zoom .dex-detail-sprite { animation: none; } }
.dex-detail-names { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.dex-detail-name { font-family: var(--pixel-font); font-synthesis-weight: none; font-weight: 400; font-size: 1rem; }
.dex-detail-facts { margin: 10px 0 6px; font-weight: 700; font-size: 0.85rem; color: var(--win-muted); }
.dex-detail-text { margin: 6px 0; font-size: 0.9rem; }
.dex-detail-text.muted { color: var(--win-muted); font-style: italic; }
.dex-detail-weak { margin: 6px 0; font-weight: 700; font-size: 0.85rem; }
.dex-moves-head { margin: 12px 0 6px; font-family: var(--pixel-font); font-synthesis-weight: none; font-weight: 400; font-size: 0.75rem; }
.dex-moves { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.dex-move { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: var(--round-xs); background: var(--win-panel); font-size: 0.88rem; font-weight: 700; }
.dex-move small { margin-left: auto; color: var(--win-muted); font-weight: 700; }
.dex-move.kind-attack { box-shadow: inset 4px 0 0 #d84838; }
.dex-move.kind-drain  { box-shadow: inset 4px 0 0 #9048c0; }
.dex-move.kind-defend { box-shadow: inset 4px 0 0 #3878f0; }
.dex-move.kind-buff   { box-shadow: inset 4px 0 0 #38a048; }
.dex-move.kind-status { box-shadow: inset 4px 0 0 #888890; }
@media (max-width: 720px) {
  .dex-body { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .dex-sprite { width: 56px; height: 56px; }
  .dex-name { font-size: 0.75rem; }
  .dex-perk { gap: 8px; padding: 8px; }
  .dex-perk-icon { font-size: 1.5rem; }
  .dex-detail-sprite { width: 88px; height: 88px; }
}

/* ---------- the SAFARI POKÉDEX (js/safaridex.js): the main one's look, a page per Safari area ---------- */
/* the Safari Pokédex (js/safaridex.js): the Pokédex's banners and handheld, an area a banner */
.safari-area-box { border-color: #4a8a24; }
.safari-prize-sprite { width: 56px; height: 56px; flex: none; object-fit: contain; image-rendering: pixelated; }
.safari-prize-sprite.silhouette { filter: brightness(0) opacity(0.55); }
.sdx-screen .pdx-role.sdx-rare { background: #c08a10; }
.sdx-device .bdx-slot { background: linear-gradient(180deg, #7ab8ff, #4a88e0); }
.sdx-device .bdx-slot.rare { background: linear-gradient(180deg, #ffe08a, #d8a020); }
.sdx-device .bdx-slot.on { background: #ffe36b; }
.sdx-device .bdx-slot.caught::after { content: ""; position: absolute; top: 2px; right: 2px; z-index: 1; width: 7px; height: 7px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 1px #3a0a0e; }
.sdx-device .bdx-slot.shiny::before {   /* a shiny that's yours: a gold four-point star in the slot's corner */
  content: ""; position: absolute; left: 1px; bottom: 1px; z-index: 1; width: 11px; height: 11px; background: #ffd34a;
  clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%); filter: drop-shadow(0 0 1px #6a4a00);
}
.sdx-device .bdx-slot.sealed { box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.35), 0 0 0 2px #5a6a8a; }
.sdx-slot-art { display: block; width: 100%; height: 100%; }
.sdx-slot-cap { position: absolute; left: -3px; top: -3px; z-index: 1; width: 16px; height: 16px; }
.sdx-slot-cap svg, .sdx-cap svg { display: block; width: 100%; height: 100%; }
/* the shinies and sealed capsules: over the banners, and under an area's slots */
.sdx-shinybar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; font: 0.75rem/1.3 var(--pixel-font); font-synthesis-weight: none; }
.sdx-shinybar.whole { margin-bottom: 8px; }
.sdx-shinycount { color: #7a5600; }
.sdx-sealedcount { display: inline-flex; align-items: center; gap: 5px; color: #2a3858; }
.sdx-cap { display: inline-block; width: 20px; height: 20px; flex: none; }
.sdx-nobar { display: none; }
/* its page: the ✨ switch, the sealed capsule badge and the lines */
.sdx-shinyflip {
  position: absolute; left: 8px; bottom: 8px; z-index: 3; padding: 5px 8px; border: 2px solid #a07000; border-radius: 999px; cursor: pointer;
  background: rgba(0, 0, 0, 0.5); color: #ffe590; font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none;
}
.sdx-shinyflip.on { background: linear-gradient(180deg, #fff3b8, #f0b830); color: #4a3000; box-shadow: 0 0 10px rgba(248, 208, 48, 0.7); }
.sdx-screen.sdx-shiny .pdx-mon { filter: drop-shadow(0 0 6px rgba(255, 220, 90, 0.75)); }
.sdx-screen .shiny-aura { z-index: 2; }
.sdx-sealbadge {
  position: absolute; right: 8px; top: 8px; z-index: 3; display: flex; align-items: center; gap: 3px; padding: 3px 7px 3px 4px; border-radius: 999px;
  background: rgba(10, 14, 26, 0.72); box-shadow: 0 0 0 2px #5a6a8a; color: #cfe0ff; font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none;
}
.sdx-sealbadge .sdx-cap { width: 22px; height: 22px; }
.pdx-text.sdx-sealedline { background: #1a2238; color: #cfe0ff; font: 0.75rem/1.4 var(--pixel-font); font-synthesis-weight: none; }
.pdx-text.sdx-sparkleline { background: linear-gradient(90deg, #fff3b8, #f2dc8a); color: #6a4a00; font: 0.75rem/1.4 var(--pixel-font); font-synthesis-weight: none; }
.sdx-sig { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.sdx-sig h4 { align-self: stretch; margin: 0; font: 0.75rem/1.3 var(--pixel-font); font-synthesis-weight: none; }
.sdx-sig .card { width: 130px; flex: none; }
.sdx-sig small { font-size: 0.75rem; opacity: 0.75; }
.safari-sig-locked { display: grid; place-items: center; width: 110px; aspect-ratio: 5 / 7; border: 3px dashed rgba(31, 58, 20, 0.5); border-radius: var(--round-sm); font: 2.4rem/1 var(--pixel-font); font-synthesis-weight: none; color: rgba(31, 58, 20, 0.5); }

/* a starter a won fight just unlocked (unlockWindow() in js/run.js): a gold banner, the Pokémon hopping on a spotlight */
.unlock-dialog { text-align: center; width: min(340px, calc(100vw - 32px)); }
.unlock-dialog[open] { animation: unlockIn 0.45s ease-out both; }
@keyframes unlockIn { 0% { scale: 0.6; opacity: 0; } 70% { scale: 1.06; opacity: 1; } 100% { scale: 1; } }
.unlock-kicker {
  margin: -4px -4px 10px;
  padding: 8px 10px 7px;
  background: repeating-linear-gradient(90deg, #f0b828 0 12px, #f8c848 12px 24px);
  border: 3px solid #181010;
  border-radius: var(--round-sm);
  color: #3a2408;
  font-family: var(--pixel-font);
  font-size: 0.95rem;
  animation: unlockFlash 0.9s steps(2) 3;
}
@keyframes unlockFlash { 50% { filter: brightness(1.35); } }
.unlock-stage {
  display: grid;
  place-items: end center;
  height: 120px;
  background: radial-gradient(ellipse 26% 7% at 50% 92%, rgba(24, 16, 16, 0.25) 0 98%, transparent), radial-gradient(circle at 50% 60%, #fff6d0 0 34%, transparent 35%);
}
.unlock-stage img { width: auto; height: 104px; image-rendering: pixelated; animation: unlockHop 0.9s ease-in-out infinite; transform-origin: 50% 100%; }
@keyframes unlockHop { 50% { translate: 0 -6px; } }
#unlock-name { margin: 6px 0 4px; font-family: var(--pixel-font); color: var(--win-gold); font-size: 1.3rem; }
#unlock-text { margin: 0 0 6px; }
.unlock-hint { margin: 0 0 4px; color: var(--muted); font-size: 0.75rem; }
@media (prefers-reduced-motion: reduce) { .unlock-dialog[open], .unlock-kicker, .unlock-stage img { animation: none; } }

/* the Bag never runs off a phone's screen: its pocket scrolls inside it (the user couldn't read past 8 relics) */
.bag:not([hidden]) { display: flex; flex-direction: column; max-height: calc(100dvh - 84px); }
.bag .bag-pocket-body { min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: 2px; }

/* the item swap's two little boxes (offerItem() in js/run.js): what you'd toss and what you'd take */
.swap-tips { display: flex; justify-content: center; gap: 8px; margin: 4px auto 10px; max-width: 380px; padding: 0 8px; animation: tipsIn 0.2s ease-out; }
.swap-tips[hidden], .swap-found[hidden] { display: none; }
/* a found item's window under it (offerItem), saying what it does without a text box to tap through */
.swap-tip.swap-found { max-width: min(320px, calc(100% - 32px)); margin-top: -8px; font-size: 0.75rem; }
.swap-found .card-tip-name { display: block; margin: 0 0 3px; font-size: 0.75rem; }
.swap-tip { flex: 1 1 0; max-width: 180px; text-align: left; }
.swap-tip .card-tip-name { display: block; margin-bottom: 3px; }
.swap-out .card-tip-name { color: #b8201c; }
.swap-in .card-tip-name { color: #2a7c2a; }

/* a card an event hands you (revealCard() in js/run.js): it pops up big in a burst of the treasure room's rays */
.reward-options.card-reveal-room { display: grid; place-items: center; }
.card-reveal { position: relative; display: grid; place-items: center; padding: 28px 0; }
.card-reveal .chest-rays { bottom: 50%; animation: raysIn 0.7s ease-out forwards, raysTurn 40s linear infinite; }
.card-reveal .card { --card-w: min(56vw, 220px); position: relative; animation: cardReveal 0.6s cubic-bezier(0.3, 1.6, 0.5, 1) both; }
@keyframes cardReveal { from { scale: 0.2; rotate: -12deg; opacity: 0; } 60% { opacity: 1; } }
.card-reveal.pair { grid-auto-flow: column; gap: 14px; }
.card-reveal.pair .card { --card-w: min(40vw, 180px); }
.card-reveal.pair .card:last-child { animation-delay: 0.15s; }
.card-reveal.trio { gap: 8px; }
.card-reveal.trio .card { --card-w: min(29vw, 160px); }
.card-reveal.trio .card:nth-child(4) { animation-delay: 0.08s; }
@media (prefers-reduced-motion: reduce) { .card-reveal .card, .card-reveal .chest-rays { animation: none; opacity: 1; } }
/* Voltorb Flip's table (flipGame() in js/run.js): eight cards, two rows of four, each turning over to its move or a
   Voltorb; a matched pair keeps a gold ring */
.reward-options.flip-game { display: grid; place-items: center; }
.flip-board { --tile-w: min(21vw, 112px, 15vh); display: grid; grid-template-columns: repeat(4, var(--tile-w)); gap: 10px; padding: 16px 0; }
.flip-tile { position: relative; width: var(--tile-w); aspect-ratio: 5 / 7.4; padding: 0; border: 0; background: none; cursor: pointer; perspective: 700px; }
.flip-back, .flip-face { position: absolute; inset: 0; display: grid; place-items: center; border-radius: 9%; backface-visibility: hidden; -webkit-backface-visibility: hidden; transition: transform 0.35s ease-out; }
.flip-back {
  background: radial-gradient(circle at 50% 50%, #f8f8f8 0 14%, #28242c 14% 19%, transparent 19%),
    linear-gradient(#e84838 0 47%, #28242c 47% 53%, #f8f8f8 53%);
  border: 3px solid #f8f8f8; box-shadow: 0 0 0 2px #28242c, 0 4px 0 #1a1820;
}
.flip-face { transform: rotateY(180deg); }
.flip-tile.up .flip-back { transform: rotateY(-180deg); }
.flip-tile.up .flip-face { transform: rotateY(0deg); }
.flip-face .card { --card-w: 100%; }
.flip-face:has(.flip-voltorb) { background: #2a2a38; border: 3px solid #f8d030; box-shadow: 0 0 0 2px #28242c; }
.flip-voltorb { width: 82%; image-rendering: pixelated; }
.flip-tile.kept .flip-face { box-shadow: 0 0 0 3px #f8d030, 0 0 12px 2px rgba(248, 208, 48, 0.7); }
@media (prefers-reduced-motion: reduce) { .flip-back, .flip-face { transition: none; } }

/* ---------- a biome's intro (js/biome-intro.js): a short film over the map as the biome starts ---------- */
.biome-intro { position: fixed; inset: 0; z-index: 940; overflow: hidden; background: #000; cursor: pointer; animation: biIn 0.5s both; }
.biome-intro.leaving { animation: biOut 0.65s ease-in both; pointer-events: none; }
@keyframes biIn { from { opacity: 0; } }
@keyframes biOut { to { opacity: 0; } }
.bi-canvas { position: absolute; left: 0; top: 0; image-rendering: pixelated; }
.bi-mons { position: absolute; inset: 0; }
.bi-mon { position: absolute; transform: translate(-50%, -100%); overflow: hidden; padding-top: 48px; }
.bi-mon img { display: block; image-rendering: pixelated; transform: translateY(110%); }
.bi-mon.up img { animation: biPop 0.7s cubic-bezier(.2, .9, .3, 1.2) both; }
.bi-mon img.unseen { filter: brightness(0); }
.bi-mon img { transition: filter .45s ease; }
.bi-walker { position: absolute; transform: translate(-50%, -100%); }
.bi-walker img { display: block; image-rendering: pixelated; }
@keyframes biPop { 0% { transform: translateY(110%); } 55% { transform: translateY(-22%); } 75% { transform: translateY(4%); } 100% { transform: none; } }
.bi-bars::before, .bi-bars::after { content: ''; position: absolute; left: 0; right: 0; height: 7vh; background: #000; z-index: 2; animation: biBar 0.8s ease-out both; }
.bi-bars::before { top: 0; --from: -100%; }
.bi-bars::after { bottom: 0; --from: 100%; }
.biome-intro.leaving .bi-bars::before, .biome-intro.leaving .bi-bars::after { animation: biBar 0.6s ease-in reverse both; }
@keyframes biBar { from { transform: translateY(var(--from)); } }
.bi-title { position: absolute; left: 0; right: 0; top: 9vh; z-index: 3; display: flex; flex-direction: column; align-items: center; gap: 1.6vh;
  text-align: center; pointer-events: none; padding: 0 12px; }
.bi-title::before { content: ''; position: absolute; inset: -4vh 0; z-index: -1; opacity: 0; background: radial-gradient(ellipse 60% 55% at 50% 50%, rgba(0, 10, 20, .55), transparent 75%); }
.bi-title.on::before { animation: biGlow 1s 0.1s both; }
.bi-kicker { font-size: clamp(12px, 2.6vw, 16px); color: #f8e070; letter-spacing: .3em; text-shadow: 2px 2px 0 #000; opacity: 0; }
.bi-name { display: flex; flex-direction: column; align-items: center; gap: .25em; font-size: clamp(26px, 11.5vw, 84px); line-height: 1; color: var(--ink); }
.bi-word { display: flex; }
.bi-letter { display: inline-block; opacity: 0;
  text-shadow: 0 .08em 0 var(--edge), .08em 0 0 var(--edge), -.08em 0 0 var(--edge), 0 -.08em 0 var(--edge), .08em .08em 0 var(--edge), -.08em .08em 0 var(--edge), .08em -.08em 0 var(--edge), -.08em -.08em 0 var(--edge), .1em .18em 0 var(--deep); }
.bi-place { font-size: clamp(16px, 6vw, 34px); color: #fff8e0; letter-spacing: .12em; text-transform: uppercase; opacity: 0;
  text-shadow: 0 3px 0 #000, 3px 0 0 #000, -3px 0 0 #000, 0 -3px 0 #000, 3px 3px 0 #000, -3px 3px 0 #000, 3px -3px 0 #000, -3px -3px 0 #000; }
.bi-place::before, .bi-place::after { content: "-"; color: #f8e070; margin: 0 .5em; }
.bi-title.on .bi-kicker { animation: biRise .5s both; }
.bi-title.on .bi-letter { animation: biDrop .55s calc(.25s + var(--i) * 55ms) cubic-bezier(.2, .9, .3, 1.4) both, biShine 2.4s calc(1.6s + var(--i) * 60ms) infinite; }
.bi-title.on .bi-place { animation: biRise .6s 1.3s both; }
/* a Safari area's name under SAFARI ZONE, on the Zone's green board */
.bi-area { font-size: clamp(15px, 5.2vw, 30px); color: #fff8e0; letter-spacing: .14em; text-transform: uppercase; opacity: 0; padding: .3em .8em .25em;
  background: #2e8a34; border: 3px solid #14501c; box-shadow: inset 0 3px 0 #68c858, 0 4px 0 rgba(0, 0, 0, .45); text-shadow: 2px 2px 0 #14501c; }
.bi-title.on .bi-area { animation: biRise .6s 1s both; }
.bi-title.on .bi-area ~ .bi-place { animation-delay: 1.5s; }
@keyframes biRise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes biGlow { to { opacity: 1; } }
@keyframes biDrop { 0% { opacity: 0; transform: translateY(-1.2em) scale(1.4); } 60% { opacity: 1; } 100% { opacity: 1; transform: none; } }
@keyframes biShine { 0%, 12%, 100% { color: var(--ink); } 5% { color: #ffffff; } }
@media (min-aspect-ratio: 1/1) {
  .bi-title { right: 40%; top: 16vh; }
  .bi-name { font-size: clamp(26px, 6.5vw, 84px); }
  .biome-intro.mini .bi-title { right: 0; top: 11vh; }
}
.bi-skip { position: absolute; right: 14px; bottom: calc(7vh + 10px); z-index: 3; font-size: 12px; color: #fff; opacity: .55; text-shadow: 1px 1px 0 #000; animation: biRise .5s 1.2s both; }
@media (prefers-reduced-motion: reduce) {
  .biome-intro, .biome-intro *, .biome-intro *::before, .biome-intro *::after { animation-duration: .01s !important; animation-delay: 0s !important; animation-iteration-count: 1 !important; }
  .bi-mon img { transform: none; }
}

/* ?scene=<place> (init() in js/main.js): only the painted scene, for a look at a room */
body.scene-peek > :not(#scene-bg):not(#scene-light):not(.peek-label):not(.biome-intro) { visibility: hidden !important; }
.peek-label { position: fixed; left: 50%; bottom: 12px; transform: translateX(-50%); z-index: 5; padding: 4px 10px; border: 2px solid #183a14; background: #3e8a3a; color: #fff8d8; font-family: var(--pixel-font); font-size: 0.75rem; white-space: nowrap; }
body.scene-peek #backdrop { display: none; }

/* ---------- the Safari Zone's lobby (js/safariprep.js): the Pokédex device, like the Sky Pillar's (the user's call,
   2026-10-07); it wears `.tower-lobby`, so the shell, lid, window, bezel, LCD, keys and the top-five list are the
   tower's, and only what's the Safari's own is here: the gate in the window (js/safari-lobby.js, `--ground` its grass
   line), the day's areas, the try pills, the balls and the rules, all in the LCD's ink. ---------- */
.safari-prep-dialog .sp-window { background: #4888e0; }
.sp-sky { position: absolute; left: 0; top: 0; pointer-events: none; }
.sp-gate-mon { position: absolute; z-index: 1; left: 50%; top: var(--ground, 80%); width: 84px; height: 84px; object-fit: contain; object-position: 50% 100%;
  translate: -50% calc(4px - 100%); pointer-events: none; image-rendering: pixelated; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.3)); animation: pdxIdle 1.4s ease-in-out infinite; }
.tdev-keys.sp-keys { grid-template-columns: repeat(4, 1fr); max-width: 330px; }
/* the Duo key in the window's top right corner (the user's call, 2026-10-20), grey until the day's Daily run is done */
.sp-window .sp-duo-key { position: absolute; z-index: 2; top: 8px; right: 8px; width: 62px; padding: 7px 0 6px; }
.sp-window .sp-duo-key .mdex-ico .smooth-icon { width: 26px; height: 26px; }
#sp-duo.locked { filter: grayscale(1) brightness(0.8); opacity: 0.75; }
/* .cdev-dex's overflow: hidden is for the Dex, which scrolls its own list; the Duo app is one long page */
.cdev-app.sp-duo-app { overflow-y: auto; }
/* the Duo app keeps the window: the picked pair stands at the gate, lead on the left */
.sp-gate-mon[hidden], .sp-gate-note[hidden] { display: none; }
.sp-window.duo-gate .sp-gate-mon { left: 36%; }
.sp-window.duo-gate .sp-gate-second { left: 64%; z-index: 0; animation-delay: -0.7s; }
.sp-gate-note { position: absolute; z-index: 2; left: 50%; bottom: 10px; translate: -50% 0; margin: 0; padding: 3px 8px; border: 2px solid #2a2a30;
  border-radius: 6px; background: rgba(216, 236, 176, 0.92); color: #1f3a14; font-family: var(--pixel-font); font-size: 0.75rem; white-space: nowrap; }
/* ---------- the Berry Booth (js/berrybooth.js, 2026-10-23): the Safari lobby's device, its window the run's loadout
   (the held slot, the Berry Pouch's, the kit's) on a berry-orchard green, its apps' rows in the LCD's ink ---------- */
.booth-dialog .bb-window { height: clamp(150px, 24dvh, 220px); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background: radial-gradient(ellipse at 50% 120%, #f6a0c8 0%, #8a3a7a 45%, #2a1a40 100%); }
.bb-load { width: 100%; }
.bb-slots { display: flex; justify-content: center; align-items: flex-start; gap: 10px; padding: 0 10px; }
.bb-split { align-self: stretch; width: 2px; margin: 4px 2px 18px; background: rgba(255, 255, 255, 0.3); }
.bb-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.bb-cell small { color: #fff4fa; font-family: var(--pixel-font); font-size: 0.75rem; text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5); }
.bb-slot { display: grid; place-items: center; width: 54px; height: 54px; padding: 0; border: 2px dashed rgba(255, 255, 255, 0.5); border-radius: 10px;
  background: rgba(0, 0, 0, 0.25); }
.bb-slot.full { border: 3px solid #2a2a30; background: #fdf6ec; box-shadow: 0 3px 0 rgba(0, 0, 0, 0.35); cursor: pointer; }
.bb-slot:disabled { cursor: default; }
.bb-cell.held .bb-slot.full { box-shadow: 0 0 0 3px #ffd84a, 0 3px 0 4px rgba(0, 0, 0, 0.35); }
.bb-cell.held.eaten .bb-slot { filter: grayscale(1) brightness(0.7); opacity: 0.6; }
.bb-cell.swap .bb-slot { animation: bbSwap 0.9s ease-in-out both; }
@keyframes bbSwap { 40% { translate: 0 -10px; } 100% { translate: 0 0; } }
.bb-ico { display: grid; place-items: center; width: 36px; height: 36px; flex: none; }
.bb-ico .item-sprite, .bb-ico img { width: 36px; height: 36px; image-rendering: pixelated; }
.bb-caption { margin: 0; padding: 3px 10px; border: 2px solid #2a2a30; border-radius: 6px; background: rgba(216, 236, 176, 0.92); color: #1f3a14;
  font-family: var(--pixel-font); font-size: 0.75rem; white-space: nowrap; }
.tdev-keys.bb-keys { grid-template-columns: repeat(3, 1fr); max-width: 260px; }
.bb-stock { margin: 0; font-size: 0.8rem; line-height: 1.4; }
.bb-tips { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; font-size: 0.75rem; line-height: 1.4; }
.bb-tips li { display: flex; gap: 6px; }
.bb-tip-icon { flex: none; width: 1.4em; text-align: center; }
.cdev-app.bb-app { overflow-y: auto; padding: 10px 12px 16px; display: flex; flex-direction: column; gap: 6px; font-family: var(--pixel-font); color: #1f3a14; background: #b6d68e; }
.bb-app-head, .bb-empty { margin: 0 0 2px; font-size: 0.75rem; line-height: 1.4; }
.bb-empty { padding: 8px 10px; border: 2px dashed #3d5a2a; border-radius: 6px; background: rgba(255, 255, 255, 0.35); }
.bb-row { display: flex; align-items: center; gap: 8px; width: 100%; padding: 5px 8px; border: 2px solid #1f3a14; border-radius: 8px; background: rgba(255, 255, 255, 0.4);
  color: inherit; font: inherit; text-align: left; cursor: pointer; }
.bb-row.on { background: #1f3a14; color: #d8ecb0; }
.bb-row:disabled { opacity: 0.45; cursor: default; }
.bb-row-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bb-row-text b { font-weight: 400; font-size: 0.8rem; }
.bb-row-text small { font-size: 0.75rem; line-height: 1.3; opacity: 0.85; }
.bb-count { flex: none; font-size: 0.8rem; }
.bb-guide-text { margin: 0; font-size: 0.8rem; line-height: 1.5; }
.bb-steps { margin: auto 0 0; text-align: center; font-size: 0.75rem; letter-spacing: 2px; }
@media (prefers-reduced-motion: reduce) { .bb-cell.swap .bb-slot { animation: none; } }
.type-badge { display: inline-block; width: 1.25em; height: 1.25em; flex: none; vertical-align: middle; }
.type-badge svg { display: block; width: 100%; height: 100%; filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.25)); }
.duo-type { display: inline-flex; align-items: center; gap: 4px; }
.duo-fold > summary { list-style: none; cursor: pointer; }
.duo-fold > summary::-webkit-details-marker { display: none; }
.duo-fold > summary::after { content: '▸'; margin-left: 2px; transition: rotate 0.2s; }
.duo-fold[open] > summary::after { rotate: 90deg; }
.duo-fold[open] { display: flex; flex-direction: column; gap: 4px; }
.duo-area-count { flex: none; min-width: 3.4em; text-align: right; font-size: 0.75rem; }
.duo-area-head.done .duo-area-count::before { content: '✓ '; }
.duo-area-head .sp-area-no { flex: none; width: 20px; height: 20px; border-radius: 50%; }
.duo-area-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 400; }
.duo-fares { flex: none; display: flex; align-items: center; gap: 4px; font-size: 0.75rem; }
.duo-tri { min-width: 30px; padding: 1px 4px; border: 2px solid currentColor; border-radius: 5px; background: rgba(255, 255, 255, 0.5); font: inherit; font-weight: 700; line-height: 1.2; cursor: pointer; }
.duo-tri.up { color: #1f8a3a; }
.duo-tri.down { color: #c0303a; }
.duo-tri.up.on, .duo-tri.down.on { color: #fff; }
.duo-tri.up.on { background: #1f8a3a; border-color: #1f8a3a; }
.duo-tri.down.on { background: #c0303a; border-color: #c0303a; }
.duo-why { margin: 4px 0 0; padding: 5px 8px; border-left: 4px solid; border-radius: 4px; background: rgba(255, 255, 255, 0.45); font-size: 0.75rem; line-height: 1.35; }
.duo-why.up { border-color: #1f8a3a; }
.duo-why.down { border-color: #c0303a; }
.duo-face-pic { position: absolute; inset: 0; overflow: hidden; border-radius: 50%; }
.duo-face .duo-face-mon { position: absolute; max-width: none; object-fit: fill; image-rendering: pixelated; }
.duo-face-type.type-badge { width: 22px; height: 22px; z-index: 1; }
/* the Duo key's app (js/duoprep.js): today's road, the duo pool's portraits, how the pair fares */
.duo-app { padding: 10px 12px 18px; display: flex; flex-direction: column; gap: 8px; font-family: var(--pixel-font); color: #1f3a14; }
.duo-head { margin: 4px 0 0; font-size: 0.85rem; letter-spacing: 0.04em; text-transform: uppercase; }
.duo-note, .duo-lock { margin: 0; font-size: 0.75rem; line-height: 1.35; }
.duo-lock { padding: 8px 10px; border: 2px dashed #3d5a2a; border-radius: 6px; background: rgba(255, 255, 255, 0.35); }
.duo-road { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.duo-area { padding: 6px 8px; border-radius: 6px; background: rgba(255, 255, 255, 0.3); display: flex; flex-direction: column; gap: 4px; }
.duo-area-head { margin: 0; display: flex; align-items: center; gap: 6px; font-size: 0.85rem; }
.duo-types { display: flex; flex-wrap: wrap; gap: 4px; }
.duo-type { font-size: 0.75rem; padding: 1px 6px; border-radius: 999px; background: #e8f0d8; border: 1px solid #3d5a2a; }
.duo-mons { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.duo-mon { width: 36px; height: 36px; object-fit: contain; }
.duo-mon.unseen { filter: brightness(0) opacity(0.55); }
.duo-pool { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; }
.duo-pick { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 6px 4px; border-radius: 8px; background: rgba(255, 255, 255, 0.3); border: 2px solid transparent; }
.duo-pick.on { border-color: #e2a92c; background: rgba(255, 236, 160, 0.55); }
.duo-pick.locked { opacity: 0.55; }
.duo-pick.locked .duo-face img { filter: brightness(0) opacity(0.5); }
.duo-face { position: relative; width: 64px; height: 64px; padding: 0; border: 2px solid #303038; border-radius: 50%; background: radial-gradient(circle at 50% 35%, #fff, #c8d8b0); cursor: pointer; }
.duo-pick.type-fire .duo-face  { background: radial-gradient(circle at 50% 35%, #ffd2b0, #ff8f4d); }
.duo-pick.type-grass .duo-face { background: radial-gradient(circle at 50% 35%, #d4f5c8, #72dc70); }
.duo-pick.type-water .duo-face { background: radial-gradient(circle at 50% 35%, #cfeaff, #5cbcff); }
.duo-pick.type-electric .duo-face { background: radial-gradient(circle at 50% 35%, #fff6c0, #ffd84a); }
.duo-pick.type-ice .duo-face { background: radial-gradient(circle at 50% 35%, #eafcff, #8ae0f8); }
.duo-pick.type-fighting .duo-face { background: radial-gradient(circle at 50% 35%, #ffe0d0, #f49a70); }
.duo-pick.type-ground .duo-face { background: radial-gradient(circle at 50% 35%, #fff0d0, #e8c878); }
.duo-pick.type-flying .duo-face { background: radial-gradient(circle at 50% 35%, #f0eeff, #c8c0ff); }
.duo-pick.type-dark .duo-face { background: radial-gradient(circle at 50% 35%, #f4ece4, #a8907c); }
.duo-face img { width: 100%; height: 100%; object-fit: contain; }
.duo-face-type { position: absolute; left: -4px; top: -4px; font-size: 0.8rem; }
.duo-face-no { position: absolute; right: -8px; bottom: -6px; padding: 1px 4px; border-radius: 4px; background: #e2a92c; color: #303038; font-style: normal; font-size: 0.75rem; }
.duo-name { font-size: 0.75rem; text-align: center; }
.duo-look { display: flex; flex-wrap: nowrap; justify-content: center; align-items: center; gap: 2px; font-size: 0.75rem; white-space: nowrap; }
.duo-arrow { flex: none; padding: 2px 4px; border: 1px solid #3d5a2a; border-radius: 4px; background: #e8f0d8; font-size: 0.75rem; cursor: pointer; }
.duo-count { min-width: 3.4em; text-align: center; }   /* 1/8 and 10/11 the same width, so the arrows never move or wrap */
.duo-face-box { position: relative; display: block; }
.duo-shiny {   /* the shown look's shiny, top right of the portrait like the type badge top left */
  position: absolute; right: -8px; top: -6px; width: 26px; height: 26px; padding: 0; display: grid; place-items: center;
  border: 2px solid #8a8a90; border-radius: 50%; background: #e4e4e8; font-size: 0.75rem; line-height: 1; cursor: pointer;
}
.duo-shiny > * { filter: grayscale(1); opacity: 0.55; }
.duo-shiny.on { border-color: #b08a1a; background: #fff3b0; box-shadow: 0 0 6px 1px rgba(255, 216, 74, 0.8); }
.duo-shiny.on > * { filter: none; opacity: 1; }
.sp-keys .mdex-btn { position: relative; }
.sp-tasks-n {   /* Ranger tasks ready to claim (js/safariprep.js's taskCount()) */
  position: absolute; top: -6px; right: -4px; min-width: 20px; height: 20px; padding: 0 5px; box-sizing: border-box; border-radius: 99px;
  display: grid; place-items: center; background: #d84838; color: #fff; font: 12px/1 var(--pixel-font); font-style: normal; box-shadow: 0 2px 0 #0005;
}
.sp-tasks-n[hidden] { display: none; }
/* its keys' apps (the Safari Dex, Ranks, the Game Corner) slide over the LCD as the Collection's do, and the window folds
   away to give them the room */
.sp-glass, .tower-lobby .tdev-glass { position: relative; }
.sp-app { inset: 8px; border: 3px solid #2a2a30; border-radius: 6px 6px 6px 22px; }
.tower-lobby .tower-window { transition: height 0.26s cubic-bezier(0.25, 0.8, 0.3, 1), border-width 0.26s, margin 0.26s, box-shadow 0.26s; }
.tower-lobby .app-open .tower-window { height: 0; border-width: 0; box-shadow: none; margin-bottom: -10px; }
.tdev-key .cdev-btn:disabled { filter: grayscale(1) brightness(0.8); animation: none; cursor: default; }
@media (prefers-reduced-motion: reduce) { .tower-lobby .tower-window { transition: none; } }
.sp-today { display: grid; gap: 8px; }
.sp-areas { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.sp-area { display: grid; grid-template-columns: 20px 1fr auto; align-items: center; gap: 8px; margin: 0; padding: 3px 6px 3px 3px; border: 2px solid rgba(31, 58, 20, 0.45);
  border-radius: 6px; font-size: 0.75rem; }
.sp-area b { font-weight: 400; text-transform: uppercase; letter-spacing: 0.5px; }
.sp-area small { font-size: 0.75rem; }
.sp-area-no { display: grid; place-items: center; height: 20px; border-radius: 4px; background: #1f3a14; color: #b6d68e; font-size: 0.75rem; }
.sp-area.done { background: #1f3a14; color: #b6d68e; }
.sp-area.done .sp-area-no { background: #b6d68e; color: #1f3a14; }
.sp-try { margin: 0; display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; }
.sp-try .smooth-icon { width: 15px; height: 15px; }
/* the two tries side by side: what each one gets, the off ones struck through */
.sp-replay { display: grid; grid-template-columns: repeat(4, auto); justify-content: center; align-items: center; gap: 6px 5px; margin: 0; padding: 8px 0;
  border-block: 2px dashed rgba(31, 58, 20, 0.35); }
.sp-pill-row { display: contents; }
.sp-pill { padding: 4px 7px 3px; border: 2px solid #1f3a14; border-radius: 5px; font-size: 0.75rem; line-height: 1; text-align: center; text-transform: uppercase; letter-spacing: 0.3px; }
.sp-pill:is(.daily, .replay) { background: #1f3a14; color: #b6d68e; }
.sp-pill.off { border-color: rgba(31, 58, 20, 0.35); color: rgba(31, 58, 20, 0.45); text-decoration: line-through; }
.sp-eq { font-size: 0.75rem; }
.sp-foot { display: grid; gap: 6px; }
.safari-prep-dialog .sp-head { margin: 0; font-size: 0.75rem; font-weight: 400; letter-spacing: 0.5px; text-transform: uppercase; color: #1f3a14; }
.sp-balls { display: flex; gap: 6px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; overscroll-behavior-x: contain; }
.sp-balls::-webkit-scrollbar { display: none; }
.sp-balls.more-r { mask-image: linear-gradient(90deg, #000 85%, transparent); }
.sp-balls.more-l { mask-image: linear-gradient(90deg, transparent, #000 15%); }
.sp-balls.more-l.more-r { mask-image: linear-gradient(90deg, transparent, #000 15%, #000 85%, transparent); }
.sp-ball { position: relative; flex: none; display: grid; justify-items: center; width: 54px; padding: 3px 0 4px; border: 2px solid rgba(31, 58, 20, 0.45); border-radius: 6px;
  scroll-snap-align: start; cursor: help; }
.sp-ball.none { opacity: 0.4; }
.sp-ball.none .sp-ball-icon img { filter: grayscale(1); }
.sp-ball-icon img { width: 36px; height: 36px; image-rendering: pixelated; }
.sp-ball-left { font-size: 0.75rem; font-weight: 400; }
.sp-how > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 6px; -webkit-tap-highlight-color: transparent; }
.sp-how > summary::-webkit-details-marker { display: none; }
.sp-how > summary::after { content: '▸'; transition: rotate 0.2s; }
.sp-how[open] > summary::after { rotate: 90deg; }
.sp-rules { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 7px; }
.safari-prep-dialog .sp-rules li { display: grid; grid-template-columns: 1.6em 1fr; align-items: center; gap: 8px; margin: 0; font-size: 0.75rem; line-height: 1.6; }
.safari-prep-dialog .sp-rules li.with-card { grid-template-columns: 1.6em 1fr auto; }
.sp-rule-icon { display: grid; place-items: center; font-size: 1rem; }
.sp-rule-icon .smooth-icon { width: 18px; height: 18px; }
.sp-card { width: 54px; cursor: zoom-in; flex: none; }
.safari-prep-dialog .sp-plaque-slot { min-height: 0; }
@media (prefers-reduced-motion: reduce) { .sp-gate-mon { animation: none; } }

/* ---------- the leaderboards (js/leaderboard.js): the Pokédex's banners and handheld (the user's call, 2026-10-07, over
   the dark glassy panel they had for a day). A banner per board with its top three on it, then the red handheld, one
   trainer a screen; the period, the name and sign-in on green LCDs above the banners. The window (the title's 🏆, the
   result window's Leaderboard) is a red handheld of its own; the lobbies' Ranks apps sit in their own device's screen. ---------- */
.board-dialog {
  width: min(480px, 94vw); height: min(780px, 88dvh); max-height: none; padding: 0; border: 0; border-radius: 22px; overflow: hidden; color: #1f3a14;
  background: linear-gradient(180deg, var(--shell-hi), var(--shell) 40%, var(--shell-lo));
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset 6px 0 0 rgba(255, 255, 255, 0.08), 0 24px 60px rgba(0, 0, 0, 0.5);
}
.board-dialog[open] { display: flex; flex-direction: column; }
.lb-lid { display: flex; align-items: center; gap: 8px; padding: 12px 12px 10px; }
.board-dialog #board-title {
  flex: 1; min-width: 0; margin: 0 0 0 6px; padding: 7px 6px 6px; outline: none; white-space: nowrap; overflow: hidden; text-align: center;
  font: 0.75rem/1.3 var(--pixel-font); font-synthesis-weight: none; text-transform: uppercase;
}
.lb-glass { position: relative; flex: 1; margin: 0 10px 12px; border: 4px solid #2a2a30; border-radius: 8px 8px 8px 24px; box-shadow: 0 0 0 3px var(--shell-rim); }
.lb-signin, .lb-name-form { display: grid; justify-items: center; gap: 8px; text-align: center; }
.lb-signin p, .lb-name-form p { margin: 0; }
.lb-name-form strong { font-weight: 400; font-size: 0.75rem; }
.lb-name-input {
  width: min(260px, 100%); padding: 8px 12px; border: 3px solid var(--shell-rim); border-radius: 8px; background: #e4f0cc; color: #1f3a14;
  font: 0.75rem/1.2 var(--pixel-font); font-synthesis-weight: none;
}
.lb-name-input:focus { outline: 3px solid #ffe36b; outline-offset: 1px; }
.lb-btn {
  flex: none; padding: 8px 14px 7px; border: 3px solid var(--shell-rim); border-radius: 8px; background: #e4f0cc; color: #1f3a14; cursor: pointer;
  font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none; box-shadow: 0 3px 0 var(--shell-rim);
}
.lb-btn.primary { background: var(--btn-a); color: #fff; }
.lb-btn:active { translate: 0 2px; box-shadow: 0 1px 0 var(--shell-rim); }
/* the board itself (2026-10-18, the user's ask: an MMO-style table, easy to read): a banner, gold period tabs, board pills,
   a row per trainer with the top three in gold / silver / bronze, your own row pinned, then the count and your name */
.lb-host { overflow: hidden !important; }
.lb-mmo, .lb-top {
  --lb-ink: #e8ecff; --lb-dim: #9aa6d4; --lb-gold: #ffd25a; --lb-gold-lo: #b8861c; --lb-row: #1b2342; --lb-row2: #171e3a; --lb-line: #2c3766;
}
.lb-mmo {
  position: absolute; inset: 0; display: flex; flex-direction: column; overflow: hidden; color: var(--lb-ink);
  background: linear-gradient(180deg, #1a2244, #0e1328); font: 0.75rem/1.3 var(--pixel-font); font-synthesis-weight: none;
}
.lb-hero {
  position: relative; flex: none; display: grid; gap: 6px; justify-items: start; padding: 10px 84px 9px 12px; overflow: hidden;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.16) 1px, transparent 1.5px) 0 0 / 10px 10px, linear-gradient(120deg, var(--b1), var(--b2));
  border-bottom: 3px solid var(--lb-gold-lo); text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.45);
}
.lb-hero-name { font-size: 0.95rem; font-weight: 400; color: #fff; text-transform: uppercase; text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.45); }
.lb-hero-line { line-height: 1.6; color: #eef2ff; }
.lb-hero-timer { padding: 4px 7px; border: 2px solid rgba(255, 255, 255, 0.35); border-radius: 6px; background: rgba(0, 0, 0, 0.35); color: var(--lb-gold); }
.lb-hero-mon { position: absolute; right: 4px; bottom: -4px; width: 76px; height: 76px; object-fit: contain; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.35)); }
.lb-top { display: grid; gap: 6px; padding: 8px 8px 0; background: #0c1024; }
.lb-top:empty { display: none; }
.lb-period { display: flex; gap: 4px; margin: 0 0 -6px; border-bottom: 3px solid var(--lb-gold-lo); }
.lb-key {
  flex: 1; padding: 9px 2px 8px; border: 2px solid var(--lb-line); border-bottom: 0; border-radius: 7px 7px 0 0; background: #141a32; color: var(--lb-dim);
  cursor: pointer; font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none; white-space: nowrap;
}
.lb-key[aria-selected="true"] { border-color: var(--lb-gold-lo); background: linear-gradient(180deg, #ffe58a, var(--lb-gold)); color: #1a1406; }
.lb-top .pdx-lcd { margin: 6px 0 0; padding: 8px 10px; border: 2px solid var(--lb-line); border-radius: 8px; background: #141a32; color: var(--lb-ink); box-shadow: none; font: 0.75rem/1.7 var(--pixel-font); font-synthesis-weight: none; }
.lb-top .pdx-lcd ~ .pdx-lcd { margin-top: 0; }
.lb-top .lb-mine { border-color: #5ad08a; color: #b8ffd0; }
.lb-note { text-align: center; }
.lb-pills { flex: none; display: flex; gap: 6px; padding: 8px; background: #141a32; }
.lb-pills.scroll { overflow-x: auto; scrollbar-width: none; }
.lb-pill {
  flex: 1 0 auto; padding: 8px 10px 7px; border: 2px solid var(--lb-line); border-radius: 20px; background: none; color: var(--lb-dim); cursor: pointer;
  font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none; white-space: nowrap;
}
.lb-pill[aria-selected="true"] { border-color: #6a7ee0; background: #2d3a78; color: #fff; }
.lb-cols { position: sticky; top: 0; z-index: 1; display: flex; gap: 6px; padding: 7px 14px; border-top: 2px solid var(--lb-line); border-bottom: 2px solid var(--lb-line); background: #10162e; color: var(--lb-dim); text-transform: uppercase; }
.lb-cols span:first-child { width: 86px; }
.lb-cols span:nth-child(2) { flex: 1; }
.lb-scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.lb-rows { padding: 4px 6px; }
.lb-empty { margin: 24px 12px; text-align: center; color: var(--lb-dim); line-height: 1.7; }
.lb-row { margin: 4px 0; border: 2px solid transparent; border-radius: 8px; background: var(--lb-row); }
.lb-row:nth-child(even) { background: var(--lb-row2); }
.lb-row-head {
  display: grid; grid-template-columns: 34px 40px 1fr auto; align-items: center; column-gap: 6px; width: 100%; padding: 5px 6px; border: 0;
  background: none; color: inherit; text-align: left; cursor: pointer; font: inherit;
}
.lb-rk { grid-row: 1 / span 3; display: grid; place-items: center; height: 30px; color: var(--lb-dim); }
.lb-rk.medal { color: #1a1406; clip-path: polygon(50% 0, 100% 22%, 100% 78%, 50% 100%, 0 78%, 0 22%); }
.lb-mon { grid-row: 1 / span 3; width: 40px; height: 40px; object-fit: contain; }
.lb-who { display: contents; }
.lb-name { grid-column: 3; min-width: 0; overflow: hidden; font-weight: 400; color: #fff; white-space: nowrap; text-overflow: ellipsis; }
.lb-sub { grid-column: 3 / span 2; margin-top: 5px; font-size: 0.75rem; overflow: hidden; color: var(--lb-dim); white-space: nowrap; text-overflow: ellipsis; }
.lb-val { grid-column: 4; grid-row: 1; font-size: 0.875rem; color: #fff; text-align: right; white-space: nowrap; }
.lb-aug-row { grid-column: 3 / span 2; display: flex; flex-wrap: nowrap; align-items: center; gap: 3px; margin-top: 5px; overflow: hidden; }
.lb-aug-row .aug-icon, .lb-aug-row .aug-emoji { flex: none; width: 22px; height: 22px; font-size: 16px; line-height: 22px; }
.lb-aug-more { color: var(--lb-dim); }
.lb-crown { margin-right: 4px; }
.lb-shiny { margin-left: 5px; color: #ffd84a; text-shadow: 0 0 6px rgba(255, 216, 74, 0.6); }
.lb-you-tag { margin-right: 6px; padding: 2px 4px; border-radius: 4px; background: #5ad08a; color: #0c2416; }
.lb-row.gold { border-color: rgba(255, 210, 90, 0.6); background: linear-gradient(90deg, rgba(255, 210, 90, 0.28), rgba(255, 210, 90, 0.04)); box-shadow: 0 0 12px rgba(255, 210, 90, 0.25); }
.lb-row.silver { border-color: rgba(200, 210, 235, 0.4); background: linear-gradient(90deg, rgba(200, 210, 235, 0.2), rgba(200, 210, 235, 0.03)); }
.lb-row.bronze { border-color: rgba(216, 138, 72, 0.45); background: linear-gradient(90deg, rgba(216, 138, 72, 0.22), rgba(216, 138, 72, 0.03)); }
.lb-row.gold .lb-rk { background: linear-gradient(180deg, #fff2a8, #f4c430 60%, #b8861c); }
.lb-row.silver .lb-rk { background: linear-gradient(180deg, #ffffff, #c8d0e0 60%, #7d879c); }
.lb-row.bronze .lb-rk { background: linear-gradient(180deg, #ffd0a0, #d88a48 60%, #8a4a1c); }
.lb-row.gold .lb-name, .lb-row.gold .lb-val { color: var(--lb-gold); }
.lb-row.gold .lb-val { text-shadow: 0 0 6px rgba(255, 210, 90, 0.6); }
.lb-rows .lb-row.mine { box-shadow: inset 0 0 0 2px #5ad08a; }
.lb-row.pinned { flex: none; margin: 4px 6px 6px; border-color: #5ad08a; background: linear-gradient(90deg, #1f5a3a, #173a2c); box-shadow: 0 0 10px rgba(90, 208, 138, 0.35); }
.lb-row.pinned .lb-rk { color: #b8ffd0; background: none; clip-path: none; }
.lb-row.pinned.open { max-height: 45%; overflow-y: auto; }
.lb-more { display: grid; gap: 8px; padding: 4px 8px 10px; }
.lb-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; padding: 8px; border: 2px solid var(--lb-line); border-radius: 6px; background: rgba(0, 0, 0, 0.3); }
.lb-facts span { display: grid; gap: 4px; min-width: 0; overflow-wrap: anywhere; }
.lb-facts b { font-weight: 400; color: var(--lb-dim); }
.lb-augs { display: grid; gap: 4px; padding: 8px; border: 2px solid var(--lb-line); border-radius: 6px; background: rgba(0, 0, 0, 0.3); }
.lb-augs b { margin-bottom: 2px; font-weight: 400; color: var(--lb-dim); }
.lb-aug { display: flex; align-items: center; gap: 8px; line-height: 1.4; }
.lb-aug .aug-icon, .lb-aug .aug-emoji { flex: none; width: 26px; height: 26px; font-size: 18px; line-height: 26px; text-align: center; }
.lb-add { justify-self: center; }
.lb-add.on, .lb-add:disabled { opacity: 0.7; cursor: default; translate: none; }
.lb-foot { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 7px 10px; border-top: 2px solid var(--lb-line); background: #0a0e20; color: var(--lb-dim); }
.lb-mmo .lb-btn { border-color: var(--lb-gold-lo); background: var(--lb-gold); color: #1a1406; box-shadow: 0 3px 0 var(--lb-gold-lo); }
.lb-mmo .lb-btn.primary { border-color: #2a7a4a; background: #5ad08a; color: #0c2416; box-shadow: 0 3px 0 #2a7a4a; }
.lb-name-key { min-width: 0; max-width: 60%; padding: 6px 8px 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.bdx-banner.empty { cursor: default; }
.bdx-banner.empty:hover, .bdx-banner.empty:active { transform: none; }
.bdx-banner.empty .pdx-banner-sub { top: 42px; max-width: 70%; }
.board-line { font-size: 1.1rem; text-align: center; }

/* ---------- the descent to the Sealed Gate (js/descent.js): the arena splits, your Pokémon falls down a crystal shaft into
   violet light. Under the gate's scene (z-index 949), which fades in over its dark last frame. ---------- */
.descent-scene { position: fixed; inset: 0; z-index: 949; overflow: hidden; background: #05020c; animation: gateIn 0.6s ease-out both; }
.descent-scene.waiting { cursor: pointer; }
.descent-world { position: absolute; inset: 0; }
.descent-canvas { position: absolute; left: 0; top: 0; width: 100%; height: 100%; image-rendering: pixelated; }
.descent-scene.shaking .descent-world { animation: descentShake 0.12s linear infinite alternate; }
@keyframes descentShake { 0% { translate: -3px 1px; } 50% { translate: 3px -1px; } }
/* your Pokémon: standing on the arena floor (top is its feet), then tumbling down the middle of the shaft */
.descent-mon { position: absolute; left: 50%; max-width: none; translate: -50% calc(var(--foot, 0px) - 100%); image-rendering: pixelated; }
.descent-scene.shaking .descent-mon { animation: descentTotter 0.5s ease-in-out infinite; }
@keyframes descentTotter { 0%, 100% { rotate: 0deg; } 25% { rotate: -4deg; } 75% { rotate: 4deg; } }
.descent-scene.loss .descent-mon { filter: grayscale(0.7) brightness(0.6); }
.descent-scene.falling .descent-mon { translate: -50% calc(-50% + var(--mid, 0px)); animation: descentDrop 0.7s cubic-bezier(0.3, 0, 0.4, 1) both, descentTumble 2.4s ease-in-out 0.7s infinite; filter: drop-shadow(0 6px 10px rgba(176, 96, 240, 0.55)); }
.descent-scene.falling.loss .descent-mon { filter: grayscale(0.7) brightness(0.6) drop-shadow(0 6px 10px rgba(120, 40, 160, 0.5)); }
/* transform, not top, so the fall moves on the GPU: falling, place() puts it at 40% of the height, so -30% is -70vh */
@keyframes descentDrop { from { transform: translate3d(0, -70vh, 0); rotate: -30deg; } to { transform: translate3d(0, 0, 0); } }
@keyframes descentTumble { 0%, 100% { rotate: -8deg; translate: -50% calc(-50% + var(--mid, 0px) - 4px); } 50% { rotate: 8deg; translate: -50% calc(-50% + var(--mid, 0px) + 4px); } }
/* the landing: the light below floods up, your Pokémon drops into it, then dark for the gate */
.descent-light { position: absolute; inset: 0; pointer-events: none; opacity: 0; background: radial-gradient(ellipse 90% 60% at 50% 115%, #f6dcff 0%, #c070ff 30%, rgba(122, 48, 192, 0.6) 55%, transparent 80%); }
.descent-scene.falling .descent-light { opacity: 0.35; transition: opacity 3s; }
.descent-scene.landing .descent-light { opacity: 1; transition: opacity 1s ease-in; }
.descent-scene.landing .descent-mon { animation: descentLand 1.1s cubic-bezier(0.5, 0, 0.9, 0.6) forwards; }
@keyframes descentLand { to { transform: translate3d(0, 80vh, 0); rotate: 20deg; } }
.descent-flash { position: absolute; inset: 0; background: #f0c8ff; opacity: 0; pointer-events: none; }
.descent-scene.flash .descent-flash { animation: descentFlash 0.7s ease-out; }
@keyframes descentFlash { 0% { opacity: 0; } 20% { opacity: 1; } 100% { opacity: 0; } }
.descent-dark { position: absolute; inset: 0; background: #05020c; opacity: 0; pointer-events: none; }
.descent-scene.dark .descent-dark { opacity: 1; transition: opacity 0.6s ease-in; }
/* the gate already open: the light below glows up through the crack, your Pokémon leans towards it and is thrown back */
.descent-scene.glowing .descent-light { opacity: 0.4; transition: opacity 2s; }
.descent-scene.drawn .descent-mon { animation: descentDrawn 1.6s ease-in-out forwards; }
@keyframes descentDrawn { to { transform: translate3d(0, 4px, 0) scale(1.06); } }
.descent-scene.repelled .descent-mon { animation: descentRepelled 0.9s cubic-bezier(0.2, 0.8, 0.3, 1) forwards; }
@keyframes descentRepelled {
  0% { transform: translate3d(0, 4px, 0) scale(1.06); filter: brightness(3) drop-shadow(0 0 12px #c070ff); }
  30% { transform: translate3d(0, -22px, 0) scale(0.95); }
  100% { transform: translate3d(0, -8px, 0) scale(0.9); filter: drop-shadow(0 0 6px rgba(176, 96, 240, 0.5)); }
}
.descent-scene.still, .descent-scene.still .descent-mon, .descent-scene.still.flash .descent-flash { animation: none; }
.descent-scene.still.falling .descent-mon { top: 40%; }
.descent-scene.still.landing .descent-mon { animation: none; opacity: 0; }

/* ---------- journey films (js/travel.js): your Pokémon walks to the next biome between two canvases ---------- */
.travel-scene { position: fixed; inset: 0; z-index: 945; overflow: hidden; background: #000; cursor: pointer; animation: biIn 0.5s both; }
.travel-canvas { position: absolute; left: 0; top: 0; image-rendering: pixelated; }
.travel-mon { position: absolute; max-width: none; translate: -50% calc(var(--foot, 0px) - 100%); scale: -1 1; image-rendering: pixelated;
  filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.35)); }
.travel-flyer { position: absolute; max-width: none; translate: -50% -50%; image-rendering: pixelated; pointer-events: none;
  filter: brightness(0) drop-shadow(0 0 1px rgba(220, 228, 255, 0.85)); }   /* a silhouette, rimmed by the moon so it reads at night */
.travel-bars::before, .travel-bars::after { content: ''; position: absolute; left: 0; right: 0; height: 5vh; background: #000; pointer-events: none; }
.travel-bars::before { top: 0; } .travel-bars::after { bottom: 0; }
.travel-skip { position: absolute; right: 12px; top: calc(5vh + 8px); font-size: 12px; color: rgba(255, 255, 255, 0.6); text-shadow: 1px 1px 0 #000; pointer-events: none; }
.travel-scene.waiting .travel-skip { visibility: hidden; }
.travel-dark { position: absolute; inset: 0; background: #000; opacity: 0; pointer-events: none; }
.travel-scene.dark .travel-dark { opacity: 1; transition: opacity 0.6s ease-in; }
.travel-scene.still { animation: none; }

/* the crossroads after a boss (js/crossroads.js): a card over each road, your Pokémon at the fork, the button under it */
.crossroads-scene { position: fixed; inset: 0; z-index: 944; overflow: hidden; touch-action: none; background: #282c68; animation: biIn 0.5s both; user-select: none; -webkit-user-select: none; }
.crossroads-scene.still, .crossroads-scene.held { animation: none; }
.crossroads-scene.wait > * { visibility: hidden; }
.crossroads-scene.dark .travel-dark { opacity: 1; transition: opacity 0.6s ease-in; }
.xr-mon { position: absolute; max-width: none; translate: -50% calc(var(--foot, 0px) - 100%); transform-origin: 50% 100%;
  image-rendering: pixelated; pointer-events: none; }
.xr-mon.walking { animation: xrBob 0.38s steps(2) infinite; }
@keyframes xrBob { 50% { margin-top: -3px; } }
.crossroads-scene.still .xr-mon { animation: none; }
.xr-roads { position: absolute; inset: 0; pointer-events: none; }
.xr-road { position: absolute; top: calc(12px + env(safe-area-inset-top)); translate: -50% 0; display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 0 6px 8px; border: 3px solid #1a1008; border-radius: 6px; background: rgba(20, 14, 34, 0.82); color: #fff4d6; cursor: pointer;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.45); pointer-events: auto; font: inherit; transition: translate 0.2s, border-color 0.2s; }
.xr-road:hover { border-color: #8a6a3a; }
.xr-road.on { border-color: #f8c850; translate: -50% 4px; box-shadow: 0 0 0 2px #fff0a0, 0 0 16px rgba(248, 200, 80, 0.55), 3px 3px 0 rgba(0, 0, 0, 0.45); }
.xr-road .xr-sign { margin: -3px -9px 2px; width: calc(100% + 18px); box-sizing: border-box; padding: 6px 8px 7px; font-size: 1rem; text-align: center; line-height: 1.15; }
.xr-label { font-size: 0.75rem; letter-spacing: 1px; text-transform: uppercase; opacity: 0.7; }
.xr-bosses { display: flex; justify-content: center; align-items: flex-end; gap: 2px; min-height: 44px; }
.xr-boss { height: 44px; width: auto; max-width: 33%; object-fit: contain; image-rendering: pixelated; }
.xr-boss.unmet { filter: brightness(0) drop-shadow(0 0 1px rgba(255, 240, 200, 0.8)); }
.xr-types { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px; }
/* Wayfinder (the Savanna page's perk): steps the second road through the other biomes it could be */
.xr-swap { margin-top: 4px; padding: 3px 10px; border: 2px solid #f8c850; border-radius: 999px; background: #3a2a14; color: #fff0a0; font-size: 0.8rem; cursor: pointer; }
.xr-swap:hover { background: #5a4020; }
.xr-types .chip { font-size: 0.75rem; padding: 2px 6px; }
.xr-go { position: absolute; left: 50%; bottom: calc(14px + env(safe-area-inset-bottom)); translate: -50% 0; min-width: 200px; max-width: calc(100% - 32px); white-space: nowrap; }
.xr-go:disabled { opacity: 1; filter: saturate(0.4) brightness(0.85); }
.crossroads-scene.chosen .xr-roads, .crossroads-scene.chosen .xr-go { opacity: 0; transition: opacity 0.4s; }
@media (min-width: 721px) {
  .xr-road .xr-sign { font-size: 1.25rem; }
  .xr-bosses, .xr-boss { min-height: 64px; height: 64px; }
}

/* the Sky Pillar's opening film (js/climb-intro.js), on the journey films' frame */
.climb-mon { position: absolute; left: 50%; max-width: none; transform-origin: 50% 100%; image-rendering: pixelated;
  filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.35)); }
.climb-title { position: absolute; left: 0; right: 0; top: 20vh; text-align: center; pointer-events: none; opacity: 0;
  font: 1.7rem/1.2 var(--pixel-font); letter-spacing: 2px; color: #fff; transition: opacity 0.7s;
  text-shadow: 2px 2px 0 #10183a, -2px -2px 0 #10183a, 2px -2px 0 #10183a, -2px 2px 0 #10183a; }
.climb-title small { display: block; margin-top: 0.7rem; font-size: 0.75rem; letter-spacing: 1px; color: #a0ffc8; }
.climb-scene.titled .climb-title { opacity: 1; }
.climb-light { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.8s ease-in;
  background: radial-gradient(circle at 50% var(--door, 50%), #f0fff8 0, #9af0c8 30%, rgba(60, 200, 150, 0) 75%); }
.climb-scene.flood .climb-light { opacity: 1; }

/* "New!": a card or relic you've never had (not in the Index yet), on rewards and the Mart's shelves */
.new-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  z-index: 3;
  padding: 3px 5px 2px;
  font-family: var(--pixel-font);
  font-size: 0.75rem;
  line-height: 1;
  color: #181010;
  background: #f8d030;
  border: 2px solid #181010;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.35);
  rotate: 8deg;
  pointer-events: none;
}
.relic:has(> .new-badge) { position: relative; }
.card.small > .new-badge { font-size: 0.75rem; top: -5px; right: -5px; }
.float-thing > .new-badge { top: 0; right: -4px; }

/* the Sky Pillar's lobby (js/towerprep.js): the Pokédex device, like the map and the Collection (the user's call,
   2026-10-07: it should match them). A lid with the lens, lights and an LCD title; a window onto the painted tower
   (`--ground` the grass line the climber stands on); the grey-bezelled screen, a green LCD with the floors in
   seven-segment digits, the rules and the week's top climbers; then the hardware: Leaderboard / Practice keys, B and A. */
.tower-lobby { position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; overflow: hidden;
  background: var(--shell); color: #fff; }
.tower-lobby::backdrop { background: #000; }
/* it comes in over the title the way New game's select does, as the title fades (leaveTitle(): 0.38 s) */
.tower-lobby[open], .tower-lobby[open]::backdrop { animation: lobbyIn 0.38s ease-out both; }
@keyframes lobbyIn { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .tower-lobby[open], .tower-lobby[open]::backdrop { animation: none; } }
.tower-page { position: relative; display: flex; flex-direction: column; gap: 10px; height: 100%; width: 100%; margin: 0 auto; overflow: hidden;
  padding: max(8px, env(safe-area-inset-top)) 12px max(12px, env(safe-area-inset-bottom));
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.1), transparent 30%), linear-gradient(180deg, var(--shell-hi), var(--shell) 30%, var(--shell-lo));
  box-shadow: inset 0 0 0 3px var(--shell-rim); }
@media (min-width: 560px) {
  .tower-lobby { background: radial-gradient(ellipse at 50% 30%, #1c2448, #070a16); }
  .tower-page { width: 500px; height: min(920px, calc(100% - 32px)); margin: 16px auto; border-radius: 26px; box-shadow: inset 0 0 0 3px var(--shell-rim), 0 18px 50px rgba(0, 0, 0, 0.5); }
}
.tdev-lid { flex: none; display: flex; align-items: center; gap: 8px; min-height: 48px; }
.tdev-lid .pdx-lens { width: 38px; height: 38px; }
.tower-lobby[open] .pdx-light { animation: pdxBlink 0.16s steps(1) 5 both; }
.tower-lobby[open] .pdx-light.yellow { animation-delay: 0.08s; }
.tower-lobby[open] .pdx-light.green { animation-delay: 0.16s; }
.tdev-lid .cdev-lcd { min-width: 0; max-width: 64%; }
.tower-title { margin: 0; font-size: 0.75rem; font-weight: 400; letter-spacing: 1px; text-transform: uppercase; }
.tower-title:focus { outline: none; }
.tower-week { margin: 0; font-size: 0.75rem; opacity: 0.75; white-space: nowrap; }
/* the window onto the tower: the canvas is painted to this box (startSky()) */
.tower-window { position: relative; flex: none; height: clamp(190px, 34dvh, 340px); overflow: hidden; border: 3px solid #2a2a30; border-radius: 10px;
  background: #10183a; box-shadow: 0 0 0 3px var(--shell-rim), inset 0 0 0 2px rgba(255, 255, 255, 0.25); }
.tower-sky { position: absolute; left: 0; top: 0; pointer-events: none; }
.tower-pad { position: absolute; z-index: 1; left: 50%; top: var(--ground, 80%); width: 110px; height: 24px; translate: -50% -40%; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, rgba(170, 255, 210, 0.75), rgba(70, 220, 150, 0.35) 55%, rgba(40, 180, 120, 0) 100%); animation: towerPad 2.6s ease-in-out infinite; }
@keyframes towerPad { 50% { opacity: 0.6; scale: 0.92; } }
.tower-mon { position: absolute; z-index: 1; left: 50%; top: var(--ground, 80%); width: 80px; height: 80px; object-fit: contain; object-position: 50% 100%;
  translate: -50% calc(6px - 100%); pointer-events: none; filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.45)); animation: pdxIdle 1.4s ease-in-out infinite; }
.tower-window.power-on { animation: pdxPowerOn 0.5s steps(8) both; }
/* the screen: the Collection's grey bezel, its corner cut, a green LCD inside */
.tdev-glass { flex: 1; min-height: 0; display: flex; padding: 8px; border-radius: 12px 12px 12px 30px; background: #e4e4ea; box-shadow: inset 0 0 0 3px var(--shell-rim), inset 0 -4px 0 rgba(0, 0, 0, 0.14); }
.tower-base::-webkit-scrollbar { display: none; }
.tower-base > * { flex: none; }
.tower-base { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; padding: 10px 10px 12px; border: 3px solid #2a2a30; border-radius: 6px 6px 6px 22px; background: #b6d68e; color: #1f3a14;
  box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.12); text-shadow: none; animation: pdxLcd 0.3s steps(3) both; }
.tower-name { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin: 0; padding-bottom: 7px; border-bottom: 2px dashed rgba(31, 58, 20, 0.35);
  font-size: 0.75rem; letter-spacing: 0.5px; text-transform: uppercase; }
.tower-name strong { font-weight: 400; font-size: 0.78rem; letter-spacing: 1px; }
.tower-name span { opacity: 0.75; text-align: right; }
.tower-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tower-stat { display: grid; gap: 6px; padding: 7px 9px 8px; border: 2px solid rgba(31, 58, 20, 0.55); border-radius: 6px; background: rgba(31, 58, 20, 0.06); }
.tower-stat-label { display: flex; align-items: center; gap: 5px; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; }
.tower-stat-label .smooth-icon { width: 15px; height: 15px; flex: none; }
.tower-stat .sdx-seg { height: 32px; }
.tower-rules { list-style: none; margin: 0; padding: 0; display: flex; justify-content: space-between; gap: 4px; font-size: min(0.75rem, 2.1vw); text-transform: uppercase; white-space: nowrap; }
.tower-rules li { display: flex; align-items: center; gap: 4px; margin: 0; }
.tower-rules .smooth-icon { width: 15px; height: 15px; flex: none; }
.tower-note { margin: -2px 0 0; font-size: 0.75rem; line-height: 1.5; text-align: center; opacity: 0.8; }
.tower-picks { display: grid; grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); gap: 6px; padding-top: 8px; border-top: 2px dashed rgba(31, 58, 20, 0.35); }
.tower-picks[hidden] { display: none; }
.tower-picks::before { content: 'Practice with...'; grid-column: 1 / -1; font-size: 0.75rem; text-transform: uppercase; }
.tower-pick { aspect-ratio: 1; padding: 3px; border: 2px solid rgba(31, 58, 20, 0.55); border-radius: 6px; background: rgba(31, 58, 20, 0.06); cursor: pointer;
  -webkit-tap-highlight-color: transparent; }
.tower-pick:hover, .tower-pick:focus-visible { outline: none; background: #1f3a14; }
.tower-pick img { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
/* the hardware: two menu keys like the map's, then B and A (A climbs) */
.tdev-pad { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 2px 2px 0; }
.tdev-keys { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; flex: 1; max-width: 190px; }
.tdev-keys .mdex-btn { padding: 8px 2px 7px; }
.tdev-keys .mdex-ico .smooth-icon { width: 26px; height: 26px; }
.tdev-keys .mdex-btn.on { translate: 0 2px; background: #b6d68e; color: #1f3a14; box-shadow: inset 0 0 0 2px var(--shell-rim), 0 1px 0 var(--shell-deep); }
.tdev-keys .mdex-btn.on .mdex-label { text-shadow: none; }
.tdev-ab { display: flex; align-items: flex-start; gap: 12px; }
.tdev-key { display: grid; justify-items: center; gap: 5px; font-size: 0.75rem; text-transform: uppercase; text-shadow: 1px 1px 0 var(--shell-deep); }
.tdev-key .cdev-btn { -webkit-tap-highlight-color: transparent; }
.tdev-key.b { margin-top: 16px; }
.tdev-key.b .cdev-btn { background: radial-gradient(circle at 35% 30%, #f4f4f8 0 12%, #b8b8c4 45%, #6a6a78); color: #2a2a30; text-shadow: none; }
.tdev-key.a .cdev-btn { width: 62px; height: 62px; font-size: 0.9rem; animation: tdevGo 2.2s ease-in-out infinite; }
@keyframes tdevGo { 50% { box-shadow: 0 4px 0 var(--shell-deep), 0 0 0 4px rgba(255, 255, 255, 0.35), 0 0 22px 4px rgba(255, 255, 255, 0.35); } }
.tdev-key .cdev-btn:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .tower-pad, .tower-mon, .tdev-key.a .cdev-btn, .tower-window.power-on { animation: none; } }

/* ---------- the Sky Pillar's climb (js/tower.js): the tower is the map, painted behind the run card ---------- */
.tower-view { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: #0a0c1c; }
#map-screen.tower .map-wrap { display: none; }
#map-screen.tower .run-card { z-index: 2; }
.tw-canvas { position: absolute; left: 0; top: 0; image-rendering: pixelated; }
.tw-mon { position: absolute; max-width: none; translate: -50% calc(var(--foot, 0px) - 100%); image-rendering: pixelated; pointer-events: none;
  filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.4)); }
.tw-mon.flip { scale: -1 1; }
.tw-mon.behind { filter: brightness(0.55) drop-shadow(0 2px 0 rgba(0, 0, 0, 0.4)); }
.tw-doors { position: absolute; inset: 0; pointer-events: none; }
.tw-grave { pointer-events: auto; }
.tw-door { position: absolute; pointer-events: auto; padding: 0; border: 0; background: none; cursor: pointer; border-radius: 40% 40% 4px 4px / 22% 22% 4px 4px; }
.tw-door:hover, .tw-door:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--gem), 0 0 18px 2px var(--gem); background: color-mix(in srgb, var(--gem) 14%, transparent); }
/* each door's room on a little hanging sign over its arch, bobbing like the map's rooms */
.tw-door-tag { position: absolute; left: 50%; bottom: 100%; translate: -50% -2px; display: grid; place-items: center; min-width: 30px; height: 26px; padding: 0 4px;
  border: 2px solid #2a2028; border-radius: 4px; background: linear-gradient(#f8ecd0, #d8c49c); box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.18), 0 0 0 2px var(--gem), 2px 3px 0 rgba(0, 0, 0, 0.45);
  font-size: 0.95rem; line-height: 1; animation: twTag 1.6s ease-in-out infinite; }
.tw-door-tag::before { content: ''; position: absolute; left: 50%; bottom: 100%; width: 2px; height: 6px; translate: -50% 0; background: #2a2028; }
.tw-door:nth-child(2) .tw-door-tag { animation-delay: -0.5s; } .tw-door:nth-child(3) .tw-door-tag { animation-delay: -1s; }
.tw-door.guardian .tw-door-tag { min-width: 40px; height: 32px; font-size: 1.2rem; background: linear-gradient(#fff4b8, #f8c830); }
@keyframes twTag { 50% { translate: -50% -6px; } }
/* the altitude gauge: the sky's colours by height, a tick every 10 floors, your floor and your best */
.tw-gauge { position: absolute; left: 4px; top: max(36px, calc(env(safe-area-inset-top) + 28px)); bottom: calc(var(--tw-bar-h, 240px) + 18px); width: 12px; pointer-events: none; z-index: 1; }
.tw-gauge-cap { position: absolute; top: -16px; left: 50%; translate: -50% 0; font-size: 0.75rem; color: #f8f0d8; text-shadow: 1px 1px 0 #000; }
.tw-gauge-track { position: absolute; inset: 0; border: 2px solid #1a1620; border-radius: 6px; box-shadow: 0 0 0 2px #8a8274, 2px 3px 0 2px rgba(0, 0, 0, 0.4); }
.tw-tick { position: absolute; left: 0; right: 0; height: 1px; background: rgba(255, 255, 255, 0.55); }
.tw-mark { position: absolute; left: 100%; translate: 3px 50%; display: none; align-items: center; gap: 3px; font-size: 0.75rem; color: #f8f0d8; text-shadow: 1px 1px 0 #000; white-space: nowrap; }
.tw-mark b { font-weight: normal; font-size: 0.75rem; }
.tw-gauge.wide { width: 16px; }
.tw-gauge.wide .tw-mark { display: flex; }
.tw-here { position: absolute; left: 50%; width: 22px; height: 10px; translate: -50% 50%; border: 2px solid #1a1620; border-radius: 3px; background: #f8f0d8; box-shadow: 0 0 8px 2px rgba(255, 240, 180, 0.8); transition: bottom 1.4s ease-in-out; }
.tw-best { position: absolute; left: -4px; right: -4px; height: 3px; translate: 0 50%; background: #f8c830; box-shadow: 0 0 0 1px #4a3410; }

/* the guardian intros and the fall (js/tower.js): one overlay over everything */
.tower-fx { position: fixed; inset: 0; z-index: 946; overflow: hidden; background: #000; cursor: pointer; animation: biIn 0.4s both; }
.tower-fx.shake .tw-canvas, .tower-fx.shake .tw-fx-mon { animation: twShake 0.45s linear; }
@keyframes twShake { 20% { translate: 4px 2px; } 40% { translate: -5px -1px; } 60% { translate: 3px -2px; } 80% { translate: -2px 2px; } }
.tw-fx-mon { position: absolute; max-width: none; translate: -50% -100%; transform-origin: 50% 100%; image-rendering: pixelated; pointer-events: none; opacity: 0;
  filter: brightness(0) drop-shadow(0 0 3px rgba(255, 90, 60, 0.9)) drop-shadow(0 0 12px rgba(255, 60, 40, 0.6)); }
.tw-fx-mon.rayquaza { filter: brightness(0) drop-shadow(0 0 3px #a0ffc8) drop-shadow(0 0 16px #30d880) drop-shadow(0 0 30px rgba(60, 220, 140, 0.6)); }
.tw-fx-mon.faller { translate: -50% -50%; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.4)); transform-origin: 50% 50%; }
.tw-fx-text { position: absolute; left: 50%; top: 22%; translate: -50% 0; display: grid; justify-items: center; gap: 10px; width: min(92vw, 520px); text-align: center; pointer-events: none; }
.tw-fx-text.in { animation: twSlam 0.5s cubic-bezier(0.3, 1.5, 0.5, 1) both; }
.tw-fx-top { font-size: 0.75rem; letter-spacing: 3px; color: #f8d878; text-shadow: 2px 2px 0 #000; }
.tw-fx-name { font-weight: normal; font-size: clamp(1.1rem, 5vw, 2rem); color: #fff; text-shadow: 3px 0 0 #2a0c10, -3px 0 0 #2a0c10, 0 3px 0 #2a0c10, 0 -3px 0 #2a0c10, 0 7px 0 rgba(0, 0, 0, 0.5); }
@keyframes twSlam { 0% { scale: 2.4; opacity: 0; } 60% { scale: 0.94; opacity: 1; } 100% { scale: 1; } }
.tw-fx-dark { position: absolute; inset: 0; background: #000; opacity: 0; pointer-events: none; }
.tower-fx.flash .tw-fx-dark { background: #fff; animation: twFlash 0.5s both; }
@keyframes twFlash { 0% { opacity: 1; } 100% { opacity: 0; } }
.tower-fx.dark .tw-fx-dark { background: #000; opacity: 1; transition: opacity 0.45s ease-in; animation: none; }
@media (prefers-reduced-motion: reduce) { .tw-door-tag, .tw-fx-text.in { animation: none; } }
.tw-fx-text.high { top: 7%; }
/* the lobby's plaque (js/towerprep.js): the week's top climbers engraved in a bronze plate, riveted at the corners */
/* pinned to the screen's bottom while the lobby scrolls (the user's ask, 2026-10-05); sticky needs the pages' overflow to be
   clip, not hidden, or the page would be its scroll container. The empty slot lets taps through until the plaque is in. */
.tower-plaque-slot { position: relative; z-index: 2; width: 100%; min-height: var(--plaque-h, 0px); margin: 6px 0 max(10px, env(safe-area-inset-bottom)); pointer-events: none; }
.tower-plaque-slot[hidden] { display: none; }
.tower-plaque.in { pointer-events: auto; }
.tower-plaque { visibility: hidden; opacity: 0; transition: opacity 0.35s ease-out, visibility 0s 0.35s; }
.tower-plaque.in { visibility: visible; opacity: 1; transition: opacity 0.35s ease-out; }
.tower-plaque { position: relative; width: 100%; margin: 0; text-shadow: none; padding: 10px 18px 12px; border: 3px solid #4a3410; border-radius: 6px;
  background: linear-gradient(160deg, #f0d088 0%, #c89a48 35%, #a87830 70%, #c89a48 100%); color: #3a2408;
  box-shadow: inset 2px 2px 0 rgba(255, 248, 210, 0.6), inset -2px -2px 0 rgba(60, 36, 8, 0.4), 3px 4px 0 rgba(0, 0, 0, 0.35); }
.tower-plaque::before, .tower-plaque::after { content: ''; position: absolute; top: 5px; width: 6px; height: 6px; border-radius: 50%; background: #6a4818; box-shadow: inset 1px 1px 0 #f8e0a0; }
.tower-plaque::before { left: 5px; } .tower-plaque::after { right: 5px; }
.tower-plaque-title { margin: 0 0 10px; font-size: 0.85rem; text-align: center; letter-spacing: 1px; color: #3a2408; text-shadow: 1px 1px 0 rgba(255, 240, 190, 0.7); }
.tower-plaque-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; font-size: 1rem; }
.tower-plaque-row { display: grid; grid-template-columns: 24px 40px 1fr auto; align-items: center; gap: 8px; padding-bottom: 6px; border-bottom: 1px solid rgba(74, 52, 16, 0.35);
  text-shadow: 1px 1px 0 rgba(255, 240, 190, 0.6); }
.tower-plaque-row:last-child { border-bottom: 0; padding-bottom: 0; }
.tower-plaque-row img { width: 40px; height: 40px; object-fit: contain; image-rendering: pixelated; filter: sepia(1) saturate(0.6) brightness(0.8) contrast(1.3); }
.tower-plaque-row.mine .tower-plaque-name { color: #1a5a28; }
.tower-plaque-rank { text-align: right; }
.tower-plaque-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tower-plaque-row.empty { opacity: 0.35; }
.tower-plaque-note { text-align: center; font-size: 0.85rem; opacity: 0.85; }
@media (max-width: 480px) { .tower-plaque { padding: 10px 14px 12px; } .tower-plaque-list { font-size: 0.85rem; gap: 6px; } .tower-plaque-row { grid-template-columns: 20px 34px 1fr auto; gap: 6px; } .tower-plaque-row img { width: 34px; height: 34px; } }

/* the Sky Pillar lobby's plaque, on its LCD: dark green ink, your row lit in reverse */
.tower-lobby .tower-plaque-slot { margin: 0; padding-top: 8px; border-top: 2px dashed rgba(31, 58, 20, 0.35); }
.tower-lobby .tower-plaque { padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; color: #1f3a14; text-shadow: none; }
.tower-lobby .tower-plaque::before, .tower-lobby .tower-plaque::after { display: none; }
.tower-lobby .tower-plaque-title { display: flex; align-items: center; gap: 6px; margin: 0 0 6px; font-size: 0.75rem; font-weight: 400; letter-spacing: 0.5px;
  text-transform: uppercase; color: #1f3a14; text-shadow: none; }
.tower-lobby .tower-plaque-title .smooth-icon { width: 16px; height: 16px; }
.tower-lobby .tower-plaque-list { gap: 2px; font-size: 0.75rem; }
.tower-lobby .tower-plaque-row { grid-template-columns: 22px 32px 1fr auto; gap: 6px; padding: 2px 6px 2px 2px; border: 0; border-radius: 4px; text-shadow: none; }
.tower-lobby .tower-plaque-row > * { text-shadow: none; }
.tower-lobby .tower-plaque-row:last-child { padding-bottom: 2px; }
.tower-lobby .tower-plaque-rank { text-align: center; }
.tower-lobby .tower-plaque-row[data-rank="1"] .tower-plaque-rank::before { content: '★'; }
.tower-lobby .tower-plaque-row[data-rank="1"] .tower-plaque-rank { font-size: 0; }
.tower-lobby .tower-plaque-row[data-rank="1"] .tower-plaque-rank::before { font-size: 0.85rem; }
.tower-lobby .tower-plaque-row img { width: 32px; height: 32px; filter: grayscale(1) contrast(1.4); mix-blend-mode: multiply; }
.tower-lobby .tower-plaque-row.mine { background: #1f3a14; color: #b6d68e; }
.tower-lobby .tower-plaque-row.mine .tower-plaque-name { color: inherit; }
.tower-lobby .tower-plaque-row.mine img { filter: grayscale(1) invert(1) sepia(1) hue-rotate(40deg) saturate(1.5); mix-blend-mode: screen; }
.tower-lobby .tower-plaque-note { font-size: 0.75rem; }

/* ---------- THE POKÉDEX WINDOW (js/pokedex.js): full screen, Pokémon GO's banner per biome, then a handheld Pokédex ---------- */
.pokedex {
  position: fixed; inset: 0; width: 100%; height: 100%; max-width: none; max-height: none; margin: 0; padding: 0; border: 0;
  overflow: hidden; color: #1f2a44;
  background:
    radial-gradient(circle, rgba(255, 255, 255, 0.35) 1px, transparent 1.5px) 0 0 / 14px 14px,
    linear-gradient(180deg, #c8ecf8, #9fd6ec);
}
.pokedex::backdrop { background: #9fd6ec; }
.pokedex[open] { display: block; }
.pdx-list, .pdx-stage { position: absolute; inset: 0; overflow: auto; overscroll-behavior: contain; isolation: isolate; }
.pdx-stage { z-index: 1; }
.pdx-list[hidden], .pdx-stage[hidden] { display: none; }
.pdx-list { padding: max(12px, env(safe-area-inset-top)) 12px max(16px, env(safe-area-inset-bottom)); }
.pdx-top, .pdx-banners { width: min(560px, 100%); margin: 0 auto; }
.pdx-top { display: grid; grid-template-columns: 44px 1fr 44px; align-items: center; gap: 8px; margin-bottom: 14px; }
.pdx-close {
  width: 44px; height: 44px; border-radius: 50%; border: 3px solid #fff; background: #e9f6fb; color: #2f6f9a;
  font-size: 1.1rem; box-shadow: 0 3px 0 rgba(30, 80, 110, 0.25); cursor: pointer;
}
.pdx-title {
  justify-self: center; margin: 0; padding: 9px 26px 8px; border: 0; border-radius: 999px; background: #2f78b0; color: #fff;
  font: 0.85rem/1 var(--pixel-font); font-synthesis-weight: none; letter-spacing: 1px; box-shadow: 0 3px 0 #1d5482; outline: none;
}
.pdx-total { justify-self: end; font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none; color: #2f78b0; white-space: nowrap; }
.pdx-banners { display: flex; flex-direction: column; gap: 12px; }

.pdx-banner {
  --b1: #5cb850; --b2: #2b7a3a;
  position: relative; display: block; width: 100%; height: 116px; padding: 0; overflow: hidden; text-align: left; cursor: pointer;
  border: 4px solid #fff; border-radius: 18px; color: #fff; font-family: var(--pixel-font); font-synthesis-weight: none;
  background: linear-gradient(150deg, var(--b1), var(--b2));
  box-shadow: 0 4px 0 rgba(30, 80, 110, 0.22), inset 0 0 0 2px rgba(0, 0, 0, 0.08);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.pdx-banner:hover { transform: translateY(-2px); box-shadow: 0 6px 0 rgba(30, 80, 110, 0.22); }
.pdx-banner:active { transform: translateY(2px); box-shadow: 0 2px 0 rgba(30, 80, 110, 0.22); }
.pdx-banner:focus-visible { outline: 4px solid #ffe36b; outline-offset: 2px; }
.pdx-banner.complete { border-color: #ffe9a0; box-shadow: 0 4px 0 rgba(30, 80, 110, 0.22), inset 0 0 0 3px rgba(255, 230, 140, 0.55); }
.pdx-banner-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 70%; image-rendering: pixelated; }
.pdx-banner-shade { position: absolute; inset: 0; background: linear-gradient(90deg, var(--b2) 0, color-mix(in srgb, var(--b2) 70%, transparent) 38%, transparent 66%); }
.pdx-banner-art:not([hidden]) ~ .pdx-stripe { display: none; }
.pdx-stripe {
  position: absolute; inset: 0 0 0 auto; width: 64%; clip-path: polygon(24% 0, 100% 0, 100% 100%, 0 100%);
  background:
    linear-gradient(115deg, transparent 0 18%, rgba(255, 255, 255, 0.5) 18% 20%, transparent 20% 25%, rgba(255, 255, 255, 0.35) 25% 26%, transparent 26%),
    radial-gradient(circle, rgba(255, 255, 255, 0.35) 1.4px, transparent 2px) 0 0 / 9px 9px,
    rgba(255, 255, 255, 0.12);
}
.pdx-banner-name { position: absolute; left: 14px; top: 12px; font-size: 1.05rem; font-weight: 400; letter-spacing: 1px; text-transform: uppercase; text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.35); }
.pdx-banner-sub { position: absolute; left: 14px; top: 36px; max-width: 48%; font-size: 0.75rem; line-height: 1.4; text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.45); }
.pdx-banner-count { position: absolute; left: 14px; top: 56px; font-size: 0.75rem; text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.45); }
.pdx-banner .dex-bar { position: absolute; left: 14px; top: 72px; width: 40%; height: 8px; margin: 0; border: 0; border-radius: 6px; background: rgba(0, 0, 0, 0.3); }
.pdx-banner .ach-fill { background: #ffe36b; border-radius: 6px; }
.pdx-medal {
  position: absolute; left: 12px; bottom: 7px; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%;
  font-size: 0.8rem; border: 2px solid rgba(255, 255, 255, 0.8); background: rgba(0, 0, 0, 0.25); filter: grayscale(1); opacity: 0.75;
}
.pdx-banner-name .pdx-medal { position: relative; left: auto; bottom: auto; display: inline-grid; vertical-align: middle; margin: -6px 0 0 10px; width: 34px; height: 34px; font-size: 1.05rem; letter-spacing: 0; text-shadow: none; }
.pdx-medal.lv1 { filter: none; opacity: 1; background: linear-gradient(160deg, #f4f4f8, #9ea4b4); border-color: #fff; }
.pdx-medal.lv2 { filter: none; opacity: 1; background: linear-gradient(160deg, #fff2a0, #d89a10); border-color: #fff6c8; box-shadow: 0 0 8px rgba(255, 220, 100, 0.8); }
.pdx-banner-mons { position: absolute; right: 2px; bottom: 0; display: flex; align-items: flex-end; }
.pdx-banner-mon { width: 76px; height: 76px; object-fit: contain; object-position: bottom; image-rendering: pixelated; margin-left: -18px; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.25)); }
.pdx-banner-mon:nth-child(2) { width: 92px; height: 92px; z-index: 1; }
.pdx-banner-mon.unseen { filter: brightness(0) opacity(0.55); }
.pdx-trophy { right: 22px; bottom: 14px; font-size: 4.4rem; line-height: 1; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.25)); }
.pdx-mystery-mark { margin: 0 34px 14px 0; font: 3.6rem/1 var(--pixel-font); font-synthesis-weight: none; color: rgba(255, 255, 255, 0.25); }
.pdx-banner.biome-clearing { --b1: #6cc85a; --b2: #2b7a3a; }
.pdx-banner.biome-shrine   { --b1: #c27ad2; --b2: #5a2e7e; }
.pdx-banner.biome-ruins    { --b1: #4ab8c0; --b2: #14485e; }
.pdx-banner.biome-thornwood { --b1: #6ac040; --b2: #1e4a1a; }
.pdx-banner.biome-savanna { --b1: #f0b040; --b2: #8a4a14; }
.pdx-banner.biome-wastes   { --b1: #f08a48; --b2: #8a2a18; }
.pdx-banner.biome-depths   { --b1: #9a68e8; --b2: #24104c; }
.pdx-banner.biome-mystery  { --b1: #4a3a72; --b2: #140c26; cursor: default; }
.pdx-banner.pdx-rewards    { --b1: #f2c040; --b2: #a8640c; }

/* the handheld: a red Pokédex, the Gen 1 anime's, one entry at a time */
.pdx-stage {
  display: flex; justify-content: center; align-items: flex-start; padding: 0;
  background:
    radial-gradient(circle, rgba(255, 255, 255, 0.35) 1px, transparent 1.5px) 0 0 / 14px 14px,
    linear-gradient(180deg, #c8ecf8, #9fd6ec);
}
.pdx-stage.zooming { background: transparent; overflow: hidden; }
.pdx-device {
  --sky: #bfe8ff; --ground: #7cc75f; --pad: #5ea548;
  display: flex; flex-direction: column; width: min(520px, 100%); min-height: 100%;
  background: linear-gradient(180deg, var(--shell-hi), var(--shell) 40%, var(--shell-lo));
  position: relative; box-shadow: inset 0 0 0 3px var(--shell-rim), inset 6px 0 0 rgba(255, 255, 255, 0.08);
}
@media (min-width: 560px) {
  .pdx-stage { padding: 20px 0; }
  .pdx-device { min-height: 0; border-radius: 22px; box-shadow: inset 0 0 0 3px var(--shell-rim), 0 14px 40px rgba(20, 60, 90, 0.35); }
}
.pdx-device.biome-shrine { --sky: #f7c6d8; --ground: #b89870; --pad: #8e7454; }
.pdx-device.biome-ruins { --sky: #a8e0e0; --ground: #6a8a7a; --pad: #4a6a5c; }
.pdx-device.biome-thornwood { --sky: #b8e890; --ground: #3e6a2a; --pad: #2e5020; }
.pdx-device.biome-savanna { --sky: #ffd890; --ground: #b88a40; --pad: #8a6428; }
.pdx-device.biome-wastes { --sky: #ffb070; --ground: #7a3c24; --pad: #5a2a18; }
.pdx-device.biome-depths { --sky: #3a2470; --ground: #6a4aa8; --pad: #4a2e88; }
.pdx-lid {
  position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 8px;
  padding: max(10px, env(safe-area-inset-top)) 12px 10px; background: var(--shell); border-bottom: 3px solid var(--shell-rim);
}
@media (min-width: 560px) { .pdx-lid { border-radius: 22px 22px 0 0; } }
.pdx-back {
  width: 38px; height: 38px; border-radius: 10px; border: 3px solid var(--shell-rim); background: #f2f2f2; color: var(--shell-rim);
  font-size: 0.9rem; cursor: pointer; box-shadow: 0 3px 0 var(--shell-rim);
}
.pdx-back:active { translate: 0 2px; box-shadow: 0 1px 0 var(--shell-rim); }
.pdx-lens {
  width: 40px; height: 40px; border-radius: 50%; border: 4px solid #fff; flex: none;
  background: radial-gradient(circle at 34% 30%, #e6f8ff 0 14%, #5ec8ff 16%, #1f78c8 70%); box-shadow: 0 0 0 2px var(--shell-rim);
}
.pdx-light { width: 11px; height: 11px; border-radius: 50%; border: 2px solid var(--shell-rim); flex: none; }
.pdx-light.red { background: #ff5a5a; }
.pdx-light.yellow { background: #ffe36b; }
.pdx-light.green { background: #6be36b; }
.pdx-lid-title { margin-left: auto; font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none; color: #ffe0e2; letter-spacing: 1px; text-transform: uppercase; }
.pdx-body { flex: 1; display: flex; flex-direction: column; gap: 10px; padding: 12px; }
.pdx-lcd {
  padding: 8px 10px; border: 3px solid var(--shell-rim); border-radius: 8px; background: #b6d68e; color: #1f3a14;
  box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.12); font-size: 0.85rem; line-height: 1.45;
}
.pdx-nameplate { display: flex; justify-content: space-between; align-items: center; gap: 8px; font: 0.8rem/1.2 var(--pixel-font); font-synthesis-weight: none; }
.pdx-no { opacity: 0.75; white-space: nowrap; }
.pdx-plate2 { display: grid; grid-template-columns: 1fr auto; gap: 6px 8px; }
.pdx-plate2 .pdx-no, .pdx-plate2 .pdx-sub:last-child { text-align: right; }
.pdx-sub { font-size: 0.75rem; opacity: 0.75; white-space: nowrap; }
.pdx-screen {
  position: relative; flex: none; aspect-ratio: 2 / 1; container-type: size;
  border: 4px solid #2a2a30; border-radius: 10px; overflow: hidden; touch-action: pan-y;
  background: linear-gradient(180deg, var(--sky) 0 58%, var(--ground) 58%);
  box-shadow: 0 0 0 3px var(--shell-rim), inset 0 0 0 2px rgba(255, 255, 255, 0.35);
}
/* the biome's own scenery (scene.js's sceneShot()), its battle pad, and the Pokémon standing on it */
.pdx-scene { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center bottom; image-rendering: pixelated; pointer-events: none; }
.pdx-scene-old { z-index: 0; }
.pdx-pad { position: absolute; left: 24cqw; bottom: 5cqh; width: 52cqw; height: 17.3cqw; border-radius: 50%; background: var(--pad); box-shadow: inset 0 -4px 0 rgba(0, 0, 0, 0.18); }
.pdx-screen.painted .pdx-pad { border-radius: 0; box-shadow: none; background-color: transparent; background-size: 100% 100%; image-rendering: pixelated; }
.pdx-mon {
  position: absolute; left: 20cqw; bottom: calc(5cqh + 7.5cqw); width: 60cqw; height: 68cqh; object-fit: contain; object-position: bottom;
  image-rendering: pixelated; pointer-events: none; animation: pdxIdle 1.4s ease-in-out infinite;
}
.pdx-screen.unseen .pdx-mon:not(.pdx-ghost), .pdx-mon.pdx-ghost.unseen { filter: brightness(0) opacity(0.7); animation: none; }
.pdx-ghost { animation: none; }
@keyframes pdxIdle { 50% { transform: translateY(-3px); } }
/* powering on: the screen opens from a bright line, like an old set warming up, then the LCDs settle */
.pdx-screen.power-on { animation: pdxPowerOn 0.5s steps(8) both; }
@keyframes pdxPowerOn {
  0% { clip-path: inset(49% 0 49% 0); filter: brightness(4) saturate(0); }
  35% { clip-path: inset(0 0 0 0); filter: brightness(2.2) saturate(0.4); }
  100% { clip-path: inset(0 0 0 0); filter: none; }
}
.pdx-body .pdx-lcd { animation: pdxLcd 0.3s steps(3) both; }
@keyframes pdxLcd { from { filter: brightness(1.25) contrast(0.6); } }
.pdx-device.powered .pdx-light { animation: pdxBlink 0.16s steps(1) 5 both; }
.pdx-device.powered .pdx-light.yellow { animation-delay: 0.08s; }
.pdx-device.powered .pdx-light.green { animation-delay: 0.16s; }
@keyframes pdxBlink { 50% { filter: brightness(1.8); box-shadow: 0 0 8px 2px currentColor; } }
.pdx-light.red { color: #ff5a5a; }
.pdx-light.yellow { color: #ffe36b; }
.pdx-light.green { color: #6be36b; }
.pdx-device.powered .pdx-lens { animation: pdxLens 0.9s ease-out both; }
@keyframes pdxLens { 30% { box-shadow: 0 0 0 2px var(--shell-rim), 0 0 16px 6px #7fd8ff; filter: brightness(1.4); } }
.pdx-text.typing::after { content: '▌'; margin-left: 1px; animation: pdxCaret 0.5s steps(1) infinite; }
@keyframes pdxCaret { 50% { opacity: 0; } }
/* the front cover that swings open on its left hinge (pokedex.js's cover()) */
.pdx-cover {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 4; transform-origin: left center; backface-visibility: hidden;
  background:
    linear-gradient(160deg, rgba(255, 255, 255, 0.12), transparent 40%),
    linear-gradient(180deg, var(--shell-hi), var(--shell) 45%, var(--shell-fold));
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset -10px 0 0 rgba(0, 0, 0, 0.12);
}
@media (min-width: 560px) { .pdx-cover { border-radius: 0 0 22px 22px; } }
.pdx-cover-hinge { position: absolute; left: 0; top: 0; bottom: 0; width: 14px; background: repeating-linear-gradient(180deg, var(--shell-hinge) 0 18px, var(--shell-deep) 18px 22px); }
.pdx-cover-mark {
  position: absolute; left: 50%; top: min(30%, 220px); width: 90px; height: 90px; translate: -50% 0; border-radius: 50%;
  border: 6px solid var(--shell-rim); background: radial-gradient(circle, #f2f2f2 0 22%, var(--shell-rim) 23% 30%, transparent 31%), linear-gradient(180deg, #ff6a6a 0 46%, var(--shell-rim) 46% 54%, #f2f2f2 54%);
  box-shadow: 0 4px 0 rgba(0, 0, 0, 0.25);
}
@media (prefers-reduced-motion: reduce) {
  .pdx-mon, .pdx-screen.power-on, .pdx-body .pdx-lcd, .pdx-device.powered .pdx-light, .pdx-device.powered .pdx-lens, .pdx-text.typing::after { animation: none; }
}
.pdx-role, .pdx-screen .index-only, .pdx-caught { position: absolute; top: 8px; font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none; padding: 5px 7px; border-radius: 6px; color: #fff; }
.pdx-role { left: 8px; background: rgba(0, 0, 0, 0.45); }
.pdx-role.role-elite { background: #7a3cb8; }
.pdx-role.role-boss { background: #b8322a; }
.pdx-screen .index-only { right: 8px; }
.pdx-screen .sdx-typechips { position: absolute; top: 8px; right: 8px; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.pdx-screen .sdx-typechips .index-only { position: static; }
.pdx-caught { top: auto; bottom: 8px; right: 8px; background: rgba(0, 0, 0, 0.45); }
.pdx-caught.gold { background: #d8a010; color: #fff8d0; }
.pdx-text.muted { opacity: 0.75; font-style: italic; }
.pdx-text.gold { background: #f2dc8a; font: 0.75rem/1.4 var(--pixel-font); font-synthesis-weight: none; color: #6a4a00; }
.pdx-facts { display: flex; flex-wrap: wrap; gap: 4px 14px; font: 0.75rem/1.5 var(--pixel-font); font-synthesis-weight: none; }
.pdx-facts small { flex-basis: 100%; font: 0.75rem/1.3 var(--font); opacity: 0.7; }
.pdx-moves h4 { margin: 0 0 6px; font: 0.75rem/1.3 var(--pixel-font); font-synthesis-weight: none; }
.pdx-move { display: flex; align-items: baseline; gap: 6px; font-weight: 700; }
.pdx-move-icon { flex: none; width: 1.3em; }
.pdx-move-name { flex: none; }
.pdx-dots { flex: 1; min-width: 12px; border-bottom: 2px dotted rgba(31, 58, 20, 0.45); translate: 0 -4px; }
.pdx-move-num { flex: 0 1 auto; min-width: 0; font-weight: 400; text-align: right; }
.pdx-slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 6px; padding: 8px; border: 3px solid var(--shell-rim); border-radius: 8px; background: #8e1820; }
.pdx-slot {
  position: relative; aspect-ratio: 1; padding: 2px; border: 2px solid #3a0a0e; border-radius: 6px; cursor: pointer;
  background: linear-gradient(180deg, #7ab8ff, #4a88e0); box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.35);
}
.pdx-slot.role-elite { background: linear-gradient(180deg, #b48ae8, #7a4cc0); }
.pdx-slot.role-boss { background: linear-gradient(180deg, #f08a7a, #c0443a); }
.pdx-slot.on { background: #ffe36b; outline: 3px solid #fff; outline-offset: -1px; }
.pdx-slot-mon { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
.pdx-slot.unseen .pdx-slot-mon { filter: brightness(0) opacity(0.5); }
.pdx-slot.caught::after { content: ""; position: absolute; top: 2px; right: 2px; width: 7px; height: 7px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 1px #3a0a0e; }
.pdx-slot.researched::after { background: #ffd23a; }
.pdx-device .dex-perk { margin: 0; border: 3px solid var(--shell-rim); background: #b6d68e; color: #1f3a14; }
.pdx-device .dex-perk.earned { background: #f2dc8a; border-color: var(--shell-rim); }
.pdx-device .dex-perk-text small, .pdx-device .dex-goal-how { color: #3a4a2a; }
.pdx-controls {
  position: sticky; bottom: 0; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 16px max(12px, env(safe-area-inset-bottom)); background: var(--shell-lo); border-top: 3px solid var(--shell-rim);
}
@media (min-width: 560px) { .pdx-controls { border-radius: 0 0 22px 22px; } }
.pdx-round {
  width: 52px; height: 52px; border-radius: 50%; border: 4px solid var(--shell-rim); cursor: pointer; color: #fff; font-size: 1.1rem;
  background: var(--btn-a); box-shadow: 0 4px 0 var(--shell-deep);
}
.pdx-round:active { translate: 0 3px; box-shadow: 0 1px 0 var(--shell-deep); }
.pdx-counter { min-width: 96px; text-align: center; font: 0.75rem/1 var(--pixel-font); font-synthesis-weight: none; }

/* ---------- Settings' Flashing & shake: Reduced (calmFx() in js/prefs.js, html.calm-fx) ----------
   nothing shakes or strobes, and every white-out is one soft fade; the painted scenes do the same in js/scene.js */
.calm-fx :is(.energy-orb.shake, #end-turn-btn.pressed, .energy-orb.refill, #battle-screen.big-hit .arena, #battle-screen.ko-shake .arena, .hof-scene.boom .hof-layout,
  .hof-scene.boom .hof-fx, .hof-scene.party .hof-title, .gate-plate.jolt, .gate-strike.held .card, .gate-strike.full .card,
  .gate-scene.charging .gate-mon, .gate-free.flash img, .descent-scene.shaking .descent-world, .tower-fx.shake .tw-canvas,
  .tower-fx.shake .tw-fx-mon, .gc-pick.won, .gc-pick.flash) { animation: none !important; }
.calm-fx .battle-wipe::before { animation: none !important; }
.calm-fx #battle-screen .hit { animation: calmHit 0.42s; }
@keyframes calmHit { 30% { filter: brightness(1.4); } }
.calm-fx .treasure-flash, .calm-fx #battle-screen.big-hit::after, .calm-fx .title-screen.flash::after { animation: calmFlash 0.5s ease-out forwards; }
.calm-fx :is(.ko-flash, .hof-scene.boom .hof-boom) { animation: calmFlash 0.8s ease-out both; }
.calm-fx .descent-scene.flash .descent-flash { animation: calmFlash 0.7s ease-out; }
.calm-fx .tower-fx.flash .tw-fx-dark { animation: calmFlash 0.5s both; }
.calm-fx .title-screen.leaving::after { animation: calmTitle 1.1s ease-out forwards; }
.calm-fx .gate-scene.white .gate-flash { opacity: 0.3; transition-duration: 0.6s; }
@keyframes calmFlash { from { opacity: 0.2; } to { opacity: 0; } }
@keyframes calmTitle { 0%, 35% { opacity: 0; } 45% { opacity: 0.2; } 100% { opacity: 0; } }

/* ---------- the map inside the Pokédex (the user's call, 2026-10-07) ----------
   The map screen is the device itself, full screen: a window onto the scenery at the top with your Pokémon and HP
   (.mdex-window), a hinge with the lens, lights and the biome on an LCD (.mdex-hinge), the map on the device's screen
   (.mdex-glass, it scrolls in there) and the Bag's pockets as its menu bar (.mdex-dock). The shell round the window is
   the window's own huge shadow, so the scenery shows through the window and nowhere else; every part after it is
   positioned, so it paints over that shadow. A Sky Pillar climb keeps its own look: the wrappers step aside. */
#map-screen:not(.tower) {
  position: fixed; inset: 0; z-index: 1; max-width: none; margin: 0;
  display: flex; flex-direction: column;
  padding: var(--topbar-h) 0 0;
  overflow: hidden;
}
#map-screen.tower .mdex-glass { display: contents; }
#map-screen:not(.tower) .mdex-window {
  position: relative; flex: none; margin: 2px 10px 0; padding: 6px 6px 4px; border-radius: 16px 16px 8px 8px;
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset 0 8px 14px rgba(0, 0, 0, 0.3), 0 0 0 100vmax var(--shell);
}
#map-screen:not(.tower) .run-card { padding: 2px 2px 4px; }
#map-screen .mdex-hinge { position: relative; flex: none; display: flex; align-items: center; gap: 8px; padding: 7px 12px; }
/* the hinge on top, over the LCD, like the Sky Pillar's bar (the user's call, 2026-10-08); flex order also orders the
   painting, so it needs a z-index to paint over the window's shell shadow */
body[data-screen="map-screen"]:has(#map-screen:not(.tower)) { --hinge-h: 44px; }   /* the top bar reads it too */
#map-screen:not(.tower) .mdex-hinge { order: 1; z-index: 1; height: var(--hinge-h); box-sizing: border-box; }
#map-screen:not(.tower) .mdex-window { order: 2; }
#map-screen:not(.tower) .mdex-glass { order: 3; margin-top: 8px; }
#map-screen:not(.tower) .mdex-dock { order: 4; }
.mdex-hinge .pdx-lens { width: 30px; height: 30px; border-width: 3px; }
.mdex-lights { display: flex; gap: 5px; }
.mdex-lights .pdx-light { width: 9px; height: 9px; }
/* the Pokédex shortcut, after the Home key (30px, laid over the hinge at the lights' end): this biome's page at a tap
   (the user's ask, 2026-10-13) */
.map-dex-btn {
  flex: none; margin-left: 38px; height: 28px; padding: 0 10px; cursor: pointer;
  border: 2px solid var(--shell-rim); border-radius: 999px;
  background: linear-gradient(var(--shell-hi), var(--shell) 60%, var(--shell-lo));
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.25), 0 3px 0 var(--shell-deep);
  color: #fff; font: 0.75rem var(--pixel-font); font-synthesis-weight: none; white-space: nowrap;
  text-shadow: 0 1px 0 var(--shell-deep); -webkit-tap-highlight-color: transparent; transition: translate 0.06s, box-shadow 0.06s;
}
.map-dex-btn:active { translate: 0 2px; box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.25), 0 1px 0 var(--shell-deep); }
#map-screen.tower .map-dex-btn { display: none; }
#map-screen .mdex-hinge .map-head {
  flex: 0 1 auto; min-width: 0; display: flex; align-items: center;
  margin: 0 0 0 auto; padding: 5px 10px; border: 3px solid var(--shell-rim); border-radius: 8px;
  background: #b6d68e; box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.12);
}
#map-screen .mdex-hinge :is(.biome-sign, .stage-sign) {
  max-width: 100%; margin: 0; padding: 0; border: 0; background: none; box-shadow: none; text-shadow: none;
  color: #1f3a14; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; animation: none !important;
}
#map-screen .mdex-hinge .biome-sign { font-size: 0.75rem; letter-spacing: 0.04em; }
#map-screen .mdex-hinge .stage-sign { font-size: 0.75rem; opacity: 0.8; }
#map-screen .mdex-hinge .stage-sign::before, #map-screen .mdex-hinge .stage-sign::after { display: none; }
#map-screen .mdex-hinge :is(.biome-sign, .stage-sign).arrive { animation: lcdType 0.6s steps(6) both !important; }
@keyframes lcdType { from { clip-path: inset(0 0 0 100%); } to { clip-path: inset(0); } }
#map-screen:not(.tower) .mdex-glass {
  position: relative; flex: 1; min-height: 0; display: flex; margin: 0 10px; padding: 8px; border-radius: 12px 12px 12px 30px;
  background: #e4e4ea; box-shadow: inset 0 0 0 3px var(--shell-rim), inset 0 -4px 0 rgba(0, 0, 0, 0.14);
}
#map-screen:not(.tower) .map-wrap {
  flex: 1; min-width: 0; padding: 0; overflow: auto; overscroll-behavior: contain; scrollbar-width: none;
  border: 3px solid #2a2a30; border-radius: 6px 6px 6px 22px; background: #1c2440;
}
#map-screen:not(.tower) .map-wrap::-webkit-scrollbar { display: none; }
#map-screen:not(.tower) .map { width: 100%; box-shadow: none; border-radius: 0; }
#map-screen:not(.tower) .map > .map-tools { bottom: 10px; }
#map-screen:not(.tower) .mdex-dock {
  position: relative; flex: none; display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px;
  padding: 10px 10px max(10px, env(safe-area-inset-bottom));
}
.mdex-btn {
  position: relative; display: grid; justify-items: center; gap: 3px; min-width: 0; padding: 7px 0 6px; border: 0; border-radius: 12px;
  background: var(--shell-lo); box-shadow: inset 0 0 0 2px var(--shell-rim), 0 3px 0 var(--shell-deep);
  color: #fff; font: 0.75rem var(--pixel-font); font-synthesis-weight: none; cursor: pointer;
  transition: translate 0.06s, box-shadow 0.06s; -webkit-tap-highlight-color: transparent;
}
.mdex-ico { font-size: 26px; line-height: 0; filter: drop-shadow(0 2px 1px rgba(20, 10, 30, 0.45)); }
.mdex-label { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-shadow: 1px 1px 0 var(--shell-deep); }
.mdex-btn:active, .mdex-btn[aria-current] { translate: 0 2px; box-shadow: inset 0 0 0 2px var(--shell-rim), 0 1px 0 var(--shell-deep); }
.mdex-btn[aria-current] { background: #b6d68e; color: #1f3a14; }
.mdex-btn[aria-current] .mdex-label { text-shadow: none; }
.mdex-count {
  position: absolute; top: -7px; right: 0; min-width: 20px; padding: 2px 4px; border: 2px solid var(--shell-rim); border-radius: 9px;
  background: #1f3a14; color: #d8f0b0; font-size: 0.75rem; font-weight: 400; line-height: 1;
}
.mdex-count:empty { display: none; }
/* the news box and the Bag sit just over the menu bar (the Bag half the screen tall at most, its pocket scrolling: the user found it covering the map, 2026-10-07); the Bag's own tabs are the menu bar there, and the top bar's Bag goes */
body[data-screen="map-screen"] .map-bottom { bottom: calc(max(10px, env(safe-area-inset-bottom)) + 70px); }
body[data-screen="map-screen"] #bag-btn { display: none; }
body[data-screen="map-screen"] .bag:not([hidden]) {
  position: fixed; top: auto; right: auto; left: 50%; bottom: calc(max(10px, env(safe-area-inset-bottom)) + 66px); translate: -50% 0;
  max-height: min(50dvh, calc(100dvh - var(--topbar-h) - max(10px, env(safe-area-inset-bottom)) - 80px)); animation: bagRise 0.18s ease-out;
}
body[data-screen="map-screen"] .bag-pockets { display: none; }
body[data-screen="map-screen"] .bag-head { margin-bottom: 10px; }
@keyframes bagRise { from { transform: translateY(24px); opacity: 0; } }
/* the top of the device is one green LCD (the user's ask, 2026-10-07: like the Center's monitor, but the Pokédex's):
   the top bar's floor and coins and the run card share it, in the LCD's ink, split by a dotted rule. The window grows
   up behind the (transparent, fixed) top bar, so the bar's buttons sit on the screen. */
#map-screen .mdex-window { --lcd: #c2dc9a; --lcd-lo: #a8c97e; --lcd-ink: #1f3a14; --lcd-dim: #5a7a40; }
#map-screen:not(.tower) .mdex-window {
  padding: 7px; border-radius: 18px 18px 10px 10px; background: #e4e4ea;
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset 0 -4px 0 rgba(0, 0, 0, 0.14), 0 0 0 100vmax var(--shell);
}
#map-screen .run-card {
  gap: 16px; padding: 6px 10px 8px; border: 3px solid #2a2a30; border-radius: 8px 8px 8px 22px;
  background:
    repeating-linear-gradient(0deg, rgba(31, 58, 20, 0.05) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(31, 58, 20, 0.05) 0 1px, transparent 1px 3px),
    radial-gradient(120% 140% at 30% 0%, var(--lcd), var(--lcd-lo));
  box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), inset 0 0 18px rgba(31, 58, 20, 0.12);
  color: var(--lcd-ink);
}
#map-screen .run-sprite { filter: drop-shadow(0 3px 0 rgba(31, 58, 20, 0.22)); }
#map-screen .run-mon::before {   /* a shadow pad under your Pokémon, like the Pokédex's entry screens */
  content: ""; position: absolute; left: 10%; right: 10%; bottom: 0; height: 12px; border-radius: 50%; background: rgba(31, 58, 20, 0.16);
}
#map-screen .run-info { text-shadow: none; }
#map-screen .run-info strong { color: var(--lcd-ink); font-weight: 400; }
#map-screen .run-bars .gb-hp-tag { border-color: var(--lcd-ink); background: var(--lcd-ink); color: var(--lcd); box-shadow: none; }
#map-screen .run-bars :is(.gb-hp-track, .gb-exp) { border-color: var(--lcd-ink); background: rgba(255, 255, 255, 0.35); box-shadow: none; }
#map-screen .run-bars .gb-exp-fill { background: #2f6cc8; }
#map-screen .run-foot .gb-hp-num { color: var(--lcd-ink); font-weight: 400; }
#map-screen .run-foot .level-chip { border: 2px solid var(--lcd-ink); background: var(--lcd-ink); color: var(--lcd); }
#map-screen .run-foot .level-chip.replay { background: none; color: var(--lcd-ink); }
#map-screen .run-ability { border-width: 2px; }
/* a battle status box (the user's ask, 2026-10-08: the card was untidy): your Pokémon in the LCD's own four greens on
   the left, then name | Level, the HP bar, Ability | HP numbers, every row the same width; the run's ₽ are the top bar's */
.svg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
#map-screen:not(.tower) .run-card { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 0 12px; }
/* the greens go on each moving piece, not the button: iOS Safari drops a parent's SVG filter for a few frames while its
   children animate, flashing them in full colour */
#map-screen:not(.tower) .run-mon { width: 84px; height: 84px; margin: -6px -4px -8px 0; translate: 0 -10px; }
#map-screen:not(.tower) .run-sprite { width: 84px; height: 84px; filter: url(#lcd-ink); }
#map-screen:not(.tower) .run-ball { filter: none; }
#map-screen:not(.tower) :is(.cball-top, .cball-bottom, .cball-light) { filter: url(#lcd-ink); }
#map-screen:not(.tower) .run-mon[data-state="recalling"] .run-sprite { animation-name: monRecallInk; }
#map-screen:not(.tower) .run-mon[data-state="releasing"] .run-sprite { animation-name: monReleaseInk; }
#map-screen:not(.tower) .run-sprite[data-blaze] { animation: blazeAuraInk 0.5s steps(1) infinite; }
@keyframes monRecallInk {
  0% { transform: none; filter: url(#lcd-ink); }
  15%, 100% { filter: brightness(0.45) url(#lcd-ink); }
  100% { transform: scale(0.1); opacity: 0; }
}
@keyframes monReleaseInk {
  0%, 60% { filter: brightness(0) invert(1) url(#lcd-ink); }
  0% { transform: scale(0.2); }
  60% { transform: scale(1.12); }
  100% { transform: none; filter: url(#lcd-ink); }
}
@keyframes blazeAuraInk { 0% { filter: url(#lcd-ink); } 50% { filter: drop-shadow(0 0 3px #000) url(#lcd-ink); } }
@media (prefers-reduced-motion: reduce) { #map-screen:not(.tower) .run-sprite[data-blaze] { animation: none; } }
#map-screen:not(.tower) .run-info {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "name name lv" "bar bar bar" "ab ct hp";
  align-items: center; gap: 5px 8px; width: auto;
}
#map-screen:not(.tower) .run-foot { display: contents; }
#map-screen:not(.tower) .run-name { grid-area: name; justify-content: flex-start; }
#map-screen:not(.tower) .run-name::before { display: none; }
#map-screen:not(.tower) .run-name strong { font-size: 1rem; letter-spacing: 0.04em; }
#map-screen:not(.tower) #run-level { grid-area: lv; justify-self: end; }
#map-screen:not(.tower) #run-level[hidden] { display: none; }
#map-screen:not(.tower) .run-bars { grid-area: bar; width: 100%; }
#map-screen:not(.tower) .run-ability { grid-area: ab; justify-self: start; margin: 0; }
#map-screen:not(.tower) .run-foot .gb-hp-num { grid-area: hp; justify-self: end; font-size: 0.85rem; }
/* a Safari run's catches so far, beside the Ability (the user's ask, 2026-10-20: the daily run never said how many) */
#map-screen:not(.tower) .run-caught { grid-area: ct; justify-self: start; }
.run-caught { display: inline-flex; align-items: center; gap: 4px; font-size: 0.75rem; padding: 1px 8px 1px 4px; cursor: help;
  border: 2px solid var(--lcd-ink, #1f3a14); background: none; color: var(--lcd-ink, #1f3a14); }
.run-caught[hidden] { display: none; }
.run-caught img { width: 16px; height: 16px; image-rendering: pixelated; }
.run-caught.bump { animation: caughtBump 0.5s ease-out; }
@keyframes caughtBump { 40% { transform: scale(1.25); } }
@media (prefers-reduced-motion: reduce) { .run-caught.bump { animation: none; } }
#map-screen:not(.tower) .run-money { display: none; }
@media (max-width: 720px) { #map-screen:not(.tower) { padding-top: 6px; } }
/* the top bar's floor and coins sit on the run card's LCD at every width (the user's ask, 2026-10-12: on the iPad they
   floated in the screen's corners, off the handheld) */
@media all {
  #map-screen:not(.tower) .run-card {
    padding-top: calc(var(--topbar-h) - 2px);
    background-image:
      radial-gradient(circle, rgba(31, 58, 20, 0.35) 1px, transparent 1.5px),
      repeating-linear-gradient(0deg, rgba(31, 58, 20, 0.05) 0 1px, transparent 1px 3px),
      repeating-linear-gradient(90deg, rgba(31, 58, 20, 0.05) 0 1px, transparent 1px 3px),
      radial-gradient(120% 140% at 30% 0%, var(--lcd), var(--lcd-lo));
    background-size: 6px 6px, auto, auto, auto;
    background-position: 2px calc(var(--topbar-h) - 9px), 0 0, 0 0, 0 0;
    background-repeat: repeat-x, repeat, repeat, no-repeat;
  }
  /* margin, not translate: a transform would make the top bar the containing block of the Bag (fixed, inside it) */
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .topbar { margin-top: calc(16px + var(--hinge-h, 0px)); height: calc(var(--topbar-h) - 12px); padding: 0 24px 0 22px; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .topbar::before { display: none; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .dex-sprite { width: 32px; height: 32px; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .home-dex { filter: drop-shadow(0 2px 0 rgba(31, 58, 20, 0.25)); }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) :is(.floor-tag, .coin-pill) { color: #1f3a14; text-shadow: none; filter: none; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .floor-tag b { font-size: 1.15rem; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .floor-stairs { filter: none; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .floor-stairs i { width: 16px; height: 16px; background: #1f3a14; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .coin-pill { font-size: 1.1rem; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .shop-btn { filter: drop-shadow(0 2px 0 rgba(31, 58, 20, 0.25)); }
}
/* the Sky Pillar's climb has the same device, only as a slim menu bar along the bottom (the user's calls, 2026-10-07: you
   climb up, so the screen's top is for the tower; and only the Pokédex, floor, HP, Deck, Relics, Items and Main menu,
   kept short): one LCD strip with the top bar's Pokédex and floor laid on its left and the HP bar, then a row of icons.
   js/tower.js measures it (--tw-lcd-x/y/h, --tw-bar-h) to lay the top bar on the LCD and stand the floor just above it. */
#map-screen.tower {
  position: fixed; inset: 0; z-index: 1; max-width: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; justify-content: flex-end; align-items: center; overflow: hidden;
}
#map-screen.tower :is(.mdex-window, .mdex-dock) { position: relative; z-index: 2; width: min(100%, 520px); background: var(--shell); }
#map-screen.tower .mdex-window {
  order: 2; padding: 4px 10px 6px;
  box-shadow: inset 3px 0 0 var(--shell-rim), inset -3px 0 0 var(--shell-rim);
}
#map-screen.tower .run-card {
  justify-content: stretch; gap: 0; min-height: 40px; margin: 3px; padding: 4px 10px 4px 104px; border-width: 2px; border-radius: 6px;
  box-shadow: inset 0 2px 0 rgba(31, 58, 20, 0.14), inset 0 0 12px rgba(31, 58, 20, 0.12), 0 0 0 3px #e4e4ea, 0 0 0 5px var(--shell-rim);
}
#map-screen.tower :is(.run-mon, .run-name, .run-ability, #run-level, .run-bars .gb-exp) { display: none; }
#map-screen.tower .run-info { flex: 1; flex-direction: row; align-items: center; gap: 8px; width: auto; }
#map-screen.tower .run-bars { flex: 1; width: auto; margin: 0; }
#map-screen.tower .run-foot { width: auto; }
#map-screen.tower .run-foot .gb-hp-num { font-size: 0.75rem; white-space: nowrap; }
/* the climb's ₽ (it starts at 0, unlike the PokéCoin savings) sit at the LCD's right end, past the HP */
.room-cash.run-money { display: none; }   /* .room-cash below would show it on every map; only a climb has no top bar ₽ */
#map-screen.tower .run-money { display: flex; margin-left: 4px; padding-left: 8px; border-left: 2px dashed rgba(31, 58, 20, 0.35); font-size: 0.75rem; color: #1f3a14; }
#map-screen.tower .run-money .smooth-icon { width: 14px; height: 14px; }
/* the hinge on top of the bar, over the LCD: lens, lights and "Sky Pillar / Floors 1-10" on its own LCD (the user's calls,
   2026-10-08: the stone plate over the tower went, the title sits on the bar like every map's; then it moved above the LCD) */
#map-screen.tower .mdex-hinge {
  order: 1; z-index: 2; width: min(100%, 520px); padding: 8px 14px 2px; background: var(--shell); border-radius: 16px 16px 0 0;
  box-shadow: inset 0 3px 0 var(--shell-hi), inset 0 0 0 3px var(--shell-rim), 0 -4px 14px rgba(0, 0, 0, 0.4);
}
#map-screen.tower .mdex-hinge .pdx-lens { width: 24px; height: 24px; }
#map-screen.tower .mdex-hinge .map-head { padding: 3px 10px; }
#map-screen.tower .mdex-dock {
  order: 3; display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; padding: 2px 12px max(8px, env(safe-area-inset-bottom));
  box-shadow: inset 3px 0 0 var(--shell-rim), inset -3px 0 0 var(--shell-rim);
}
#map-screen.tower .mdex-btn { padding: 5px 0; border-radius: 10px; }
#map-screen.tower .mdex-ico { font-size: 20px; }
#map-screen.tower :is(.mdex-label, .mdex-btn[data-pocket="key"], .mdex-btn[data-pocket="trainer"]) { display: none; }
#map-screen.tower .mdex-count { top: -5px; right: 4px; min-width: 16px; padding: 1px 3px; font-size: 0.75rem; }
.mdex-btn:is(.mdex-menu, .mdex-aug) { display: none; }
#map-screen.tower .mdex-btn:is(.mdex-menu, .mdex-aug) { display: grid; }
body[data-screen="map-screen"]:has(#map-screen.tower) .topbar {
  position: fixed; left: calc(var(--tw-lcd-x, 20px) + 6px); right: auto; top: var(--tw-lcd-y, 80vh); width: auto;
  height: var(--tw-lcd-h, 40px); padding: 0; gap: 8px; justify-content: flex-start;
}
body[data-screen="map-screen"]:has(#map-screen.tower) .topbar::before { display: none; }
body[data-screen="map-screen"]:has(#map-screen.tower) :is(.coin-pill, .shop-btn) { display: none; }
body[data-screen="map-screen"]:has(#map-screen.tower) .dex-sprite { width: 26px; height: 26px; }
body[data-screen="map-screen"]:has(#map-screen.tower) .home-dex { filter: drop-shadow(0 2px 0 rgba(31, 58, 20, 0.25)); }
body[data-screen="map-screen"]:has(#map-screen.tower) .floor-tag { color: #1f3a14; text-shadow: none; filter: none; }
body[data-screen="map-screen"]:has(#map-screen.tower) .floor-tag b { font-size: 0.95rem; }
body[data-screen="map-screen"]:has(#map-screen.tower) .floor-stairs { filter: none; }
body[data-screen="map-screen"]:has(#map-screen.tower) .floor-stairs i { width: 13px; height: 13px; background: #1f3a14; }
body[data-screen="map-screen"]:has(#map-screen.tower) :is(.map-bottom, .bag:not([hidden])) { bottom: calc(var(--tw-bar-h, 120px) + 8px); }
/* a climb's first look: the bar and the top bar on its LCD slide up from below (popBar() in js/tower.js, BAR_IN) */
#map-screen.tower.bar-in :is(.mdex-window, .mdex-hinge, .mdex-dock),
body[data-screen="map-screen"]:has(#map-screen.tower.bar-in) .topbar { animation: twBarIn 0.48s cubic-bezier(0.2, 0.9, 0.3, 1.1) both; }
@keyframes twBarIn { from { translate: 0 calc(var(--tw-bar-h, 140px) + 30px); } to { translate: 0 0; } }
/* an augment pick over the climb (showChoice()'s `over`): no title, no text box, no backdrop, just the tiles and the
   reroll floating over the tower above the bar */
#reward-screen.over-map {
  position: fixed; left: 0; right: 0; top: 0; bottom: var(--tw-bar-h, 140px); z-index: 3; max-width: none; margin: 0;
  justify-content: center; padding: 16px 12px; animation: biIn 0.3s both;
}
#reward-screen.over-map :is(.reward-title, .reward-coins, .reward-bottom) { display: none; }
/* wider than a phone (an iPad, a PC) the device is a handheld standing in the middle of the scenery, which fills the
   rest of the screen, like the Collection's Pokédex over the Clearing (the user's ask, 2026-10-12: a stretched map
   device wasted the iPad's screen, a phone-shaped frame round the whole game shrank the worlds with it) */
@media (min-width: 721px) {
  body[data-screen="map-screen"] { --mdex-gap: max(0px, (100dvh - 28px - 940px) / 2); }   /* centres it on a tall screen */
  #map-screen:not(.tower) {
    inset: calc(14px + var(--mdex-gap)) auto calc(14px + var(--mdex-gap)) 50%; width: min(500px, calc(100vw - 32px));
    translate: -50% 0; padding-top: 12px; border-radius: 26px; box-shadow: 0 18px 50px rgba(10, 20, 60, 0.45);
  }
  #map-screen:not(.tower) .mdex-window, #map-screen:not(.tower) .mdex-glass { margin-inline: 14px; }
  #map-screen:not(.tower) .mdex-dock { padding-inline: 14px; padding-bottom: 12px; }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .map-bottom { bottom: calc(100px + var(--mdex-gap)); }
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .bag:not([hidden]) { bottom: calc(96px + var(--mdex-gap)); max-height: min(50dvh, calc(100dvh - var(--topbar-h) - 120px)); }
  /* the top bar laid on the handheld's run card, as on a phone (the window's 14px inset, its rim and padding) */
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .topbar {
    width: calc(min(500px, 100vw - 32px) - 8px); margin: calc(36px + var(--mdex-gap) + var(--hinge-h, 0px)) auto 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  #map-screen .mdex-hinge :is(.biome-sign, .stage-sign).arrive { animation: none !important; }
  .bag:not([hidden]) { animation: none !important; }
}

/* ---------- the Bag, redone as a piece of the Pokédex (the user's call, 2026-10-07) ----------
   The device's shell round it, the pocket's name on the green LCD between blinking arrows, the pockets as the shell's
   buttons (pressed in and lit green when open) and each pocket on a cream screen in a grey bezel, its rows as cards. */
.drop.bag {
  padding: 10px; border: 0; border-radius: 20px;
  background: linear-gradient(180deg, var(--shell-hi), var(--shell) 40%, var(--shell-lo));
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset 6px 0 0 rgba(255, 255, 255, 0.08), 0 16px 40px rgba(0, 0, 0, 0.55);
}
.bag .bag-head { flex: none; border: 3px solid var(--shell-rim); border-radius: 8px; background: #b6d68e; box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.12); }
.bag .bag-head strong { color: #1f3a14; font-size: 0.8rem; }
.bag .bag-flip { color: #1f3a14; }
.bag .bag-flip:hover { color: #3a6a20; }
.bag .bag-pockets { flex: none; gap: 8px; margin: 10px 0 12px; }
.bag .bag-pocket {
  width: 52px; height: 46px; border: 0; border-radius: 12px; font-size: 26px;
  background: var(--shell-lo); box-shadow: inset 0 0 0 2px var(--shell-rim), 0 3px 0 var(--shell-deep);
}
.bag .bag-pocket > span { line-height: 0; filter: drop-shadow(0 2px 1px rgba(20, 10, 30, 0.45)); }
.bag .bag-pocket[aria-selected="true"] { background: #b6d68e; transform: translateY(2px); box-shadow: inset 0 0 0 2px var(--shell-rim), 0 1px 0 var(--shell-deep); }
.bag .bag-pocket[aria-selected="true"]::after { display: none; }
.bag .bag-pocket b { right: -8px; top: -8px; border-color: var(--shell-rim); border-radius: 10px; background: #1f3a14; color: #d8f0b0; }
/* each pocket is the Pokédex's green LCD (UI fixes D, 2026-10-07: the cream screen was the last of the old windows on
   the map), its rows lighter LCD tiles in the screen's ink, its buttons LCD keys */
:is(.bag .bag-pocket-body, .dev-window .dev-screen) {
  --ink: #1f3a14; --muted: #3a5a28; --panel: #d6e8b8; --panel-edge: #1f3a14;
  border: 3px solid #2a2a30; border-radius: 6px 6px 6px 18px; color: #1f3a14;
  background: radial-gradient(circle, rgba(31, 58, 20, 0.1) 1px, transparent 1.5px) 0 0 / 8px 8px, #a8c884;
  box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), 0 0 0 6px #e4e4ea, 0 0 0 9px var(--shell-rim);
}
.bag .bag-pocket-body { margin: 6px; padding: 10px 8px; }
.bag .howto-list { gap: 6px; }
.bag .howto-li { background: #e4f0cc; border: 2px solid #1f3a14; border-radius: 10px; box-shadow: 0 2px 0 rgba(31, 58, 20, 0.3); }
.bag .howto-li:last-child { border-bottom: 2px solid #1f3a14; }
.bag :is(.howto-li-text small, .drop-note, .drop-empty) { color: #3a5a28; }
:is(.bag .bag-pocket-body, .dev-window) .btn {
  border: 2px solid #1f3a14; border-radius: 999px; background: #d6e8b8; color: #1f3a14; box-shadow: 0 3px 0 #1f3a14;
}
:is(.bag .bag-pocket-body, .dev-window) .btn:hover:not(:disabled) { background: #e4f0cc; }
:is(.bag .bag-pocket-body, .dev-window) .btn:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 1px 0 #1f3a14; }
.bag .item-actions .btn { box-shadow: 0 2px 0 #1f3a14; }

/* the deck and map-peek windows are the device too (.dev-window): the Bag's shell, the title on its LCD, the filter and
   sort as the Moves app's keys, the cards or map on the green screen, Close a shell key */
.dialog.dev-window {
  padding: 10px 10px 12px; border: 0; border-radius: 20px; color: #1f3a14;
  background: linear-gradient(180deg, var(--shell-hi), var(--shell) 40%, var(--shell-lo));
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset 6px 0 0 rgba(255, 255, 255, 0.08), 0 20px 60px rgba(0, 0, 0, 0.55);
}
.dev-window h2 {
  margin: 0 0 10px; padding: 8px 12px; border: 3px solid var(--shell-rim); border-radius: 8px; background: #b6d68e;
  box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.12); color: #1f3a14; font-size: 0.8rem; letter-spacing: 0.1em; text-align: center; text-transform: uppercase;
}
.dev-window h2 .count { color: #3a5a28; }
.dev-window .deck-tools { margin: 0 0 14px; }
.dev-window .deck-seg { border: 2px solid var(--shell-rim); border-radius: 6px; background: #d6e8b8; box-shadow: 0 3px 0 var(--shell-deep); }
.dev-window .deck-seg button { border-left: 2px solid #1f3a14; background: none; color: #1f3a14; }
.dev-window .deck-seg button:first-child { border-left: 0; }
.dev-window .deck-seg button:hover { background: #e4f0cc; }
.dev-window .deck-seg button[aria-pressed="true"] { background: #1f3a14; color: #c4dca0; text-shadow: none; }
.dev-window .dev-screen { margin: 6px; padding: 12px 8px; }
.dev-window .dev-screen:empty { display: none; }
.dev-window .deck-empty { color: #fff; text-shadow: 1px 1px 0 var(--shell-deep); }
.dev-window .dialog-actions { margin-top: 16px; }
.dev-window::-webkit-scrollbar-track { background: var(--shell-lo); box-shadow: inset 0 0 0 2px var(--shell-rim); }
.bag .bag-pocket-body::-webkit-scrollbar-track { background: #94b870; box-shadow: none; }
@supports not selector(::-webkit-scrollbar) {
  .dev-window { scrollbar-color: #e4e4ea var(--shell-lo); }
  .bag .bag-pocket-body { scrollbar-color: #1f3a14 #94b870; }
}
.dev-window .dialog-actions .btn {
  border: 0; background: var(--shell-lo); color: #fff; text-shadow: 1px 1px 0 var(--shell-deep);
  box-shadow: inset 0 0 0 2px var(--shell-rim), 0 3px 0 var(--shell-deep);
}
.dev-window .dialog-actions .btn:hover:not(:disabled) { background: var(--shell); }
.dev-window .dialog-actions .btn:active:not(:disabled) { box-shadow: inset 0 0 0 2px var(--shell-rim), 0 1px 0 var(--shell-deep); }
/* beside another key, the one to press is a light LCD key */
.dev-window .dialog-actions .btn:not(.secondary):not(:only-child) {
  background: #d6e8b8; color: #1f3a14; text-shadow: none; box-shadow: inset 0 0 0 2px #1f3a14, 0 3px 0 var(--shell-deep);
}
.dev-window .dialog-actions .btn:not(.secondary):not(:only-child):hover:not(:disabled) { background: #e4f0cc; }

/* the run's end windows on the device too (UI fixes D2, 2026-10-07): the result, unlock, yes/no and loss recap windows
   were cream over a map and device that no longer are */
.dev-window.result h2 { font-size: 0.95rem; }
.dev-window .dev-screen > p { margin: 0 0 8px; text-align: center; }
.dev-window .dev-screen > p:last-child { margin-bottom: 0; }
.dev-window .unlocks { margin: 0; }
.dev-window .unlocks li {
  margin: 6px 0 0; background: #e4f0cc; border: 2px solid #1f3a14; border-radius: 8px; box-shadow: 0 2px 0 rgba(31, 58, 20, 0.3); font-size: 0.75rem; line-height: 1.5;
}
.dev-window .unlocks .gate-line { background: #e4daf8; border-color: #3a2a68; color: #2a1a50; }
.dev-window .gate-hp { color: #3a2a68; }
.dev-window .result-badge-btn:hover, .dev-window .result-badge-btn:focus-visible { color: #6a4a00; }

#confirm-dialog .dev-screen { margin: 4px; padding: 16px 12px; }
#confirm-dialog #confirm-text { font-size: 0.8rem; line-height: 1.6; }

.unlock-dialog.dev-window .unlock-kicker { margin: 0 0 10px; border-color: var(--shell-rim); }
.unlock-dialog.dev-window .unlock-stage {
  margin: 0 6px; border: 4px solid #2a2a30; border-radius: 10px; box-shadow: 0 0 0 3px var(--shell-rim), inset 0 0 0 2px rgba(255, 255, 255, 0.35);
  background:
    radial-gradient(ellipse 26% 7% at 50% 92%, rgba(24, 16, 16, 0.3) 0 98%, transparent),
    radial-gradient(circle at 50% 60%, #fff6d0 0 34%, transparent 35%),
    radial-gradient(circle, rgba(255, 255, 255, 0.22) 1px, transparent 1.5px) 0 0 / 10px 10px,
    linear-gradient(150deg, #5cbcff, #1d58b8);
}
.unlock-dialog.dev-window .dev-screen { margin: 12px 6px 6px; padding: 10px 10px 12px; }
.unlock-dialog.dev-window #unlock-name {
  margin: 0 0 6px; padding: 0; border: 0; background: none; box-shadow: none; color: #1f3a14; font-size: 1.1rem; letter-spacing: 0; text-transform: none;
}
.unlock-dialog.dev-window .unlock-hint { color: #3a5a28; }

.loss-dialog.dev-window .records-sub { margin: 0 0 10px; color: #fff; text-align: center; font-size: 0.75rem; text-shadow: 1px 1px 0 var(--shell-deep); }
.loss-dialog .bdx-sheet { --rim: var(--shell-rim); --lcd: #b6d68e; --ink: #1f3a14; color: var(--ink); }
.loss-dialog .bdx-sheet > * + * { margin-top: 0; }
.loss-dialog .records-close .btn {
  border: 0; background: var(--shell-lo); color: #fff; text-shadow: 1px 1px 0 var(--shell-deep);
  box-shadow: inset 0 0 0 2px var(--shell-rim), 0 3px 0 var(--shell-deep);
}

/* the rest of the windows on the device (D2 group 3, 2026-10-07): the battle's piles (the deck window's twin, its tabs
   the deck's keys), patch notes, About, How to play and the cloud save pair; their text on the green screen, a light LCD
   tile for anything that stood out on the cream */
.dev-window .deck-seg button[aria-selected="true"] { background: #1f3a14; color: #c4dca0; text-shadow: none; }
.pile-tab-icon { margin-right: 5px; }
.piles-dialog .deck-tools { justify-content: center; }
.piles-dialog .deck-empty { margin: 0 0 10px; font-size: 0.75rem; }
.dev-window .dev-screen a { color: #1f3a14; text-decoration-thickness: 2px; }
.dev-window .dev-screen a:hover { color: #3a6a20; }
.dev-window .dev-screen .hint { color: #3a5a28; }
.dev-window .dev-screen :is(.disclaimer, .panel) {
  background: #e4f0cc; border: 2px solid #1f3a14; border-radius: 8px; box-shadow: 0 2px 0 rgba(31, 58, 20, 0.3); color: #1f3a14;
}
.about-dialog .dev-screen { font-size: 0.85rem; line-height: 1.6; }
.about-dialog .dev-screen > p { text-align: left; }
.about-dialog .disclaimer { font-size: 0.75rem; }
.about-dialog .credits { margin: 12px 0 0; }

.patch-dialog.dev-window { padding-bottom: 12px; }
.patch-dialog .patch-body { margin: 6px; padding: 12px 10px; }
.patch-dialog :is(.records-label, .patch-head) { color: #1f3a14; }
.patch-dialog .patch-title { color: #6a4a00; }
.patch-dialog .patch-date { color: #3a5a28; }
.patch-dialog .dialog-actions { flex: none; justify-content: center; margin-top: 14px; }

.cloud-dialog .dev-screen > div > p:not(.hint) { text-align: center; }
.cloud-dialog .cloud-email input { border: 2px solid #1f3a14; background: #e4f0cc; color: #1f3a14; }
.cloud-dialog .cloud-email input::placeholder { color: #5a7a48; }
.cloud-dialog .cloud-email input:focus { outline-color: #1f3a14; }
.cloud-pick-dialog .cloud-save h3 { color: #1f3a14; }
.cloud-pick-dialog .dev-screen > p { text-align: center; }

/* rewards and the Mart on the device too (UI fixes D2 group 2, 2026-10-07): the screen's title, its text box, the
   picked card's note, the relic / item / choice tiles and the hand picker's banner are each a green LCD in a ring of the
   device's shell. The scenes' text boxes (evolution, Hall of Fame, films) keep the classic window. */
:is(.reward-title, :where(#reward-screen, .map-bottom) .reward-log, .focus-note, .relic, .pick-banner) {
  border: 3px solid #2a2a30; border-radius: 8px; color: #1f3a14;
  background: radial-gradient(circle, rgba(31, 58, 20, 0.1) 1px, transparent 1.5px) 0 0 / 8px 8px, #a8c884;
  box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), 0 0 0 5px var(--shell), 0 0 0 8px var(--shell-rim), 3px 5px 0 8px rgba(0, 0, 0, 0.35);
}
/* except over a scene (the rooms, a fight's rewards, a found item): the words there are the game talking, so they keep
   the classic cream speech window (the user's calls, 2026-10-07 and 2026-10-08); green stays the device's own readouts
   (the hinge, the HP LCD, the deck pickers) and the choice signs, which are buttons */
#reward-screen.in-room .reward-log {
  border: 3px solid #b8b8c8; border-radius: var(--round); background: var(--win-bg); color: var(--win-ink);
  box-shadow: 0 0 0 2px #303038, inset 0 0 0 2px #303038, 3px 3px 0 2px rgba(0, 0, 0, 0.4);
}
.reward-title { letter-spacing: 0.04em; }
.focus-note { box-shadow: inset 0 2px 0 rgba(31, 58, 20, 0.14), 0 0 0 3px var(--shell), 0 0 0 5px var(--shell-rim), 2px 3px 0 5px rgba(0, 0, 0, 0.35); }
.reward-bottom { gap: 18px; }
:where(#reward-screen, .map-bottom) .reward-log.more::after { color: #1f3a14; }
#reward-screen.in-room .reward-log.more::after { color: #c02020; }
/* who is speaking (speaker() in js/rewards.js: a Gym Leader), on a tilted tag over the box like the Poké Mall's shopkeepers */
#reward-screen .reward-log[data-who] { margin-top: 12px; padding-top: 16px; }
#reward-screen .reward-log[data-who]::before {
  content: attr(data-who);
  position: absolute; left: 14px; top: -16px; max-width: calc(100% - 28px);
  padding: 4px 12px; border-radius: 999px; background: #f0a0b0; color: #6a2a3a; box-shadow: 0 2px 0 #c87888;
  font-size: 0.75rem; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; rotate: -3deg;
}
.relic .relic-text, .relic .relic-term { color: #3a5a28; }
.relic .relic-term { background: #d6e8b8; border-left-color: #1f3a14; }
.relic.item-tile { border-color: #1d58b8; }
.reward-option.picked > .relic { outline-offset: 10px; }
.reward-options:has(> .reward-option > .relic) { gap: 30px; }
@media (max-width: 720px) { .reward-options:has(> .reward-option > .relic) { gap: 22px; } }
.pick-banner { border-color: var(--pick); }
.pick-banner .pick-line { color: #3a5a28; }

/* the deck pickers (Forget a move, PP Up, Day Care: showChoice()'s 'deck-pick') are the device (the user's call,
   2026-10-07): its shell under the top bar, the title an LCD, the deck on a dark screen that scrolls inside the glass,
   the text box and the button kept on the shell under it, so nothing slides under the top bar or covers a card */
#reward-screen:has(> .deck-pick) {
  position: fixed; inset: 0; z-index: 1; max-width: none; margin: 0; gap: 10px;
  padding: max(10px, env(safe-area-inset-top)) 10px max(10px, env(safe-area-inset-bottom)); overflow: hidden; border-radius: 0;
  background: linear-gradient(180deg, var(--shell-hi), var(--shell) 30%, var(--shell-lo));
  box-shadow: inset 0 0 0 3px var(--shell-rim), inset 6px 0 0 rgba(255, 255, 255, 0.08);
}
#reward-screen:has(> .deck-pick) .reward-title {
  flex: none; align-self: stretch; padding: 8px 12px; border-color: var(--shell-rim); background: #b6d68e;
  box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.12); font-size: 1rem;
}
.reward-options.deck-pick {
  flex: 1; min-height: 0; align-self: stretch; width: auto; padding: 8px; border-radius: 12px 12px 12px 30px;
  background: #e4e4ea; box-shadow: inset 0 0 0 3px var(--shell-rim), inset 0 -4px 0 rgba(0, 0, 0, 0.14);
}
.deck-pick-screen {
  flex: 1; min-width: 0; height: 100%; overflow-y: auto; overscroll-behavior: contain; padding: 20px 12px 16px; border: 3px solid #2a2a30;
  border-radius: 6px 6px 6px 22px; background: #1c2440; scrollbar-width: thin; scrollbar-color: #e4e4ea #1c2440;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(104px, 28vw), 1fr)); align-content: start; gap: 22px 12px;
}
.deck-pick-screen > .reward-option { width: 100%; max-width: 180px; justify-self: center; }
/* a duo's two decks (rule 5): each partner's cards under its name, across the screen's whole grid */
.deck-pick-screen > .choice-group { grid-column: 1 / -1; display: grid; grid-template-columns: inherit; gap: inherit; }
.deck-pick-screen > .choice-group > .reward-option { width: 100%; max-width: 180px; justify-self: center; }
.choice-group-head {
  grid-column: 1 / -1; padding: 6px 10px; border-radius: 6px; background: #2c3866; color: #fff;
  font-family: var(--pixel-font); font-size: 0.85rem; text-shadow: 1px 1px 0 #10142a;
}
.choice-group + .choice-group { margin-top: 10px; }
/* who takes a Neutral move (whoTakes() in js/run.js): the two partners side by side */
.reward-options.duo-takes { display: flex; justify-content: center; gap: 14px; flex-wrap: wrap; }
.duo-take {
  --c1: #9aa0b4; --c2: #4a4e60;
  display: grid; justify-items: center; gap: 4px; width: 132px; padding: 10px 8px; border-radius: 12px;
  background: radial-gradient(circle at 50% 30%, var(--c1), var(--c2)); color: #fff; font-family: var(--pixel-font);
  font-size: 0.8rem; text-shadow: 1px 1px 0 #181820;
}
.duo-take[data-type="fire"]  { --c1: #ff8f4d; --c2: #b8321a; }
.duo-take[data-type="grass"] { --c1: #72dc70; --c2: #257a38; }
.duo-take[data-type="water"] { --c1: #5cbcff; --c2: #1d58b8; }
.duo-take[data-type="electric"] { --c1: #ffe066; --c2: #b88a00; }
.duo-take[data-type="ice"] { --c1: #a8ecff; --c2: #2a8cb8; }
.duo-take[data-type="fighting"] { --c1: #f49a70; --c2: #a03420; }
.duo-take[data-type="ground"] { --c1: #e8c878; --c2: #8a6430; }
.duo-take[data-type="flying"] { --c1: #c8c0ff; --c2: #5a50b0; }
.duo-take[data-type="dark"] { --c1: #a8907c; --c2: #3e2e26; }
.duo-take-face { width: 72px; height: 72px; object-fit: contain; }
#reward-screen:has(> .deck-pick) .reward-bottom { order: 1; position: static; flex: none; margin: 0; align-self: center; }
#reward-screen:has(> .deck-pick) .reward-log { box-shadow: inset 0 3px 0 rgba(31, 58, 20, 0.14), 0 0 0 3px var(--shell-rim); border-color: var(--shell-rim); }
#reward-screen:has(> .deck-pick) .reward-actions { order: 2; margin: 0; }
/* its buttons are the yes/no window's keys side by side (the user's call, 2026-10-08): the confirm (Upgrade, Forget...)
   a gold key on the left like the room bar's, greyed until a card is picked, then glowing; Skip a shell key on the right */
#reward-screen.deck-picking .reward-actions { align-self: stretch; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 0 4px; }
#reward-screen.deck-picking .reward-actions > .ds-btn {
  min-width: 0; padding: 0; border-radius: 999px; background: var(--shell-lo);
  box-shadow: inset 0 0 0 2px var(--shell-rim), 0 3px 0 var(--shell-deep); transition: translate 0.06s, filter 0.2s, opacity 0.2s;
}
#reward-screen.deck-picking .reward-actions > .ds-btn[hidden] { display: none; }
#reward-screen.deck-picking .reward-actions .pp-pill {
  display: block; padding: 12px 10px 11px; border: 0; background: none; box-shadow: none; color: #fff; font-size: 0.85rem;
  text-align: center; text-shadow: 1px 1px 0 var(--shell-deep); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#reward-screen.deck-picking .reward-actions .pp-pill::before { content: none; }
#reward-screen.deck-picking .reward-actions > .ds-btn:active:not(:disabled) { transform: none; translate: 0 2px; box-shadow: inset 0 0 0 2px var(--shell-rim), 0 1px 0 var(--shell-deep); }
#reward-screen.deck-picking #reward-ok {
  background: linear-gradient(#fff3a0, #f8d030 45%, #e0a818);
  box-shadow: inset 0 0 0 2px #5a3a08, inset 0 3px 0 rgba(255, 255, 255, 0.6), 0 3px 0 #5a3a08, 0 0 8px 2px rgba(255, 216, 64, 0.55); animation: deckOkPulse 1.1s ease-in-out infinite; }
#reward-screen.deck-picking #reward-ok .pp-pill { color: #3a2400; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6); }
#reward-screen.deck-picking #reward-ok:disabled { opacity: 0.45; filter: grayscale(1); cursor: default; animation: none; }
@keyframes deckOkPulse {
  50% {
    filter: brightness(1.12);
    box-shadow: inset 0 0 0 2px #5a3a08, inset 0 3px 0 rgba(255, 255, 255, 0.6), 0 3px 0 #5a3a08, 0 0 18px 7px rgba(255, 224, 80, 0.85), 0 0 0 4px rgba(255, 240, 160, 0.5);
  }
}
@media (prefers-reduced-motion: reduce) { #reward-screen.deck-picking #reward-ok { animation: none; } }
/* the picked card blown up above it: the dim stops at the text box (rewards.js openFocus() sets its bottom) */
.card-focus.reward-focus.over-pick { padding-bottom: 8px; overflow-y: auto; }
/* wider than a phone the pickers and every device window are the run map's handheld, 500px wide and 940px tall at
   most, centred in the scenery (the user's ask, 2026-10-12: the 900px deck and PP Up windows filled the iPad) */
@media (min-width: 721px) {
  #reward-screen:has(> .deck-pick) {
    inset: max(14px, (100dvh - 940px) / 2) auto max(14px, (100dvh - 940px) / 2) 50%; width: min(500px, calc(100vw - 32px)); translate: -50% 0;
    padding: 14px; border-radius: 26px; box-shadow: inset 0 0 0 3px var(--shell-rim), 0 18px 50px rgba(10, 20, 60, 0.45);
  }
  .deck-pick-screen { grid-template-columns: repeat(3, minmax(0, 1fr)); padding: 22px 14px 18px; gap: 20px 10px; }
  .dialog.dev-window:not(.small-dialog) { width: min(500px, calc(100vw - 32px)); max-height: min(88dvh, 940px); }
  .dialog.dev-window .card-pool { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 10px; }
}

/* the deck pickers and the rooms (events, the Center, the Mart, the grotto) need no top bar (the user's call, 2026-10-07):
   the rooms carry their own slim bar along the bottom instead, one row: the Pokédex's Home key, Leave (the screen's
   #reward-skip, moved in by showChoice()), then HP and money on one LCD. The move pick after a fight has the bar
   too (.learn), keeping its own Reroll / Skip. showChoice() sets .in-room */
body[data-screen="reward-screen"]:has(#reward-options.deck-pick, #reward-screen.in-room) .topbar { display: none; }
.room-bar { display: none; }
#reward-screen.in-room .room-bar {
  position: fixed; z-index: 3; left: 50%; bottom: 0; translate: -50% 0; width: min(100%, 520px);
  display: flex; flex-direction: column; gap: 6px; padding: 6px 10px max(8px, env(safe-area-inset-bottom)); border-radius: 16px 16px 0 0;
  background: var(--shell); box-shadow: inset 0 3px 0 var(--shell-hi), inset 0 0 0 3px var(--shell-rim), 0 -4px 14px rgba(0, 0, 0, 0.4);
}
.room-row { display: flex; align-items: stretch; gap: 8px; }
/* on top of the bar, the Pokédex's hinge like the map's: lens, lights and the room's name on an LCD (the user's call,
   2026-10-07: the device tells you what's happening), so the title plate up top steps aside */
#reward-screen.in-room .reward-title { display: none; }
.room-hinge { display: flex; align-items: center; gap: 8px; padding: 2px 2px 0; }
.room-hinge .pdx-lens { width: 30px; height: 30px; border-width: 3px; }
.room-sign {
  flex: 0 1 auto; min-width: 0; display: flex; align-items: center;
  margin-left: auto; padding: 3px 10px; border: 2px solid var(--shell-rim); border-radius: 6px;
  background: #b6d68e; box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.12); color: #1f3a14; font-family: var(--pixel-font); font-synthesis-weight: none;
}
.room-sign b {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 400;
  font-size: 0.75rem; letter-spacing: 0.04em; animation: lcdType 0.6s steps(6) both;
}
@media (prefers-reduced-motion: reduce) { .room-sign b { animation: none; } }
/* a friend's hearts (heartRow() in js/ui.js; docs/roadmap.md's step 8): red when filled, an outline when not */
.hearts { display: inline-flex; gap: 2px; vertical-align: middle; }
.hearts i { display: block; width: 12px; height: 11px; }
.hearts svg { display: block; width: 100%; height: 100%; overflow: visible; fill: transparent; stroke: currentColor; stroke-width: 1.1; }
.hearts i.on svg { fill: #d8384c; stroke: #7a1424; }
.hearts.full i.on svg { fill: #f04a6a; }
#room-hearts { flex: none; margin-left: 8px; color: #1f3a14; }
#room-hearts .hearts i { width: 13px; height: 12px; }
#reward-screen:has(> :is(.center-room, .event-room, .treasure-room, .mart-window)) .reward-actions { display: none; }
/* the Mart, the grotto and the move pick stand in the screen's flow, so it keeps the bar's height clear */
#reward-screen:has(> :is(.treasure-room, .mart-window)) { padding-bottom: var(--room-bar-h, 120px); }
#reward-screen.learn { padding-bottom: calc(var(--room-bar-h, 120px) + 8px); }
#reward-screen.learn .reward-bottom { bottom: calc(var(--room-bar-h, 120px) + 10px); }
.room-lcd {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; margin: 2px; padding: 3px 8px; border: 2px solid #2a2a30; border-radius: 6px;
  background: radial-gradient(120% 140% at 30% 0%, #c2dc9a, #a8c97e); color: #1f3a14; font: 0.75rem var(--pixel-font); font-synthesis-weight: none;
  box-shadow: inset 0 2px 0 rgba(31, 58, 20, 0.14), 0 0 0 3px #e4e4ea, 0 0 0 5px var(--shell-rim);
}
.room-lcd .gb-hp { flex: 1; width: auto; min-width: 34px; margin: 0; }
.room-lcd .gb-hp-tag { border-color: #1f3a14; background: #1f3a14; color: #c2dc9a; box-shadow: none; }
.room-lcd .gb-hp-track { border-color: #1f3a14; background: rgba(255, 255, 255, 0.35); box-shadow: none; }
.room-lcd .gb-hp-fill { transition-duration: 0.8s, 0.3s; }   /* an event's HP change runs down visibly, as on the old top bar plate */
.room-lcd .gb-hp-num { width: auto; align-self: center; font-size: 0.75rem; font-weight: 400; white-space: nowrap; }
.room-cash { display: flex; align-items: center; gap: 2px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.room-keys { flex: none; display: flex; align-items: stretch; gap: 6px; }
.room-home {
  flex: none; display: grid; place-items: center; width: 48px; min-height: 46px; padding: 0; border: 0;
  background: none; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
/* Leave (a door, an arrow out) and a fight's reward steps' Skip (a double chevron) are round keys exactly like Home, the
   word kept for screen readers only (the user's call, 2026-10-08); js/main.js roundKey() draws all of them */
.round-key {
  display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--shell-hi), var(--shell) 60%, var(--shell-lo));
  box-shadow: inset 0 0 0 2px var(--shell-rim), inset 0 2px 0 rgba(255, 255, 255, 0.25), 0 3px 0 var(--shell-deep);
  color: #fff; transition: translate 0.06s, box-shadow 0.06s;
}
.round-key svg { width: 21px; height: 21px; filter: drop-shadow(0 1px 0 var(--shell-deep)); }
.leave-ico, .skip-ico { display: none; }
#reward-skip.room-leave .leave-ico, #reward-skip.room-skip .skip-ico { display: grid; }
#reward-skip:is(.room-leave, .room-skip) {
  flex: none; display: grid; place-items: center; width: 48px; min-height: 46px; padding: 0; border: 0; border-radius: 0;
  background: none; box-shadow: none; -webkit-tap-highlight-color: transparent;
}
#reward-skip:is(.room-leave, .room-skip):active { transform: none; }
#reward-skip:is(.room-leave, .room-skip):active .round-key { translate: 0 2px; box-shadow: inset 0 0 0 2px var(--shell-rim), 0 1px 0 var(--shell-deep); }
#reward-skip:is(.room-leave, .room-skip)[hidden] { display: grid; visibility: hidden; }   /* Team Rocket has no Leave: the LCD keeps its place */
#reward-skip.room-skip.labelled { position: relative; place-items: start center; }
#reward-skip.room-skip.labelled::after {
  content: 'SKIP'; position: absolute; left: 50%; bottom: -5px; translate: -50% 0; pointer-events: none;
  font: 0.75rem var(--pixel-font); color: #fff; text-shadow: 0 1px 0 var(--shell-deep), 0 0 4px var(--shell-deep);
  animation: skipPulse 1.6s ease-in-out infinite;
}
@keyframes skipPulse { 50% { opacity: 0.55; scale: 0.94; } }
@media (prefers-reduced-motion: reduce) { #reward-skip.room-skip.labelled::after { animation: none; } }
#reward-skip:is(.room-leave, .room-skip) .pp-pill {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
/* the screen's confirm: a glowing gold pill beside the hinge's lights, one word on it (the user's call, 2026-10-08), the
   colour of the yellow light so it stands out on any shell and pulses clearly while it waits */
.room-ok {
  flex: none; display: grid; place-items: center; min-width: 76px; height: 32px; padding: 0 16px; cursor: pointer;
  border: 2px solid #5a3a08; border-radius: 999px;
  background: linear-gradient(#fff3a0, #f8d030 45%, #e0a818);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.7), inset 0 -2px 0 rgba(120, 70, 0, 0.35), 0 3px 0 #5a3a08, 0 0 8px 2px rgba(255, 216, 64, 0.55);
  color: #3a2400; font: 0.75rem var(--pixel-font); font-synthesis-weight: none; text-transform: uppercase; white-space: nowrap;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6); -webkit-tap-highlight-color: transparent;
  animation: roomOkIn 0.2s ease-out, roomOkPulse 1.1s ease-in-out 0.2s infinite;
  transition: translate 0.06s;
}
.room-ok[hidden] { display: none; }
/* waiting for a pick: greyed in its place, so it never pops in and out */
.room-ok:disabled { opacity: 0.45; filter: grayscale(1); cursor: default; animation: none; }
/* pressed: pushed down into the shell with a flash, and it stays down, lit, until the screen moves on */
.room-ok.pressed, #reward-screen.deck-picking #reward-ok.pressed {
  opacity: 1; filter: none; translate: 0 3px; animation: roomOkPress 0.35s ease-out both;
  background: linear-gradient(#f0d860, #e8b820 50%, #c88a10);
  box-shadow: inset 0 3px 4px rgba(90, 58, 8, 0.55), inset 0 -1px 0 rgba(255, 255, 255, 0.35), 0 0 0 #5a3a08, 0 0 10px 3px rgba(255, 216, 64, 0.6);
}
@keyframes roomOkPress {
  0% { filter: brightness(1.6); box-shadow: inset 0 3px 4px rgba(90, 58, 8, 0.55), 0 0 26px 10px rgba(255, 240, 140, 0.95); }
}
.room-ok:active:not(:disabled) { translate: 0 2px; box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.7), 0 1px 0 #5a3a08, 0 0 14px 4px rgba(255, 216, 64, 0.8); }
.room-ok:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }
@keyframes roomOkIn { from { opacity: 0; scale: 0.6; } }
@keyframes roomOkPulse {
  50% {
    scale: 1.06; filter: brightness(1.12);
    box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.7), inset 0 -2px 0 rgba(120, 70, 0, 0.35), 0 3px 0 #5a3a08,
      0 0 18px 7px rgba(255, 224, 80, 0.85), 0 0 0 4px rgba(255, 240, 160, 0.5);
  }
}
@media (prefers-reduced-motion: reduce) { .room-ok { animation: none; } }
/* a picked card blown up over a room: the bar (and its A key) stays lit above the dimmed screen */
body:has(.card-focus.over-room) #reward-screen.in-room .room-bar { z-index: 31; }
.card-focus.reward-focus.over-room { padding-bottom: calc(var(--room-bar-h, 120px) + 12px); }
@media (max-width: 360px) {
  #reward-screen.in-room .room-bar { padding-inline: 8px; }
  .room-row { gap: 6px; }
  .room-home { width: 42px; }
  #reward-skip:is(.room-leave, .room-skip) { width: 42px; }
  .room-ok { min-width: 64px; padding-inline: 12px; }
  .room-lcd { gap: 5px; padding-inline: 5px; }
  .room-lcd .gb-hp-tag { display: none; }
}

/* the Game Corner as a Pokédex app (cornerApp in js/shop.js): the cabinet's CRT fills the device's screen, its Buy under it */
.cdev-app.cdev-corner { display: flex; flex-direction: column; gap: 10px; padding: 10px; background: #0c0c10; color: #e8fff4; }
.cdev-corner .gc-crt { flex: 1 0 auto; justify-content: space-between; }
.cdev-corner .gc-crt * { text-shadow: 2px 2px 0 rgba(0, 20, 16, 0.6); }
.cdev-corner .gc-roster { padding-bottom: 4px; }
.gc-app-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.gc-app-hint { font-size: 0.75rem; text-transform: uppercase; color: #8a8a96; }
.gc-app-buy {
  min-width: 132px; padding: 10px 14px; border: 3px solid #181010; border-radius: 999px;
  background: #f878b0; box-shadow: 0 4px 0 #a83870, 0 4px 0 3px #181010; color: #181010;
  font: 0.75rem var(--pixel-font); font-synthesis-weight: none; text-transform: uppercase; cursor: pointer;
}
.gc-app-buy:active:not(:disabled) { translate: 0 3px; box-shadow: 0 1px 0 #a83870, 0 1px 0 3px #181010; }
.gc-app-buy:disabled { background: #888890; box-shadow: 0 4px 0 #505058, 0 4px 0 3px #181010; color: #2a2a30; cursor: default; }
.gc-app-buy.armed { animation: gcAppArmed 0.5s steps(1) infinite; }
@keyframes gcAppArmed { 50% { background: #fff0a0; } }
@media (prefers-reduced-motion: reduce) { .gc-app-buy.armed { animation: none; background: #fff0a0; } }

/* the map's Pokédex button is the device's Home key (the user's ask, 2026-10-07: smaller, and plainly "home"): a round key
   in the shell's colours with a house on it, pressed in on a tap; it opens the device's home screen, Main menu is there */
.home-key { display: none; }
body[data-screen="map-screen"] .home-dex .dex-sprite { display: none; }
body[data-screen="map-screen"] .home-dex { filter: none !important; }
body[data-screen="map-screen"] .home-key, .room-home .home-key {
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--shell-hi), var(--shell) 60%, var(--shell-lo));
  box-shadow: inset 0 0 0 2px var(--shell-rim), inset 0 2px 0 rgba(255, 255, 255, 0.25), 0 3px 0 var(--shell-deep);
  color: #fff; transition: translate 0.06s, box-shadow 0.06s;
}
body[data-screen="map-screen"] .home-key svg, .room-home .home-key svg { width: 17px; height: 17px; filter: drop-shadow(0 1px 0 var(--shell-deep)); }
body[data-screen="map-screen"] .home-dex:active .home-key, .room-home:active .home-key { translate: 0 2px; box-shadow: inset 0 0 0 2px var(--shell-rim), 0 1px 0 var(--shell-deep); }
body[data-screen="map-screen"]:has(#map-screen.tower) .home-key { width: 26px; height: 26px; }
body[data-screen="map-screen"]:has(#map-screen.tower) .home-key svg { width: 15px; height: 15px; }
/* the climb's Home key moves up onto the hinge, after the lights, like every map's (the user's call, 2026-10-08):
   measureBar() in js/tower.js gives its spot inside the top bar */
body[data-screen="map-screen"]:has(#map-screen.tower) .home-dex { position: absolute; z-index: 3; left: var(--tw-home-x, 0); top: var(--tw-home-y, 0); }
/* the top bar is laid on the device, so it waits for the cover to swing open (bootDevice()'s .booting) */
body:has(#map-screen.booting) .topbar { visibility: hidden; }
/* nothing on the map drags or rubber-bands the page; only the map itself scrolls, inside its glass (the user's ask, 2026-10-08) */
html:has(body[data-screen="map-screen"]), body[data-screen="map-screen"] { overflow: hidden; overscroll-behavior: none; }
body[data-screen="map-screen"] #map-screen:not(.tower) { touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
body[data-screen="map-screen"] #map-screen:not(.tower) .map-wrap { touch-action: pan-x pan-y; }
body[data-screen="map-screen"] :is(#map-screen, .topbar) img { -webkit-user-drag: none; }
/* on a map the Home key sits on the hinge, after the lights (the user's call, 2026-10-08); fixed, not moved in the DOM,
   since the top bar's button serves every screen. 95px = the hinge's padding, lens and lights */
body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .home-dex { position: fixed; z-index: 21; left: 95px; top: calc(var(--topbar-h) + (var(--hinge-h) - 30px) / 2); }
@media (max-width: 720px) { body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .home-dex { top: calc(6px + (var(--hinge-h) - 30px) / 2); } }
@media (min-width: 721px) {   /* on the handheld standing mid-screen (its size and gap in the map's wide rule) */
  body[data-screen="map-screen"]:has(#map-screen:not(.tower)) .home-dex {
    left: calc(50% - min(500px, 100vw - 32px) / 2 + 95px); top: calc(26px + var(--mdex-gap) + (var(--hinge-h) - 30px) / 2);
  }
}
.room-home .home-key { width: 38px; height: 38px; }
.room-bag[hidden] { display: none; }
.room-hinge .room-bag { width: 34px; min-height: 32px; }
.room-hinge .room-bag .home-key { width: 30px; height: 30px; }
.room-hinge .room-bag .home-key svg { width: 17px; height: 17px; }
.room-bag:active .home-key, .room-bag[aria-expanded="true"] .home-key { translate: 0 2px; box-shadow: inset 0 0 0 2px var(--shell-rim), 0 1px 0 var(--shell-deep); }
/* the reward steps' Bag key opens the top bar's Bag, though that bar is put away there: the bar comes back out of the
   flow and unseen, only its Bag showing, risen over the room bar like the map's over its dock */
body[data-screen="reward-screen"]:has(#reward-screen.in-room) .topbar:has(#bag:not([hidden])) {
  display: flex; position: fixed; inset: 0 0 auto; visibility: hidden;
}
body[data-screen="reward-screen"]:has(#reward-screen.in-room) .bag:not([hidden]) {
  visibility: visible; position: fixed; top: auto; right: auto; left: 50%; bottom: calc(var(--room-bar-h, 120px) + 8px); translate: -50% 0;
  max-height: min(60dvh, calc(100dvh - var(--room-bar-h, 120px) - 24px)); animation: bagRise 0.18s ease-out;
}
.room-home .home-key svg { width: 21px; height: 21px; }
/* in battle the Pokédex button shrinks to 24px (the user's ask, 2026-10-07: at 36px it crowded the enemy's nameplate) */
body[data-screen="battle-screen"] .home-dex .dex-sprite { width: 24px; height: 24px; }

/* ---------- the Sky Pillar's augment pick (roadmap item 21; part b, 2026-10-07: its look, js/augment-art.js) ----------
   Each tier is a frame: brushed silver, gold with a sheen sweeping across, Prismatic a rainbow edge turning round. The
   tiles are dealt face down (.aug-back, the Sky Pillar on the tier's metal) and turn over one by one; a reroll turns
   them back and drops them. */
@property --aug-spin { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.aug-pick { gap: 14px; perspective: 900px; }
.aug-pick .reward-option { width: clamp(118px, 29vw, 190px); }
.aug-tile {
  --metal: linear-gradient(135deg, #ffffff, #aeb6c2 30%, #eef1f5 50%, #7c8492 72%, #d4d9e0);
  --well: linear-gradient(180deg, #2a2f39, #1a1d24);
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 5px; height: 100%; min-height: 200px;
  padding: 22px 8px 12px; border-radius: 14px; border: 4px solid transparent; box-sizing: border-box; text-align: center;
  color: #f1f1f1; background: var(--well) padding-box, var(--metal) border-box;
  box-shadow: 0 6px 0 rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.12);
  transform-style: preserve-3d;
}
.aug-tile.aug-gold {
  --metal: linear-gradient(135deg, #fff6c0, #f0c040 30%, #fff0a0 50%, #b07818 72%, #f4cc58);
  --well: linear-gradient(180deg, #3a2f14, #221a0a);
}
.aug-tile.aug-prismatic {
  --metal: conic-gradient(from var(--aug-spin), #ff6b8a, #ffc06b, #fff07a, #6bff9c, #5ad1ff, #9a7bff, #ff6bd6, #ff6b8a);
  --well: radial-gradient(120% 80% at 50% 0%, #3a2458, #160f26 70%);
  animation: augSpin 4s linear infinite;
  box-shadow: 0 6px 0 rgba(0, 0, 0, 0.35), 0 0 18px rgba(190, 140, 255, 0.45);
}
@keyframes augSpin { to { --aug-spin: 360deg; } }
/* gold and Prismatic catch the light: a sheen sweeps across every few seconds */
.aug-tile.aug-gold::after, .aug-tile.aug-prismatic::after {
  content: ''; position: absolute; inset: 0; border-radius: 10px; pointer-events: none;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, 0.22) 48%, transparent 60%) no-repeat;
  background-size: 250% 100%; animation: augSheen 3.6s ease-in-out infinite;
}
.aug-tile.aug-prismatic::after { background-image: linear-gradient(105deg, transparent 30%, rgba(255, 120, 200, 0.18) 42%, rgba(120, 220, 255, 0.24) 50%, rgba(255, 240, 120, 0.18) 58%, transparent 70%); }
@keyframes augSheen { 0%, 55% { background-position: 130% 0; } 100% { background-position: -130% 0; } }
.aug-ribbon {
  position: absolute; top: -4px; left: 50%; translate: -50% 0; padding: 3px 12px 4px; border-radius: 0 0 10px 10px;
  font-size: 12px; font-weight: bold; letter-spacing: 0.12em; text-transform: uppercase; color: #1c1430; background: var(--metal);
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.3); white-space: nowrap;
}
.aug-prismatic .aug-ribbon { color: #fff; text-shadow: 0 1px 2px #3a1460; }
.aug-tile-icon { width: 58px; height: 58px; flex: none; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.4)); }
.aug-gold .aug-tile-icon { filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.4)) drop-shadow(0 0 8px rgba(255, 210, 90, 0.35)); }
.aug-prismatic .aug-tile-icon { filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.4)) drop-shadow(0 0 10px rgba(200, 150, 255, 0.6)); }
.aug-name { font-size: 15px; line-height: 1.15; }
.aug-gold .aug-name { color: #ffe08a; }
.aug-prismatic .aug-name { background: linear-gradient(90deg, #ff9ab0, #ffe27a, #8affb8, #8adfff, #c8a8ff); -webkit-background-clip: text; background-clip: text; color: transparent; }
.aug-type { font-size: 12px; padding: 1px 8px; border-radius: 999px; font-weight: bold; text-transform: uppercase; letter-spacing: 0.06em; color: #fff; background: #6a7080; }
.aug-type.type-fire { background: #e0602a; }
.aug-type.type-water { background: #3a7ee0; }
.aug-type.type-grass { background: #48a040; }
.aug-text { font-size: 12.5px; line-height: 1.3; color: #e4e6ec; }
/* part c: a trade-off's red chip, a set's chip and its bonuses under the text */
.aug-chip { font-size: 12px; padding: 1px 8px; border-radius: 999px; font-weight: bold; letter-spacing: 0.04em; color: #fff; }
.aug-trade { background: #b02838; text-transform: uppercase; }
.aug-set { background: #3c3c7a; }
.aug-set-text { font-size: 12px; line-height: 1.25; color: #c8c4ff; }
.focus-card.aug-tile .aug-set-text { font-size: 13px; }
.aug-set-row .aug-set-node { display: grid; place-items: center; font-size: 22px; }
.aug-set-row .aug-set-on { color: inherit; font-weight: bold; }
.aug-set-row .aug-set-off { opacity: 0.55; }
.aug-back {
  position: absolute; inset: -4px; display: grid; place-items: center; border-radius: 14px;
  background: radial-gradient(circle at 50% 45%, rgba(255, 255, 255, 0.35), transparent 60%), var(--metal);
  transform: rotateY(180deg) translateZ(1px); backface-visibility: hidden; -webkit-backface-visibility: hidden;
  box-shadow: inset 0 0 0 3px rgba(28, 20, 48, 0.5);
}
.aug-back .smooth-icon { width: 46%; height: auto; opacity: 0.9; filter: drop-shadow(0 3px 0 rgba(0, 0, 0, 0.3)); }
.reward-option.picked .aug-tile { outline: 4px solid #f8d030; outline-offset: 2px; }

/* the deal: each tile slides up face down and turns over (its chime at 55%, augment-art.js's FLIP_AT) */
.aug-deal .aug-tile { animation: augDeal 0.7s cubic-bezier(0.3, 0.7, 0.3, 1) both; animation-delay: calc(var(--i, 0) * 170ms); }
.aug-deal .aug-tile.aug-prismatic { animation: augDeal 0.7s cubic-bezier(0.3, 0.7, 0.3, 1) both calc(var(--i, 0) * 170ms), augSpin 4s linear infinite; }
@keyframes augDeal {
  0% { transform: translateY(46px) rotateY(180deg) scale(0.8); }
  45% { transform: translateY(-6px) rotateY(180deg) scale(1.02); }
  80% { transform: rotateY(-8deg) scale(1.06); }
  100% { transform: none; }
}
/* the moment it lands face up, a burst of its tier's light behind it */
.aug-deal::before {
  content: ''; position: absolute; inset: -18px; z-index: -1; border-radius: 50%; pointer-events: none; opacity: 0;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.55), transparent 65%);
  animation: augFlash 0.7s ease-out both; animation-delay: calc(var(--i, 0) * 170ms + 330ms);
}
.reward-option.aug-deal, .reward-option.aug-fold { position: relative; isolation: isolate; }
.aug-floor-gold .aug-deal::before { background: radial-gradient(circle, rgba(255, 210, 90, 0.6), transparent 65%); }
.aug-floor-prismatic .aug-deal::before { background: radial-gradient(circle, rgba(255, 140, 220, 0.45), rgba(110, 200, 255, 0.35) 40%, transparent 68%); }
@keyframes augFlash { 0% { opacity: 0; transform: scale(0.5); } 30% { opacity: 1; } 100% { opacity: 0; transform: scale(1.3); } }
/* a reroll: each turns back over and drops away */
.aug-fold { pointer-events: none; }
.aug-fold .aug-tile, .aug-fold .aug-tile.aug-prismatic { animation: augFold 0.42s ease-in both; animation-delay: calc(var(--i, 0) * 50ms); }
@keyframes augFold {
  0% { transform: none; }
  55% { transform: rotateY(180deg) scale(1.02); }
  100% { transform: translateY(60px) rotateY(180deg) scale(0.8); }
}
/* the fades sit on the button: opacity on the tile itself would flatten its 3D, and the flip would show the front mirrored */
.reward-option.aug-deal { animation: augIn 0.14s both; animation-delay: calc(var(--i, 0) * 170ms); }
.reward-option.aug-fold { animation: augOut 0.42s ease-in both; animation-delay: calc(var(--i, 0) * 50ms); }
@keyframes augIn { from { opacity: 0; } }
@keyframes augOut { 55% { opacity: 1; } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .aug-tile, .aug-tile.aug-prismatic, .aug-deal .aug-tile, .aug-deal .aug-tile.aug-prismatic, .aug-fold .aug-tile, .reward-option.aug-deal, .reward-option.aug-fold { animation: none; }
  .aug-tile::after, .aug-deal::before { animation: none; display: none; }
}

/* blown up when picked */
.focus-card.aug-tile { width: min(270px, 80vw); height: auto; min-height: 260px; max-height: none; flex: none; padding-top: 28px; }
.focus-card.aug-tile .aug-tile-icon { width: 84px; height: 84px; }
.focus-card.aug-tile .aug-name { font-size: 19px; }
.focus-card.aug-tile .aug-text { font-size: 15px; }
@media (max-width: 420px) {
  .aug-pick { gap: 7px; }
  .aug-pick .reward-option { width: calc((100% - 14px) / 3); }
  .aug-tile { min-height: 190px; padding: 20px 5px 10px; border-width: 3px; }
  .aug-ribbon { font-size: 12px; padding: 3px 8px 4px; letter-spacing: 0.08em; }
  .aug-tile-icon { width: 48px; height: 48px; }
  .aug-name { font-size: 13px; }
  .aug-text { font-size: 12px; }
  .aug-type, .aug-chip { font-size: 12px; padding: 1px 5px; }
  .aug-set-text { display: none; }
  .focus-card.aug-tile .aug-set-text { display: block; }
  /* High Roller's 4: two rows of two */
  .aug-pick:has(.reward-option:nth-child(4)) .reward-option { width: calc((100% - 7px) / 2); }
}

/* the Bag's Augments row */
.aug-head { margin: 8px 0 2px; font-weight: bold; font-size: 13px; opacity: 0.8; }
svg.aug-node { padding: 0; border: 0; background: none; box-shadow: none; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.3)); }
svg.aug-node.spent { filter: grayscale(1); opacity: 0.55; }
.aug-emoji { display: inline-grid; place-items: center; font-size: 22px; }
/* the Sky Pillar's augment pick: Reroll and Take are the gold pill (.room-ok, the user's call, 2026-10-08) */
#reward-reroll.room-ok { min-width: 96px; height: 38px; font-size: 0.75rem; }
#reward-reroll.room-ok .pp-pill { display: contents; }
#reward-reroll.room-ok .reroll-cap { display: none; }
.reward-focus .room-ok.focus-confirm { min-width: 110px; height: 42px; font-size: 0.8rem; }

/* ---------- the walk-in 3D Pokémon Center (js/center-3d.js, branch pokecenter-3d) ---------- */
/* its canvas sits where the pixel scene does, under the room's bar and text box; the choices are the room's own
   machine, PC and Chansey, so the pixel room's nurse and monitor go */
/* touch-action none: a drag walks (dragWalk()); manipulation let iPhone Safari pan the page under it too, which carried
   the floating signs off their machines (the user's report, 2026-10-29) */
.center3d-view { position: fixed; inset: 0; z-index: -1; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 0.35s; touch-action: none; }
.center3d-view.on { opacity: 1; }
/* a gateway town's folk talk in bubbles over their heads (js/event-3d.js's townCrowd()), under the room's own keys */
.town-stage { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.mart3d-view { transition: none; }   /* the Mart shows at once: a fade let the page's navy through */
#reward-options.c3d-wait :is(.reward-option, .center-nurse, .center-vitals), #reward-options.c3d :is(.center-nurse, .center-vitals) { visibility: hidden; pointer-events: none; }
/* the indoor ? rooms walked in 3D (js/event-3d.js): their trainer and Pokémon stand in the room instead */
/* display, not visibility: a blinking trainer's eyes-closed head sets itself visible and flashed over the room */
#reward-options:is(.c3d, .c3d-wait) .event-figure { display: none; }
/* a found item or relic picked over the 3D room it came from (hold() in js/event-3d.js), not the pixel scene */
body.ev3d-held :is(#scene-bg, #scene-light, #backdrop) { visibility: hidden; }
/* a deck picker over a walk-in room keeps the room behind it (pickingOver() in js/hd2d.js), not its signs and bubbles */
body:has(#reward-options.deck-pick) :is(.mart3d-sign, .town-stage) { display: none; }
/* the signs float over the 3D machine, PC and Chansey (placeSigns()); a tap on one goes through to the room, which walks
   your Pokémon over first */
#reward-options.c3d .reward-option { pointer-events: none; background: none; }
body:has(#reward-options.c3d) #reward-screen { cursor: pointer; }
/* the pixel room never shows while the 3D one loads (c3d-wait); if Three.js fails the wait comes off and it's back */
body:has(#reward-options:is(.c3d, .c3d-wait)) :is(#scene-bg, #scene-light, #backdrop) { visibility: hidden; }
/* a 3D place that keeps you waiting (load3d()): its name on a banner bottom left, your Pokémon hopping by a rolling
   Poké Ball bottom right, and the room bar out of the way; all after half a second, so a quick load never flashes it */
.loading-mark { position: fixed; inset: 0; z-index: 3; pointer-events: none; opacity: 0; animation: loading-in 0.25s 0.5s forwards; }
body:has(.loading-mark:not(.out)) #reward-screen.in-room .room-bar { animation: loading-out 0.25s 0.5s forwards; pointer-events: none; }
/* once the room is up the screen fades out over it, the room bar fading back in */
.loading-mark.out { opacity: 1; animation: loading-out 0.3s forwards; }
body:has(.loading-mark.out) #reward-screen.in-room .room-bar { animation: loading-back 0.3s both; }
.loading-buddy {
  position: absolute; right: 16px; bottom: calc(24px + env(safe-area-inset-bottom));
  display: flex; align-items: flex-end; gap: 2px;
}
.loading-buddy img { image-rendering: pixelated; }
.loading-mon { height: 56px; animation: loading-hop 0.6s steps(2, jump-none) infinite alternate; }
.loading-ball { width: 30px; height: 30px; margin-bottom: 2px; animation: loading-roll 0.8s steps(8) infinite; }
.loading-banner {
  position: absolute; left: 0; bottom: calc(24px + env(safe-area-inset-bottom));
  display: grid; gap: 6px; padding: 10px 34px 10px 18px; min-width: 150px;
  background: linear-gradient(90deg, var(--shell) 0 6px, rgba(18, 20, 42, 0.92) 6px);
  border-block: 2px solid var(--gold); color: var(--ink);
  clip-path: polygon(0 0, 100% 0, calc(100% - 18px) 100%, 0 100%);
  animation: loading-slide 0.3s 0.5s both ease-out;
}
.loading-place { font-size: 0.875rem; font-weight: normal; letter-spacing: 0.04em; }
.loading-word { font-size: 0.75rem; color: var(--gold); letter-spacing: 0.12em; text-transform: uppercase; }
.loading-word i { font-style: normal; animation: loading-dot 1.2s steps(1) infinite; }
.loading-word i:nth-child(2) { animation-delay: 0.3s; }
.loading-word i:nth-child(3) { animation-delay: 0.6s; }
.loading-mark.calm :is(.loading-mon, .loading-ball, .loading-banner, .loading-word i) { animation: none; }
@keyframes loading-in { to { opacity: 1; } }
@keyframes loading-out { to { opacity: 0; visibility: hidden; } }
@keyframes loading-back { from { opacity: 0; } }
@keyframes loading-hop { to { translate: 0 -6px; } }
@keyframes loading-roll { to { rotate: 1turn; } }
@keyframes loading-slide { from { translate: -100% 0; } }
@keyframes loading-dot { 0% { opacity: 0; } 25% { opacity: 1; } }
/* the signs are small cream speech windows, a thin border in the choice's colour (the user's pick, 2026-10-09) */
#reward-options.c3d .center-label {
  bottom: 8px; padding: 7px 12px 6px;
  background: #fbf4df; color: #6a5440; border: 2px solid #e05838; border-radius: 12px;
  box-shadow: 0 2px 0 #d8c8a4, 0 4px 10px rgba(0, 0, 0, 0.3);
}
#reward-options.c3d .reward-option + .reward-option .center-label { border-color: #3878f0; }
#reward-options.c3d .reward-option:nth-child(3) .center-label { border-color: #b058d8; }
#reward-options.c3d .center-label::after {
  width: 10px; height: 10px; margin-top: -5px; transform: translateX(-50%) rotate(45deg);
  background: #fbf4df; clip-path: polygon(100% 0, 100% 100%, 0 100%); border: inherit; border-width: 0 2px 2px 0; border-radius: 0 0 3px 0;
}
#reward-options.c3d .reward-option:is(:disabled, .locked) .center-label { color: #9a8c78; border-color: #b8ae9c; }
/* a town's quest board: no sign over it, the board (and its "!" till read) is enough (the user's call, 2026-10-14) */
#reward-options.c3d .reward-option.bare .center-label { display: none; }
/* the 3D grotto (js/event-3d.js): its chest is modelled, so the pixel chest's button stays only for its sign, floated over
   the lid, and its logic; a tap goes through to the room, which walks your Pokémon up first */
#reward-options.c3d-wait .treasure-chest, #reward-options.c3d .treasure-chest :is(.chest-part, .chest-rays, .chest-glow) { visibility: hidden; }
#reward-options.c3d .treasure-chest { pointer-events: none; animation: none; }

/* ---------- the walk-in 3D Poké Mart (js/mart-3d.js, branch pokemart-3d) ---------- */
/* the shop's tiles stay in the page (their buttons take the two-tap Buy) but the 3D shelves show the wares instead */
#reward-options.mart-window:is(.m3d, .m3d-wait) { visibility: hidden; pointer-events: none; }
#reward-options.mart-window:is(.m3d, .m3d-wait) * { visibility: hidden !important; pointer-events: none !important; animation-play-state: paused !important; }
body:has(#reward-options:is(.m3d, .m3d-wait)) :is(#scene-bg, #scene-light, #backdrop) { visibility: hidden; }
/* the hidden ware grid still takes its height, which pushed the sticky box down under the room bar on a short phone */
body:has(#reward-options.m3d) #reward-screen .reward-bottom {
  position: fixed; left: 50%; bottom: calc(var(--room-bar-h, 120px) + 14px); translate: -50% 0; width: min(calc(100% - 32px), var(--log-w));
}
body:has(#reward-options.m3d) #reward-screen { cursor: pointer; touch-action: pan-y; user-select: none; -webkit-user-select: none; }
/* the PC's sign, a cream speech window like the 3D Center's, bobbing over it */
.mart3d-sign {
  position: fixed; z-index: 2; translate: -50% -100%; pointer-events: none; white-space: nowrap;
  padding: 7px 12px 6px; font-family: var(--pixel-font); font-size: 0.75rem; line-height: 1;
  background: #fbf4df; color: #6a5440; border: 2px solid #3878f0; border-radius: 12px;
  box-shadow: 0 2px 0 #d8c8a4, 0 4px 10px rgba(0, 0, 0, 0.3);
  animation: martSign 1.6s ease-in-out infinite;
}
.mart3d-sign::after {
  content: ''; position: absolute; left: 50%; top: 100%; width: 10px; height: 10px; margin-top: -5px; translate: -50% 0; rotate: 45deg;
  background: #fbf4df; border: 2px solid #3878f0; border-width: 0 2px 2px 0; border-radius: 0 0 3px 0;
}
.mart3d-sign.off { color: #9a8c78; border-color: #b8ae9c; animation: none; }
.mart3d-sign.off::after { border-color: #b8ae9c; }
body:has(.reward-focus) .mart3d-sign, body:not([data-screen="reward-screen"]) .mart3d-sign { display: none; }
@keyframes martSign { 50% { margin-top: -5px; } }
@media (prefers-reduced-motion: reduce) { .mart3d-sign { animation: none; } }

/* ---------- an Alpha's or a boss's fight in 3D (js/arena-3d.js): the canvas over the pixel scene, the page's pads hidden
   (they're still laid out: arena-3d.js casts them into the ground to place its own) ---------- */
.arena3d-view { position: fixed; inset: 0; z-index: -2; width: 100%; height: 100%; pointer-events: none; opacity: 0; visibility: hidden; }
.arena3d-view.on { opacity: 1; visibility: visible; }
.arena3d-view.on.fade { animation: arena3dIn 0.9s ease-out both; }
@keyframes arena3dIn { from { opacity: 0; filter: brightness(3.5); } 40% { opacity: 1; } to { opacity: 1; filter: none; } }
body.arena3d .enemy-zone::after,
body.arena3d .player-zone::before { opacity: 0; }
body.arena3d-solid :is(#scene-bg, #scene-light) { visibility: hidden; }
body.arena3d-wait :is(#scene-bg, #scene-light) { visibility: hidden; }
/* the 3D fork (js/crossroads-3d.js): its canvas under the cards, the painted canvas and sprite put away */
.xr3d-view { position: absolute; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; transition: opacity 0.35s; }
.xr3d-view.on { opacity: 1; }
.crossroads-scene.x3d #xr-canvas, .crossroads-scene.x3d #xr-mon { display: none; }
/* a road's notice board, read (js/crossroads-3d.js): what the floating cards said, plus its places and Pokédex page */
.xr-panel { --xr-dark: #7a5a3a; --xr-light: #c8a070; --ink: #3a2e24; position: absolute; left: 50%; top: calc(10px + env(safe-area-inset-top)); translate: -50% 0;
  width: min(340px, calc(100% - 28px)); box-sizing: border-box; color: var(--ink); filter: drop-shadow(4px 5px 0 rgba(0, 0, 0, 0.35));
  transform-origin: 50% 100%; animation: xrPanel 0.26s cubic-bezier(0.2, 1.3, 0.4, 1) both; }
.xr-panel[hidden] { display: none; }
@keyframes xrPanel { from { opacity: 0; scale: 0.85; translate: -50% 16px; } }
/* the kiosk's roof: rounded on top, ribbed, its underside in shadow */
.xr-roof { position: relative; z-index: 1; height: 26px; margin: 0 -8px -4px; border-radius: 50% 50% 6px 6px / 100% 100% 6px 6px;
  background: repeating-linear-gradient(90deg, transparent 0 22%, rgba(0, 0, 0, 0.07) 22% 23%), linear-gradient(#fffdf6, #eadcc0 70%, #c8b89a);
  box-shadow: inset 0 -5px 0 color-mix(in srgb, var(--xr-dark) 70%, #000); }
/* the frame in the road's colours, the poster pinned inside it */
.xr-frame { padding: 7px; border-radius: 4px; background: linear-gradient(var(--xr-light), var(--xr-dark)); box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.25); }
.xr-poster { overflow: hidden; border-radius: 2px; background: radial-gradient(circle at 20% 10%, rgba(255, 255, 255, 0.6), transparent 40%), #fbf4e4;
  box-shadow: inset 0 0 0 1px rgba(58, 46, 36, 0.25), inset 0 0 18px rgba(160, 120, 70, 0.18); }
.xr-rail { height: 9px; margin: -2px 6px 0; border-radius: 0 0 6px 6px; background: linear-gradient(#fbf4e4, #eadcc0 50%, var(--xr-dark)); }
.xr-head { position: relative; display: flex; align-items: center; gap: 8px; margin: 8px 8px 0; padding: 7px 44px 7px 10px; border-radius: 4px;
  background: linear-gradient(var(--xr-light), var(--xr-dark)); color: #fff; }
.xr-title { margin: 0; font-size: 1.15rem; line-height: 1.15; letter-spacing: 0.5px; text-shadow: 0 2px 0 rgba(0, 0, 0, 0.35); }
.xr-ball { flex: none; width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--ink); box-sizing: border-box;
  background: radial-gradient(circle, #fff 0 2.5px, var(--ink) 2.5px 4px, transparent 4px), linear-gradient(#e84838 0 45%, var(--ink) 45% 55%, #fff 55%); }
.xr-shut { position: absolute; top: 50%; right: 7px; translate: 0 -50%; width: 28px; height: 28px; padding: 0; border: 2px solid var(--ink); border-radius: 50%;
  background: #fbf4e4; color: var(--ink); font: inherit; font-size: 0.8rem; line-height: 1; cursor: pointer; box-shadow: 0 2px 0 rgba(0, 0, 0, 0.3); }
.xr-body { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 8px; padding: 12px 10px 12px; }
/* each section a note pinned to the poster, a little askew */
.xr-sec { position: relative; margin: 0; padding: 9px 8px 8px; min-width: 0; border-radius: 2px; background: #fffdf8;
  box-shadow: 0 1px 0 rgba(58, 46, 36, 0.25), 1px 2px 4px rgba(58, 46, 36, 0.18); rotate: -0.6deg; }
.xr-sec:nth-child(even) { rotate: 0.7deg; }
.xr-sec::before { content: ''; position: absolute; top: -5px; left: 50%; translate: -50% 0; width: 10px; height: 10px; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff 0 15%, var(--xr-light) 30%, var(--xr-dark)); box-shadow: 0 2px 1px rgba(0, 0, 0, 0.35); }
.xr-sec-places, .xr-sec-dex { grid-column: 1 / -1; }
.xr-sec .xr-label { display: block; margin: 0 0 6px; padding-bottom: 3px; border-bottom: 1px dashed rgba(58, 46, 36, 0.3); font-size: 0.75rem; font-weight: bold;
  letter-spacing: 1px; text-transform: uppercase; color: var(--xr-dark); text-align: left; }
.xr-places { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 8px; margin: 0; padding: 0; list-style: none; }
.xr-place { display: flex; align-items: center; gap: 6px; font-size: 0.8rem; line-height: 1.1; min-width: 0; }
.xr-num { flex: none; display: grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; background: var(--xr-dark); color: #fff; font-size: 0.75rem; }
.xr-place.boss .xr-num { background: #e84838; }
.xr-pname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xr-sec-bosses .xr-bosses { justify-content: center; min-height: 40px; }
.xr-sec-bosses .xr-boss { height: 40px; }
.xr-sec-bosses .xr-boss.unmet { filter: brightness(0) opacity(0.75); }
.xr-wilds { display: flex; flex-direction: column; gap: 4px; }
.xr-wild { display: flex; align-items: center; gap: 6px; padding: 2px 8px; font-size: 0.75rem; line-height: 1.4; }
.xr-wname { flex: 1; }
.xr-wn { font-weight: bold; }
.xr-dex { display: flex; align-items: center; gap: 10px; }
.xr-dex .dex-bar { flex: 1; margin: 0; height: 10px; background: #eadcc0; box-shadow: inset 0 0 0 1px rgba(58, 46, 36, 0.3); }
.xr-dex-n { font-size: 0.8rem; min-width: 3.5em; text-align: right; font-weight: bold; }
.xr-dex + .xr-dex { margin-top: 6px; }
.xr-dex-l { flex: none; width: 7.5em; font-size: 0.75rem; }
.xr-dex-research .ach-fill { background: linear-gradient(90deg, #7fd0ff, #3a7bd5); }
.xr-body .xr-swap { grid-column: 1 / -1; justify-self: center; margin: 0; }
.crossroads-scene.chosen .xr-panel { opacity: 0; transition: opacity 0.4s; }
.crossroads-scene.still .xr-panel { animation: none; }
.xr-wild { background: #f4ecda; border-left: 4px solid #c8c0a0; border-radius: 3px; }
.xr-wild.type-fire { border-color: #f08030; background: #fbe6d4; }
.xr-wild.type-water { border-color: #6890f0; background: #e2eafb; }
.xr-wild.type-grass { border-color: #78c850; background: #e6f4dc; }
.xr-wild.type-psychic { border-color: #f85888; background: #fbe2ea; }
.xr-sec-bosses { display: flex; flex-direction: column; }
.xr-sec-bosses .xr-bosses { flex: 1; align-items: center; }
/* the wilds' note runs down beside the bosses' and the Alphas' */
.xr-sec-wilds { grid-row: span 2; }

/* Meowth's talk at the crossroads: the Secret Base's cream speech window (.b3-talk) */
.xr-talk {
  position: absolute; left: 50%; bottom: max(18px, calc(env(safe-area-inset-bottom) + 10px)); z-index: 6; translate: -50% 0;
  width: min(460px, calc(100% - 32px)); margin: 0; padding: 24px 22px 20px; box-sizing: border-box;
  border-radius: 26px / 22px; background: #fbf4df; color: #6a5440; font-size: 16px; line-height: 1.6; text-align: left;
  box-shadow: 0 3px 0 #d8c8a4, 0 6px 16px #0005; cursor: pointer;
}
.xr-talk[hidden] { display: none; }
.xr-talk.xr-say { animation: xrPop 0.25s cubic-bezier(.3, 1.5, .5, 1); }
.xr-talk b {
  position: absolute; left: 18px; top: -15px; padding: 7px 14px; border-radius: 999px; font-weight: normal; font-size: 12px;
  background: #f8d878; color: #6a4a10; rotate: -4deg; box-shadow: 0 2px 0 #c8a048;
}
.xr-talk i {
  position: absolute; right: 18px; bottom: 8px; width: 0; height: 0;
  border: 6px solid transparent; border-top: 7px solid #e8a040; border-bottom: 0; animation: xrNudge 0.8s ease-in-out infinite;
}
.xr-talk.xr-news { text-align: center; color: #7a5410; }
@keyframes xrPop { from { scale: 0.85; opacity: 0; } }
@keyframes xrNudge { 50% { translate: 0 3px; } }
.crossroads-scene.talking .xr-go { opacity: 0; pointer-events: none; }
.xr-meowth { position: absolute; z-index: 2; height: calc(var(--px, 4px) * 22); image-rendering: pixelated; translate: -50% -100%; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .xr-talk.xr-say, .xr-talk i { animation: none; } }

/* a Gym Leader's moment before and after their boss (gymTalk() in js/gym.js): they slide in on the right over a dim, a
   shadow until beaten once, and talk in the cream speech window, their name on its tag */
.gym-scene {
  position: fixed; inset: 0; z-index: 990; cursor: pointer; overflow: hidden;
  background: radial-gradient(ellipse at 70% 60%, rgba(255, 220, 150, 0.18), rgba(8, 10, 24, 0.72) 70%);
  opacity: 0; transition: opacity 0.3s;
}
.gym-scene.in { opacity: 1; }
.gym-scene.out { opacity: 0; }
.gym-trainer {
  position: absolute; right: max(6%, calc(50% - 260px)); bottom: calc(max(18px, env(safe-area-inset-bottom) + 10px) + 150px);
  height: min(46vh, 300px); width: auto; image-rendering: pixelated; filter: drop-shadow(0 8px 0 rgba(0, 0, 0, 0.35));
  translate: 100vw 0; transition: translate 0.6s cubic-bezier(.2, .9, .3, 1.08), filter 0.6s;
}
.gym-scene.in .gym-trainer { translate: 0 0; }
.gym-scene.out .gym-trainer { translate: 100vw 0; transition: translate 0.32s cubic-bezier(.6, 0, .9, .5), filter 0.6s; }
.gym-trainer.shadow { filter: brightness(0) drop-shadow(0 0 2px rgba(255, 240, 200, 0.9)); }
/* a second speaker on the left, facing them (gymTalk()'s `pair`: JONA at Phil's); whoever isn't talking steps back into the dim */
.gym-trainer.pair { right: auto; left: max(6%, calc(50% - 260px)); scale: -1 1; translate: -100vw 0; }
.gym-scene.in .gym-trainer.pair { translate: 0 0; }
.gym-scene.out .gym-trainer.pair { translate: -100vw 0; }
.gym-scene.paired .gym-trainer { height: min(40vh, 260px); transition: translate 0.6s cubic-bezier(.2, .9, .3, 1.08), filter 0.3s, opacity 0.3s; }
.gym-scene.paired .gym-trainer.quiet { filter: brightness(0.45) drop-shadow(0 8px 0 rgba(0, 0, 0, 0.35)); opacity: 0.8; animation: none; }
/* on the battle screen after the fight (gymTalk()'s `stand`): on their fallen (or recalled) Pokémon's spot, the arena
   only lightly dimmed so they stand in it, as in the games */
.gym-scene.stand { background: linear-gradient(to bottom, rgba(8, 10, 24, 0.12), rgba(8, 10, 24, 0.5)); }
.gym-scene.stand .gym-trainer { right: auto; bottom: auto; left: var(--sx); top: var(--sy); height: var(--sh); transform: translate(-50%, -100%); }
.gym-say {
  position: absolute; left: 50%; bottom: max(18px, calc(env(safe-area-inset-bottom) + 10px)); translate: -50% 0;
  width: min(480px, calc(100% - 32px)); min-height: 110px; margin: 0; padding: 26px 22px 22px; box-sizing: border-box;
  border-radius: 26px / 22px; background: #fbf4df; color: #6a5440; font-size: 16px; line-height: 1.6; text-align: left;
  box-shadow: 0 3px 0 #d8c8a4, 0 6px 16px #0005;
  translate: -50% calc(100% + 40px); transition: translate 0.45s cubic-bezier(.2, .9, .3, 1.1) 0.15s;
}
.gym-scene.in .gym-say { translate: -50% 0; }
.gym-scene.out .gym-say { translate: -50% calc(100% + 40px); transition: translate 0.28s ease-in; }
.gym-text { margin: 0; }
.gym-plate {
  position: absolute; left: 18px; top: -16px; padding: 7px 14px; border-radius: 999px; font-size: 13px;
  background: #e85848; color: #fff; rotate: -3deg; box-shadow: 0 2px 0 #a02c20; white-space: nowrap; max-width: calc(100% - 36px);
  overflow: hidden; text-overflow: ellipsis;
}
.gym-plate small { font-size: 12px; opacity: 0.8; }
.gym-more {
  position: absolute; right: 18px; bottom: 10px; width: 0; height: 0;
  border: 6px solid transparent; border-top: 7px solid #e8a040; border-bottom: 0; animation: b3Nudge 0.8s ease-in-out infinite;
}
.gym-badge {
  position: absolute; left: 50%; top: 30%; width: 96px; height: 96px; translate: -50% -50%;
  filter: drop-shadow(0 0 18px rgba(255, 230, 120, 0.9)); animation: gymBadge 0.7s cubic-bezier(.3, 1.6, .5, 1);
}
@keyframes gymBadge { from { scale: 0; rotate: -200deg; } }
@media (prefers-reduced-motion: reduce) { .gym-trainer, .gym-say { transition: none; } .gym-more, .gym-badge { animation: none; } }
/* the speed lines as they slide in: a dark band behind them, white streaks racing past, fading once they've landed */
.gym-speed {
  position: absolute; left: 0; right: 0; bottom: calc(max(18px, env(safe-area-inset-bottom) + 10px) + 150px);
  height: min(46vh, 300px); overflow: hidden; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, transparent, rgba(20, 24, 60, 0.55) 25%, rgba(232, 88, 72, 0.35) 75%, transparent);
}
.gym-speed { animation: gymSpeed 1.3s ease-out both; }
/* talking to them in their gym after the fight: no slide-in or dim, the speech window just pops up (the dim comes back
   for the badge) */
.gym-scene.bubble:not(.getting) { background: none; }
.gym-scene.bubble .gym-say { translate: -50% 0; scale: 0.6; opacity: 0; transition: scale 0.22s cubic-bezier(.3, 1.6, .5, 1), opacity 0.15s; }
.gym-scene.bubble.in .gym-say { scale: 1; opacity: 1; }
.gym-scene.bubble.out .gym-say { scale: 0.8; opacity: 0; transition: scale 0.18s ease-in, opacity 0.18s; }
@keyframes gymSpeed { 0% { opacity: 0; scale: 1 0.2; } 12% { opacity: 1; scale: 1 1; } 55% { opacity: 1; } 100% { opacity: 0; scale: 1 0.85; } }
.gym-speed i {
  position: absolute; left: 100%; top: var(--y); width: var(--w); height: var(--h); border-radius: 99px;
  background: linear-gradient(90deg, transparent, #fff 40%, rgba(255, 255, 255, 0.6));
  animation: gymStreak var(--t) linear var(--d) infinite;
}
@keyframes gymStreak { to { translate: -260% 0; } }
@media (prefers-reduced-motion: reduce) { .gym-speed { display: none; } }
/* their own ball, thrown from the right onto the boss's pad (leaderThrow() in js/battle.js), and the boss bursting out */
.intro-ball.enemy-ball { position: fixed; z-index: 980; }
.intro-ball.enemy-ball.thrown { animation: ballArcX 0.7s linear both; }
.intro-ball.enemy-ball.thrown .ball3d { animation: ballArcY 0.7s both, ballRoll 0.28s steps(16) infinite reverse; }
.enemy-zone.ball-out .enemy-portrait { transform-origin: 50% 85%; animation: enemyBallOut 0.6s ease-out; }
.enemy-zone.ball-out #enemy-img { animation: enemyBallGlow 0.6s ease-out; }
.enemy-zone.ball-out .intent { visibility: hidden; }
@keyframes enemyBallOut { from { scale: 0.15; } 55% { scale: 1.12; } to { scale: 1; } }
@keyframes enemyBallGlow { from { filter: brightness(8) var(--rest); } 55% { filter: brightness(2.5) var(--rest); } 75%, to { filter: brightness(1) var(--rest); } }

/* their badge handed over (badgeGet() in js/gym.js): the talk steps back and the screen goes dark but for the badge,
   glowing where it hangs on the arch and the only thing that takes a tap (`.wait`); grabbed, it tumbles out and lands
   mid-screen with a flash, a shockwave and sparks, rays wheel open, then YOU RECEIVED rises under it */
.gym-scene.getting .gym-say { translate: -50% calc(100% + 40px); transition: translate 0.3s ease-in; }
.gym-scene.getting .gym-trainer { opacity: 0.25; transition: opacity 0.5s, translate 0.6s; }
.gym-get {
  position: absolute; inset: 0; perspective: 700px; perspective-origin: 50% 40%; pointer-events: none; overflow: hidden;
  background: radial-gradient(circle at 50% 42%, rgba(60, 40, 0, 0.35), rgba(4, 4, 14, 0.9) 70%);
  opacity: 0; transition: opacity 0.4s;
}
.gym-get.go { opacity: 1; }
.gym-get.wait { background: rgba(3, 3, 10, 0.88); }
.gym-get > :is(.gym-get-rays, .gym-get-badge, .gym-get-ring, .gym-get-sparks) { position: absolute; left: 50%; top: 40%; translate: -50% -50%; }
.gym-get-rays {
  width: 100vmax; height: 100vmax; opacity: 0; scale: 0.3;
  transition: opacity 0.5s, scale 0.7s cubic-bezier(.2, .9, .3, 1.2);
}
.gym-get.land .gym-get-rays { opacity: 1; scale: 1; animation: gymRays 14s linear infinite; }
@keyframes gymRays { to { rotate: 360deg; } }
.gym-get-badge {
  width: min(46vw, 200px); aspect-ratio: 1; opacity: 0;
  filter: drop-shadow(0 0 22px rgba(255, 220, 110, 0.85)) drop-shadow(0 6px 0 rgba(0, 0, 0, 0.4));
}
.gym-get.go .gym-get-badge { opacity: 1; transition: opacity 0.5s; }
.gym-get.wait .gym-get-badge { pointer-events: auto; cursor: pointer; }
.gym-get.done .gym-get-badge { opacity: 1; animation: gymGetFloat 3.2s ease-in-out infinite; }
.gym-get-mark { position: relative; width: 100%; height: 100%; display: block; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.gym-get.wait .gym-get-mark { animation: gymBeckon 1.3s ease-in-out infinite; }
@keyframes gymBeckon {
  0%, 100% { scale: 1; filter: brightness(1.05) drop-shadow(0 0 10px rgba(255, 220, 110, 0.7)); }
  50% { scale: 1.07; filter: brightness(1.3) drop-shadow(0 0 26px rgba(255, 230, 140, 1)); }
}
.gym-get-halo {
  position: absolute; inset: -45%; border-radius: 50%; opacity: 0.55; pointer-events: none;
  background: radial-gradient(circle, rgba(255, 236, 160, 0.85), rgba(255, 200, 80, 0.35) 35%, transparent 68%);
}
.gym-get.wait .gym-get-halo { animation: gymHalo 1.3s ease-in-out infinite; }
@keyframes gymHalo { 0%, 100% { opacity: 0.55; scale: 0.92; } 50% { opacity: 1; scale: 1.12; } }
.gym-get-badge { perspective: 520px; }
.gym-get.spinning .gym-get-mark { filter: brightness(1.35) drop-shadow(0 0 24px rgba(255, 230, 140, 1)); animation: gymStopSpin 2.1s forwards; }
@keyframes gymStopSpin {
  0% { rotate: y 0deg; animation-timing-function: cubic-bezier(.5, 0, .2, 1); }
  8% { rotate: y -30deg; animation-timing-function: cubic-bezier(.3, 0, .2, 1); }
  100% { rotate: y 3600deg; }
}
.gym-get.spinning .gym-get-halo { opacity: 1; scale: 1.25; transition: opacity 0.3s, scale 0.3s; }
.gym-get-hint {
  position: absolute; left: 0; right: 0; bottom: max(16vh, calc(env(safe-area-inset-bottom) + 100px)); text-align: center;
  font-size: 16px; letter-spacing: 3px; color: #ffe9a8; text-shadow: 0 0 12px rgba(255, 200, 60, 0.8), 0 2px 0 #0008;
  opacity: 0; transition: opacity 0.4s; pointer-events: none;
}
.gym-get.wait .gym-get-hint { opacity: 1; animation: gymHint 1.3s ease-in-out 0.6s infinite; }
@keyframes gymHint { 50% { opacity: 0.4; } }
.gym-get-shine {
  position: absolute; inset: 0; -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, 0.95) 48%, transparent 60%) -200% 0 / 300% 100% no-repeat;
}
.gym-get.land .gym-get-shine { animation: gymShine 2.4s ease-in-out 0.1s infinite; }
@keyframes gymShine { 0% { background-position: 150% 0; } 45%, 100% { background-position: -150% 0; } }
@keyframes gymGetFloat { 0%, 100% { transform: translateY(0) rotateY(-14deg); } 50% { transform: translateY(-8px) rotateY(14deg); } }
.gym-get-ring {
  width: 60px; height: 60px; border-radius: 50%; opacity: 0;
  border: 6px solid rgba(255, 236, 160, 0.95); box-shadow: 0 0 24px rgba(255, 210, 90, 0.9), inset 0 0 18px rgba(255, 210, 90, 0.7);
}
.gym-get.land .gym-get-ring { animation: gymRing 0.8s ease-out forwards; }
@keyframes gymRing { 0% { opacity: 1; scale: 1; } 100% { opacity: 0; scale: 9; border-width: 1px; } }
.gym-get-flash { position: absolute; inset: 0; background: #fff8e0; opacity: 0; }
.gym-get.land .gym-get-flash { animation: gymFlash 0.6s ease-out; }
@keyframes gymFlash { 0% { opacity: 0.9; } 100% { opacity: 0; } }
.gym-get-sparks { width: 0; height: 0; }
.gym-get-sparks i {
  position: absolute; left: -4px; top: -4px; width: 8px; height: 8px; opacity: 0;
  background: #ffe48a; clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%);
  filter: drop-shadow(0 0 4px #ffd040);
}
.gym-get-sparks i:nth-child(3n) { background: #fff; width: 6px; height: 6px; }
.gym-get-sparks i:nth-child(4n) { background: #ffb040; }
.gym-get.land .gym-get-sparks i { animation: gymSpark var(--t) cubic-bezier(.1, .7, .3, 1) forwards; }
@keyframes gymSpark {
  0% { opacity: 1; transform: rotate(var(--a)) translateY(0) scale(1.6); }
  100% { opacity: 0; transform: rotate(var(--a)) translateY(calc(var(--d) * -1)) scale(0.3); }
}
.gym-get-cap {
  position: absolute; left: 0; right: 0; bottom: max(14vh, calc(env(safe-area-inset-bottom) + 90px)); text-align: center; align-items: center;
  display: flex; flex-direction: column; gap: 6px; opacity: 0; translate: 0 24px;
  transition: opacity 0.5s 0.25s, translate 0.6s cubic-bezier(.2, .9, .3, 1.2) 0.25s;
}
.gym-get.land .gym-get-cap, .gym-get.calm.done .gym-get-cap { opacity: 1; translate: 0 0; }
.gym-get-cap small { font-size: 14px; letter-spacing: 3px; color: #f4e6c0; text-shadow: 0 2px 0 #0008; }
.gym-get-cap b {
  font-size: clamp(22px, 7vw, 34px); letter-spacing: 2px; padding: 0 16px;
  background: linear-gradient(180deg, #fff6c8, #ffd040 55%, #e09018); -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 3px 0 #6a3a08) drop-shadow(0 0 14px rgba(255, 200, 60, 0.6));
}
.gym-get.calm .gym-get-badge { opacity: 1; animation: none; }
.gym-get.calm .gym-get-rays { opacity: 0.6; scale: 1; animation: none; }
@media (prefers-reduced-motion: reduce) {
  .gym-get .gym-get-badge, .gym-get .gym-get-rays, .gym-get .gym-get-shine, .gym-get .gym-get-mark, .gym-get .gym-get-halo { animation: none !important; }
  .gym-get.go .gym-get-badge { opacity: 1; }
}

/* the crossroads boards' Gym Leaders: a card each, a shadow and ??? till beaten, over the bosses they send out */
.xr-leaders { display: flex; gap: 8px; justify-content: center; }
.xr-leader { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 6px 4px;
  border-radius: 8px; background: rgba(255, 255, 255, 0.35); box-shadow: inset 0 0 0 1px rgba(58, 46, 36, 0.18); }
.xr-leader-pic { height: 64px; width: auto; image-rendering: pixelated; }
.xr-leader.unmet .xr-leader-pic { filter: brightness(0) opacity(0.8); }
.xr-leader-name { font-size: 0.75rem; font-weight: bold; text-align: center; line-height: 1.2; overflow-wrap: anywhere; }
.xr-leader .xr-bosses { justify-content: center; min-height: 0; }
.xr-leader .xr-boss { height: 36px; min-height: 0; }
.xr-sec-leaders { grid-column: 1 / -1; }
.xr-road .xr-leader { background: rgba(0, 0, 0, 0.2); }
.xr-road .xr-leader-pic { height: 48px; }
.xr-leader .xr-boss { max-width: none; }
.xr-road .xr-leader .xr-boss { height: 30px; }

/* the map's Gym Leader over the boss room (renderMap()'s `gym`): a trainer is narrower than a Pokémon's canvas */
.map-boss-shadow.map-leader { width: calc(var(--tile) * 5.4); margin-top: calc(var(--tile) * -2.4); }
.map-boss-shadow.paired { width: calc(var(--tile) * 8); margin-top: calc(var(--tile) * -2.6); }   /* beside its leader, clear of the room */
.map-boss-shadow.met:not(.map-leader) { filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.35)); }
.map-boss-shadow.map-leader.met { filter: drop-shadow(0 2px 0 rgba(0, 0, 0, 0.35)); }
/* their badge spinning in over the 3D gym (badgePop() in js/gym.js) */
.gym-pop { position: fixed; inset: 0; z-index: 990; pointer-events: none; transition: opacity 0.4s; }
.gym-pop.out { opacity: 0; }
/* Phil's possession (gymTalk()'s `possess`): a thinner dim so his Pokémon shows behind; once the dark takes him the
   screen's edges bleed violet and he shudders */
.gym-scene.possess { background: radial-gradient(ellipse at 70% 60%, rgba(120, 40, 200, 0.12), rgba(8, 4, 20, 0.45) 75%); }
.gym-scene.possess.taken { animation: gymDark 1.6s ease-in-out infinite; }
.gym-scene.possess.taken .gym-trainer { animation: gymShudder 0.12s steps(2) infinite; filter: drop-shadow(0 0 10px #a050e8) brightness(0.8) saturate(0.6); }
.gym-scene.possess .gym-plate { background: #5a1a9a; box-shadow: 0 2px 0 #2c0a50; }
@keyframes gymDark {
  0%, 100% { box-shadow: inset 0 0 80px 10px rgba(90, 20, 150, 0.6); }
  50% { box-shadow: inset 0 0 140px 40px rgba(40, 0, 70, 0.85); }
}
@keyframes gymShudder { 50% { translate: 2px 0; } }
@media (prefers-reduced-motion: reduce) { .gym-scene.possess.taken, .gym-scene.possess.taken .gym-trainer { animation: none; } }

/* JONA takes over (demonSwap() in js/gym.js): the screen blacks out, violet static rolls over it and everything shudders;
   while it talks the speech window is its own, black with violet text, the tag blood red */
.jona-flash {
  position: fixed; inset: 0; z-index: 2000; pointer-events: none;
  background:
    repeating-linear-gradient(0deg, rgba(200, 120, 255, 0.18) 0 2px, transparent 2px 5px),
    radial-gradient(ellipse at 50% 55%, rgba(160, 40, 255, 0.55), rgba(0, 0, 0, 0.96) 70%);
  animation: jonaFlash 1.2s steps(12) forwards;
}
.jona-flash.infuse { background: radial-gradient(circle at 50% 25%, rgba(255, 220, 255, 0.95), rgba(170, 60, 255, 0.7) 30%, rgba(20, 0, 40, 0) 70%); animation: jonaInfuse 1.1s ease-out forwards; }
.jona-flash.calm { animation: jonaCalm 0.9s ease-out forwards; }
@keyframes jonaFlash {
  0% { opacity: 0; } 8% { opacity: 1; background-position: 0 0; } 16% { opacity: 0.4; } 24% { opacity: 1; background-position: 0 7px; }
  40% { opacity: 0.85; background-position: 0 -4px; } 60% { opacity: 0.6; } 100% { opacity: 0; }
}
@keyframes jonaInfuse { 0% { opacity: 0; } 12% { opacity: 1; } 100% { opacity: 0; } }
@keyframes jonaCalm { 0% { opacity: 0; } 30% { opacity: 0.45; } 100% { opacity: 0; } }
body.jona-shake :is(#battle-screen, #reward-screen, .gym-scene, .event3d-view, canvas) { animation: jonaShake 0.6s steps(1); }
@keyframes jonaShake {
  0% { translate: 0 0; } 10% { translate: -6px 3px; } 20% { translate: 5px -4px; } 30% { translate: -4px -2px; }
  40% { translate: 6px 2px; } 50% { translate: -3px 4px; } 60% { translate: 3px -3px; } 80% { translate: -1px 1px; } 100% { translate: 0 0; }
}
.gym-scene.demon .gym-say,
#reward-screen .reward-log.demon {
  background: #120818; color: #e8c8ff; box-shadow: 0 3px 0 #4a1a7a, 0 0 22px rgba(170, 70, 255, 0.55);
  text-shadow: 0 0 6px rgba(200, 120, 255, 0.8); letter-spacing: 1px; animation: jonaBox 2.4s ease-in-out infinite;
}
.gym-scene.demon .gym-plate,
#reward-screen .reward-log.demon[data-who]::before { background: #b01030; color: #fff; box-shadow: 0 2px 0 #50040e, 0 0 10px rgba(255, 40, 80, 0.7); }
.gym-scene.demon .gym-trainer:not(.quiet) { animation: jonaFlicker 3s steps(1) infinite; }
@keyframes jonaBox { 50% { box-shadow: 0 3px 0 #4a1a7a, 0 0 36px rgba(170, 70, 255, 0.85); } }
@keyframes jonaFlicker { 0%, 46%, 50%, 100% { filter: drop-shadow(0 0 10px #a050e8) brightness(0.8) saturate(0.6); } 47%, 49% { filter: invert(1) hue-rotate(250deg) drop-shadow(0 0 14px #ff3060); } }
/* JONA poured into his Pokémon (infuse() in js/gym.js): the speech window and the dim go so the battle shows, a stream of
   dark energy on its own canvas, his Pokémon writhing and going dark as it fills, then Phil left grey and lifeless */
.gym-scene.possess.infusing { background: radial-gradient(ellipse at 50% 40%, rgba(60, 10, 110, 0.05), rgba(10, 0, 24, 0.35) 80%); cursor: default; }
.gym-scene.infusing .gym-say { opacity: 0; translate: -50% 30px; transition: opacity 0.3s, translate 0.3s; }
.gym-infuse { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.gym-scene.possess.taken .gym-trainer.drained { animation: none; filter: grayscale(1) brightness(0.45) drop-shadow(0 0 4px #301050); transition: filter 0.5s, translate 0.5s ease-in, opacity 0.5s; }
.gym-scene .gym-trainer.drained.gone { translate: 120% 0; opacity: 0; }
.enemy-portrait.sprite.writhing img { animation: writhe 0.1s steps(2) infinite; filter: brightness(0.55) saturate(0.4) drop-shadow(0 0 14px #a040ff) drop-shadow(0 0 4px #ff3868); }
@keyframes writhe { 0% { transform: translate(-3px, 1px) scale(1.02, 0.98); } 50% { transform: translate(3px, -1px) scale(0.98, 1.03); } }
@media (prefers-reduced-motion: reduce) { .enemy-portrait.sprite.writhing img { animation: none; } }
/* his Pokémon, once the dark is poured in: violet in place of the boss's gold, one still shadow on the sprite (an animated
   filter re-blurred the GIF every frame and dropped the battle's fps on a phone) and a halo behind it that breathes by
   opacity alone, which the compositor runs for free */
.enemy-portrait.sprite.boss.possessed img { --rest: drop-shadow(0 0 8px #a040ff); }
.enemy-portrait.sprite.possessed .enemy-pose::before { content: ''; position: absolute; inset: 0 -15% -5%; background: radial-gradient(ellipse 50% 45% at 50% 62%, rgba(176, 80, 255, 0.55), rgba(96, 16, 192, 0.25) 55%, transparent 72%); pointer-events: none; will-change: opacity; animation: possessedBreath 1.8s ease-in-out infinite; }
@keyframes possessedBreath { 50% { opacity: 0.45; } }
.enemy-portrait.sprite.possessed:is(.defeated, .sinking, .captured, .ran) .enemy-pose::before { content: none; }
@media (prefers-reduced-motion: reduce) {
  #reward-screen .reward-log.demon, .gym-scene.demon .gym-say, .gym-scene.demon .gym-trainer, .enemy-portrait.sprite.possessed .enemy-pose::before { animation: none; }
}
/* who's talking, on a tag over the speech window's corner (Britt at the Mart counter), like the Poké Mall shopkeepers' */
.reward-log:not([data-who=""])[data-who]::before {
  content: attr(data-who); position: absolute; left: 14px; top: -16px; padding: 4px 12px; border-radius: 999px;
  background: #f0a0b0; color: #6a2a3a; font-size: 0.75rem; line-height: 1.4; rotate: -4deg; box-shadow: 0 2px 0 #c87888, 0 0 0 2px #303038;
}

/* a town visited from home through its Waystone (js/run.js's visitTown()): no run, so no HP or Pokédollars on the bar */
body.town-visit #room-bar .room-lcd > * { visibility: hidden; }

/* a gateway town's furniture shop, visited from home (js/town-shop.js): the device's window, the day's pieces on its screen */
.town-shop { width: min(460px, calc(100vw - 32px)); }
.town-shop .tshop-say { margin: 0 0 10px; font-size: 0.8rem; line-height: 1.4; min-height: 2.8em; }
.town-shop .tshop-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; max-height: min(52vh, 420px); overflow-y: auto; padding: 2px; }
.town-shop .tshop-tile { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 6px 4px; border: 2px solid #5a7a3a; border-radius: 8px; background: #eef6dc; color: #1f3a14; font: inherit; font-size: 0.75rem; cursor: pointer; }
.town-shop .tshop-tile.on { border-color: #e8b020; background: #fff6c8; box-shadow: 0 0 0 2px #e8b020; }
.town-shop .tshop-pic { width: 64px; height: 64px; object-fit: contain; image-rendering: auto; }
.town-shop .tshop-name { text-align: center; line-height: 1.2; }
.town-shop .tshop-price { font-weight: bold; }
.town-shop .tshop-empty { grid-column: 1 / -1; text-align: center; font-size: 0.8rem; }
.town-shop .tshop-tile.sold { opacity: 0.55; }
/* Smeargle's jukebox gift (pickPlayer() in js/jukebox.js): the tapped player turning on the Furniture store's turntable
   (.mshop-stage in css/hub.css) over the five, kept small so the five still fit under it on a phone */
.jukebox-pick .jbp-stage { width: min(100%, 210px, 26vh); margin-bottom: 4px; }
.jukebox-pick .jbp-name { margin: 0 0 8px; text-align: center; font-size: 0.8rem; font-weight: bold; }
.jukebox-pick .tshop-say { min-height: 0; }
/* records (js/data/records.js): the trader's Records tab, and the jukebox's window at home (js/jukebox.js) */
.town-shop .tshop-tabs { display: flex; gap: 6px; margin: 0 0 8px; }
.town-shop .tshop-tab { flex: 1; padding: 5px 0; border: 2px solid #5a7a3a; border-radius: 6px; background: #dfe9c8; color: #1f3a14; font: inherit; font-size: 0.75rem; cursor: pointer; }
.town-shop .tshop-tab.on { background: #5a7a3a; color: #fff; }
/* the trader's crate of records (recordCrate() in js/jukebox.js): sleeves lean back in a wooden crate, the ones flipped
   past lie forward over its lip; each sleeve's transform comes from the script, so a flip is just the transition */
.town-shop .tshop-grid.crate { display: block; max-height: none; overflow: visible; padding: 0; }
.rec-crate { position: relative; height: 236px; margin: 0 0 8px; perspective: 640px; perspective-origin: 50% -40%; overflow: hidden;
  border-radius: 8px; background: radial-gradient(ellipse at 50% 20%, #4a3424, #1e150e 75%); touch-action: none; user-select: none; -webkit-user-select: none; }
.rec-crate::after { content: ''; position: absolute; left: 7%; right: 7%; bottom: 0; height: 60px; z-index: 80; pointer-events: none; border-radius: 4px 4px 0 0;
  background: linear-gradient(180deg, #c48a50 0 3px, #a8703c 3px 19px, #7a4c26 19px 21px, #9c6634 21px 39px, #7a4c26 39px 41px, #8e5c2e 41px);
  box-shadow: inset 0 -8px 12px rgba(0, 0, 0, 0.35), 0 -3px 8px rgba(0, 0, 0, 0.5); }
.rec-sleeve { --ink: #888; --shade: 0; position: absolute; left: calc(50% - 68px); bottom: 24px; width: 136px; height: 136px; padding: 0; border: 0;
  background: none; cursor: pointer; transform-origin: 50% 100%; transition: transform 0.34s cubic-bezier(0.3, 0.7, 0.3, 1), opacity 0.22s; }
.rec-sleeve .rec-disc { position: absolute; left: 9%; top: 9%; width: 82%; height: 82%; transition: transform 0.42s cubic-bezier(0.3, 0.7, 0.3, 1); }
.rec-sleeve.front .rec-disc { transform: translateY(-12%); }
.rec-sleeve.front.out .rec-disc { transform: translateY(-46%); }
.rec-sleeve .rec-cover { position: absolute; inset: 0; border-radius: 3px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.3), 0 2px 6px rgba(0, 0, 0, 0.55);
  background: radial-gradient(circle at 50% 44%, transparent 0 22%, rgba(255, 255, 255, 0.2) 22.5% 24%, transparent 24.5% 32%, rgba(255, 255, 255, 0.12) 32.5% 33.5%, transparent 34%),
    linear-gradient(155deg, color-mix(in srgb, var(--ink) 65%, #fff), var(--ink) 50%, color-mix(in srgb, var(--ink) 55%, #000)); }
.rec-sleeve .rec-cover::after { content: ''; position: absolute; inset: 0; border-radius: inherit; background: #000; opacity: var(--shade); transition: opacity 0.3s; }
.rec-sleeve .rec-tag { position: absolute; left: 7px; top: 7px; padding: 1px 6px; border-radius: 4px; background: rgba(255, 255, 255, 0.9); color: #222; font-size: 0.75rem; line-height: 1.3; }
.rec-sleeve.front:focus-visible { outline: none; }
.rec-sleeve.front:focus-visible .rec-cover { box-shadow: 0 0 0 3px #e8b020, 0 2px 6px rgba(0, 0, 0, 0.55); }
.rec-caption { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 8px; }
.rec-step { width: 40px; height: 40px; border: 2px solid #5a7a3a; border-radius: 8px; background: #eef6dc; color: #1f3a14; font: inherit; font-size: 0.9rem; cursor: pointer; }
.rec-step:disabled { opacity: 0.4; cursor: default; }
.rec-cap-words { text-align: center; min-width: 0; }
.rec-cap-name { margin: 0; font-size: 0.85rem; font-weight: bold; }
.rec-cap-note, .rec-count { margin: 2px 0 0; font-size: 0.75rem; opacity: 0.8; }
@media (prefers-reduced-motion: reduce) { .rec-sleeve, .rec-sleeve .rec-disc { transition-duration: 0.01s; } }
.rec-disc { --ink: #888; position: relative; display: inline-block; flex: none; width: 56px; height: 56px; border-radius: 50%;
  background: repeating-radial-gradient(circle, #1a1a1a 0 2px, #2c2c2c 2px 3px); box-shadow: inset 0 0 0 2px #000, 0 2px 3px rgba(0, 0, 0, 0.35); }
.rec-disc::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: linear-gradient(135deg, rgba(255, 255, 255, 0.22), transparent 45%, transparent 60%, rgba(255, 255, 255, 0.1)); }
.rec-label { position: absolute; inset: 34%; border-radius: 50%; background: var(--ink); box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.35); }
.rec-label::after { content: ''; position: absolute; inset: 40%; border-radius: 50%; background: #111; }
.rec-disc.spin .rec-label { animation: rec-spin 1.8s linear infinite; }
.rec-disc.spin .rec-label::before { content: ''; position: absolute; top: 12%; left: 46%; width: 8%; height: 22%; background: rgba(255, 255, 255, 0.7); border-radius: 2px; }
@keyframes rec-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .rec-disc.spin .rec-label { animation: none; } }
.dialog.jukebox { width: min(420px, calc(100vw - 32px)); padding: 0 0 14px; overflow-x: hidden; color: #fdeccf;
  border: 3px solid #f0c040; border-radius: 140px 140px 22px 22px / 64px 64px 22px 22px;
  background: radial-gradient(ellipse at 50% 0%, #6a1c34 0%, transparent 60%), linear-gradient(180deg, #45121f 0%, #260b16 45%, #160810 100%);
  box-shadow: 0 0 0 3px #5a1a10, inset 0 0 0 3px #8a2a3a, 0 0 22px 2px rgba(255, 80, 140, 0.5), 0 20px 60px rgba(0, 0, 0, 0.6); }
.jukebox .jb-marquee { position: relative; padding: 26px 16px 12px; text-align: center; }
.jukebox .jb-bulbs i { position: absolute; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%; background: #ffe9a8;
  box-shadow: 0 0 6px 2px rgba(255, 210, 120, 0.8); animation: jb-bulb 1.2s steps(1) infinite; animation-delay: calc(var(--i) * -0.2s); }
@keyframes jb-bulb { 50% { background: #8a5a30; box-shadow: none; } }
.dialog.jukebox .jb-name { margin: 0; padding: 0; border: 0; color: #fff3c8; font-size: 1.35rem; letter-spacing: 0.3em;
  text-shadow: 0 0 6px #ff4f8a, 0 0 14px #ff4f8a, 2px 2px 0 #5a0a24; }
.jukebox .jb-deck { position: relative; display: grid; grid-template-columns: 96px 1fr; gap: 16px; align-items: center; margin: 0 14px;
  padding: 10px; border-radius: 12px; background: linear-gradient(#34343e, #18181e); box-shadow: inset 0 0 0 2px #55555f, inset 0 3px 0 rgba(255, 255, 255, 0.07); }
.jukebox .jb-platter { width: 96px; height: 96px; border-radius: 50%; display: grid; place-items: center;
  background: radial-gradient(circle, #666 0 6%, #222 7% 100%); box-shadow: inset 0 0 0 4px #3a3a44, 0 0 0 2px #0a0a0e, 0 3px 6px rgba(0, 0, 0, 0.6); }
.jukebox .jb-platter .rec-disc { width: 84px; height: 84px; }
.jukebox .jb-arm { position: absolute; left: 100px; top: 8px; width: 6px; height: 66px; border-radius: 3px; background: linear-gradient(90deg, #f0f0f4, #8a8a94);
  transform-origin: 50% 4px; transform: rotate(-6deg); transition: transform 0.4s ease; }
.jukebox .jb-arm::before { content: ''; position: absolute; top: -5px; left: -5px; width: 16px; height: 16px; border-radius: 50%; background: #b8b8c4; box-shadow: inset 0 0 0 3px #6a6a74; }
.jukebox .jb-head { position: absolute; bottom: -7px; left: -4px; width: 14px; height: 10px; border-radius: 2px; background: #d8d8e0; box-shadow: inset 0 -3px 0 #8a8a94; }
.jukebox .jb-deck.on .jb-arm { transform: rotate(24deg); }
.jukebox .jb-deck:not(.on) .rec-label { animation-play-state: paused; }
.jukebox .jb-lcd { min-width: 0; padding: 8px 10px; border-radius: 8px; color: #8dffb4; background: #0c2416;
  box-shadow: inset 0 0 0 2px #06140c, inset 0 0 14px rgba(80, 255, 150, 0.16); }
.jukebox .jb-lcd small { display: block; font-size: 0.75rem; opacity: 0.7; letter-spacing: 0.1em; }
.jukebox .jb-scroll { overflow: hidden; white-space: nowrap; margin: 4px 0 6px; }
.dialog.jukebox .jb-now { display: inline-block; font-size: 0.9rem; text-shadow: 0 0 6px rgba(120, 255, 170, 0.6); white-space: pre; }
.jukebox .jb-now.long { animation: jb-ticker 12s linear infinite; }
@keyframes jb-ticker { to { transform: translateX(-50%); } }
.jukebox .jb-eq { display: flex; align-items: flex-end; gap: 3px; height: 16px; }
.jukebox .jb-eq i { width: 6px; height: 100%; background: #8dffb4; box-shadow: 0 0 4px rgba(120, 255, 170, 0.6); transform-origin: bottom;
  animation: jb-eq 0.8s ease-in-out infinite alternate; animation-delay: calc(var(--i) * -0.23s); }
.jukebox .jb-deck:not(.on) .jb-eq i { animation-play-state: paused; transform: scaleY(0.15); }
@keyframes jb-eq { from { transform: scaleY(0.2); } to { transform: scaleY(1); } }
.jukebox .jb-tabs { display: flex; gap: 5px; overflow-x: auto; margin: 14px 14px 0; scrollbar-width: none; }
.jukebox .jb-tabs::-webkit-scrollbar { display: none; }
.jukebox .jb-tab { flex: none; padding: 6px 10px 5px; border: 0; border-radius: 8px 8px 0 0; background: #8a6034; color: #f4e2c0; font: inherit; font-size: 0.75rem;
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.25); cursor: pointer; }
.jukebox .jb-tab.on { background: #f0c040; color: #3a1a08; box-shadow: none; }
.jukebox .jb-crate { position: relative; display: flex; height: 168px; margin: 0 14px; padding: 20px 0 14px; overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory; perspective: 520px; scrollbar-width: none; border-radius: 0 0 12px 12px;
  background: repeating-linear-gradient(90deg, #7a4f2a 0 26px, #6a4322 26px 28px); box-shadow: inset 0 12px 16px rgba(0, 0, 0, 0.5), inset 0 -4px 0 #4a2c14; }
.jukebox .jb-crate::-webkit-scrollbar { display: none; }
.jukebox .jb-crate::before, .jukebox .jb-crate::after { content: ''; flex: none; width: calc(50% - 46px); }
.jukebox .jb-sleeve { position: relative; flex: none; width: 120px; height: 120px; margin: 0 -14px; padding: 0; border: 0; background: none; font: inherit;
  scroll-snap-align: center; cursor: pointer; }
.jukebox .jb-sleeve .rec-disc { position: absolute; top: 6px; left: 6px; width: 108px; height: 108px; transition: transform 0.35s ease, opacity 0.35s; }
.jukebox .jb-sleeve.mid .rec-disc { transform: translateX(36px); }
.jukebox .jb-sleeve.out .rec-disc { transform: translate(20px, -160px) scale(0.6); opacity: 0; transition: transform 0.45s ease-in, opacity 0.45s ease-in; }
.jukebox .jb-cover { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; padding: 8px; border-radius: 4px; overflow: hidden;
  background: var(--ink); color: #fff; text-align: left;
  box-shadow: 0 8px 14px rgba(0, 0, 0, 0.55), inset 0 0 0 2px rgba(255, 255, 255, 0.2), inset -10px 0 12px rgba(0, 0, 0, 0.2); }
.jukebox .jb-cover::before, .jukebox .jb-cover::after { content: ''; position: absolute; inset: 0; pointer-events: none; }
.jukebox .jb-cover::after { background: linear-gradient(125deg, rgba(255, 255, 255, 0.28), transparent 38%); }
.dialog.jukebox .jb-cover b { position: relative; font-size: 0.75rem; line-height: 1.2; text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.7); }
.jukebox .jb-cover em { position: absolute; top: 7px; right: 6px; padding: 2px 4px; border-radius: 3px; background: #ffe9a8; color: #3a1a08;
  font-style: normal; font-size: 0.75rem; transform: rotate(6deg); box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.35); }
.jukebox .t-home::before { background: repeating-conic-gradient(rgba(255, 255, 255, 0.13) 0 25%, transparent 0 50%) 0 0 / 22px 22px; }
.jukebox .t-gift::before { background: radial-gradient(circle at 75% 30%, #fff 0 2px, transparent 3px), radial-gradient(circle at 30% 22%, #fff 0 1.5px, transparent 2.5px),
  radial-gradient(circle at 58% 55%, #fff 0 1.5px, transparent 2.5px), radial-gradient(circle at 35% 35%, rgba(255, 255, 220, 0.45), transparent 45%); }
.jukebox .t-shrine::before { background: radial-gradient(circle at 50% 36%, rgba(255, 214, 130, 0.7) 0 14px, transparent 15px), repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.18) 0 3px, transparent 3px 14px); }
.jukebox .t-wastes::before { background: radial-gradient(ellipse at 50% 120%, rgba(255, 130, 40, 0.75), transparent 62%), repeating-linear-gradient(135deg, rgba(255, 190, 70, 0.22) 0 8px, transparent 8px 18px); }
.jukebox .t-ruins::before { background: repeating-radial-gradient(circle at 50% 135%, rgba(255, 255, 255, 0.2) 0 4px, transparent 4px 14px); }
.jukebox .t-thornwood::before { background: radial-gradient(ellipse 20px 9px at 25% 28%, rgba(170, 255, 140, 0.38) 96%, transparent),
  radial-gradient(ellipse 20px 9px at 72% 50%, rgba(170, 255, 140, 0.32) 96%, transparent), radial-gradient(ellipse 15px 7px at 42% 70%, rgba(170, 255, 140, 0.3) 96%, transparent); }
.jukebox .t-savanna::before { background: radial-gradient(circle at 50% 0%, rgba(255, 244, 190, 0.85) 0 18px, transparent 19px),
  repeating-conic-gradient(from 0deg at 50% 0%, rgba(255, 232, 140, 0.3) 0 6deg, transparent 6deg 14deg); }
.jukebox .jb-caption { margin: 12px 16px 0; text-align: center; min-height: 2.8em; }
.dialog.jukebox .jb-caption b { display: block; color: #fff3c8; font-size: 0.95rem; text-shadow: 0 0 8px rgba(255, 90, 150, 0.6); }
.jukebox .jb-caption span { font-size: 0.75rem; opacity: 0.8; }
.dialog.jukebox .jb-none { margin: 10px 18px 0; font-size: 0.8rem; line-height: 1.4; text-align: center; color: #f4d8b8; }
.jukebox .dialog-actions { margin: 12px 14px 0; }
.jukebox.calm *, .jukebox.calm *::before { animation: none !important; transition: none !important; }
/* Kurt's Workshop (js/workshop.js): the town shop's window, a row of tabs over its shelf */
.workshop .wshop-tabs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; margin: 0 0 8px; }
.workshop .wshop-tab { padding: 6px 2px; border: 2px solid #5a7a3a; border-radius: 6px; background: #dfe9c8; color: #1f3a14; font: inherit; font-size: 0.75rem; cursor: pointer; }
.workshop .wshop-tab.on { background: #fff6c8; border-color: #e8b020; }
.workshop .wshop-glyph { display: grid; place-items: center; font-size: 2.4rem; line-height: 1; }
.workshop .tshop-price { font-weight: normal; font-size: 0.75rem; text-align: center; }
.workshop .tshop-price.short { color: #8a3a2a; }
.workshop .tshop-grid { max-height: min(52vh, 420px); overflow-y: auto; }
/* the PC's Grand Catalogue (js/grand-shop.js): the Workshop's window with two tabs; a shell is a little Pokédex in its colour */
.grand-shop .gshop-tabs { grid-template-columns: repeat(2, 1fr); }
.grand-shop .gshop-shell { display: block; width: 44px; height: 58px; margin: 3px 0; border-radius: 6px 6px 6px 14px; background: var(--sw);
  box-shadow: inset -4px -4px 0 rgba(0, 0, 0, 0.18), inset 3px 3px 0 rgba(255, 255, 255, 0.3), 0 0 0 2px #303038; position: relative; }
.grand-shop .gshop-shell::after { content: ''; position: absolute; left: 7px; top: 8px; width: 12px; height: 12px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #c8ecff 0 20%, #3d8ae0 55%, #1d4fa0); box-shadow: 0 0 0 2px #f8f8f0; }

/* Mewtwo speaking in your head as it steps out of the broken gate (gymTalk()'s `look`, from js/gatescene.js) */
.gym-scene.psychic { background: radial-gradient(ellipse at 70% 60%, rgba(200, 140, 255, 0.22), rgba(16, 6, 36, 0.78) 70%); }
.gym-scene.psychic .gym-trainer { filter: drop-shadow(0 0 14px rgba(190, 120, 255, 0.85)); }
.gym-scene.psychic .gym-say { color: #3a1a66; box-shadow: 0 3px 0 #b898e0, 0 0 0 3px #a060f0, 0 0 22px rgba(160, 90, 255, 0.6); }
.gym-scene.psychic .gym-plate { background: #7a3ac8; box-shadow: 0 2px 0 #3a1470, 0 0 10px rgba(180, 110, 255, 0.7); }
.gym-scene.psychic .gym-more { border-top-color: #a060f0; }
.gym-scene.psychic .gym-speed { background: linear-gradient(90deg, transparent, rgba(40, 10, 80, 0.6) 25%, rgba(170, 90, 255, 0.4) 75%, transparent); }
/* a Waystone waking (wayFlash() / wayCard() / awakenTalk() in js/gym.js, 2026-10-15): the screen whites out in the
   town's colour and shakes, WAYSTONE AWAKENED sweeps in, and its Gym Leaders slide in glowing in that colour */
.way-flash {
  position: fixed; inset: 0; z-index: 985; pointer-events: none;
  background: radial-gradient(circle at 50% 45%, #fff 0%, var(--glow) 40%, transparent 85%);
  animation: wayFlash 1.4s ease-out both;
}
@keyframes wayFlash { 0% { opacity: 0; } 6% { opacity: 1; } 22% { opacity: 0.85; } 100% { opacity: 0; } }
body.way-shake :is(.event3d-view, canvas) { animation: wayShake 0.9s steps(1); }
@keyframes wayShake {
  0% { translate: 0 0; } 6% { translate: -9px 5px; } 12% { translate: 8px -6px; } 18% { translate: -7px -3px; } 26% { translate: 6px 4px; }
  34% { translate: -5px 3px; } 44% { translate: 4px -3px; } 56% { translate: -3px 2px; } 70% { translate: 2px -1px; } 85% { translate: -1px 1px; } 100% { translate: 0 0; }
}
.way-card {
  position: fixed; inset: 0; z-index: 988; display: grid; place-items: center; cursor: pointer;
  background: radial-gradient(ellipse at 50% 50%, color-mix(in srgb, var(--glow) 28%, transparent), rgba(4, 6, 18, 0.55) 70%);
  opacity: 0; transition: opacity 0.35s;
}
.way-card.in { opacity: 1; }
.way-card.out { opacity: 0; transition: opacity 0.45s; }
.way-card-band {
  position: relative; width: 100%; padding: 22px 16px; box-sizing: border-box; text-align: center; overflow: hidden;
  display: flex; flex-direction: column; align-items: center; gap: 6px; color: #fff;
  background: linear-gradient(90deg, transparent, rgba(6, 8, 24, 0.82) 18%, rgba(6, 8, 24, 0.82) 82%, transparent);
  border-block: 2px solid var(--glow); box-shadow: 0 0 28px var(--glow), inset 0 0 22px color-mix(in srgb, var(--glow) 45%, transparent);
  clip-path: inset(0 50% 0 50%); transition: clip-path 0.55s cubic-bezier(.2, .9, .3, 1);
}
.way-card.in .way-card-band { clip-path: inset(0 0 0 0); }
.way-card-band::after {   /* a shine sweeping across once it's open */
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 35%, rgba(255, 255, 255, 0.45) 50%, transparent 65%);
  translate: -100% 0; animation: wayShine 1.1s ease-in-out 0.55s both;
}
@keyframes wayShine { to { translate: 100% 0; } }
.way-card-band small { font-size: 13px; letter-spacing: 0.3em; opacity: 0.85; }
.way-card-band b {
  font-size: clamp(22px, 7vw, 40px); letter-spacing: 0.08em; line-height: 1.1;
  color: #fff; text-shadow: 0 0 10px var(--glow), 0 0 26px var(--glow), 0 3px 0 rgba(0, 0, 0, 0.5);
}
.way-card-band strong { font-size: clamp(16px, 4.6vw, 24px); letter-spacing: 0.5em; padding-left: 0.5em; color: var(--glow); text-shadow: 0 0 12px var(--glow); }
.way-card-band > * { opacity: 0; translate: 0 10px; transition: opacity 0.4s, translate 0.4s; }
.way-card.in .way-card-band > * { opacity: 1; translate: 0 0; }
.way-card.in .way-card-band small { transition-delay: 0.35s; }
.way-card.in .way-card-band b { transition-delay: 0.5s; }
.way-card.in .way-card-band strong { transition-delay: 0.8s; }
.way-card.calm .way-card-band, .way-card.calm .way-card-band > * { clip-path: none; transition: none; opacity: 1; translate: 0 0; }
.way-card.calm .way-card-band::after { display: none; }
.gym-scene.awaken { background: radial-gradient(ellipse at 70% 60%, color-mix(in srgb, var(--glow) 34%, transparent), rgba(6, 8, 22, 0.78) 70%); }
.gym-scene.awaken .gym-trainer { filter: drop-shadow(0 0 6px #fff) drop-shadow(0 0 18px var(--glow)); animation: wayAura 2.4s ease-in-out infinite; }
@keyframes wayAura { 50% { filter: drop-shadow(0 0 8px #fff) drop-shadow(0 0 30px var(--glow)); } }
.gym-scene.awaken .gym-say { box-shadow: 0 3px 0 #d8c8a4, 0 0 0 3px var(--glow), 0 0 26px var(--glow); }
.gym-scene.awaken .gym-plate { background: color-mix(in srgb, var(--glow) 55%, #1a1630); box-shadow: 0 2px 0 #0006, 0 0 12px var(--glow); text-shadow: 0 1px 0 #0008; }
.gym-scene.awaken .gym-more { border-top-color: color-mix(in srgb, var(--glow) 70%, #000); }
.gym-scene.awaken .gym-speed { background: linear-gradient(90deg, transparent, rgba(6, 8, 30, 0.6) 25%, color-mix(in srgb, var(--glow) 50%, transparent) 75%, transparent); }
@media (prefers-reduced-motion: reduce) {
  .way-flash, body.way-shake :is(.event3d-view, canvas), .gym-scene.awaken .gym-trainer, .way-card-band::after { animation: none; }
}
/* Mewtwo's pentagram (js/pentagram.js): the five Waystone Shards' slots on a star, slid in from the right like a Gym
   Leader; a lit slot glows in its town's ring colour (--glow), a dark one is an empty socket. Mewtwo at the middle
   brightens with its strength (--power). */
.penta-scene { display: grid; place-items: center; padding: 16px; box-sizing: border-box; }
.penta-card {
  position: relative; width: min(400px, 100%); max-height: calc(100% - 8px); overflow-y: auto; box-sizing: border-box;
  padding: 26px 20px 26px; border-radius: 26px / 22px; background: rgba(22, 10, 46, 0.92); color: #efe4ff; text-align: center;
  box-shadow: 0 0 0 3px #a060f0, 0 0 26px rgba(160, 90, 255, 0.55);
  translate: 100vw 0; transition: translate 0.6s cubic-bezier(.2, .9, .3, 1.08);
}
.penta-scene.in .penta-card { translate: 0 0; }
.penta-scene.out .penta-card { translate: 100vw 0; transition: translate 0.32s cubic-bezier(.6, 0, .9, .5); }
.penta-head {
  position: absolute; left: 18px; top: 10px; padding: 7px 14px; border-radius: 999px; font-size: 13px; rotate: -3deg;
  background: #7a3ac8; color: #fff; box-shadow: 0 2px 0 #3a1470, 0 0 10px rgba(180, 110, 255, 0.7);
}
.penta-head small { font-size: 12px; opacity: 0.8; margin-right: 6px; }
.penta-star { display: block; width: min(300px, 76vw); margin: 24px auto 4px; overflow: visible; --power: 0.5; }
.penta-ring { fill: rgba(60, 20, 110, 0.35); stroke: #a060f0; stroke-width: 2; filter: drop-shadow(0 0 4px #a060f0); }
.penta-lines { fill: none; stroke: #c890ff; stroke-width: 2.2; stroke-linejoin: round; opacity: calc(0.35 + var(--power) * 0.65); filter: drop-shadow(0 0 3px #b070ff); }
.penta-inner { fill: rgba(20, 6, 40, 0.85); stroke: #7a3ac8; stroke-width: 1.5; }
.penta-mon { image-rendering: pixelated; opacity: calc(0.3 + var(--power) * 0.7); filter: brightness(calc(0.35 + var(--power) * 0.65)) drop-shadow(0 0 calc(var(--power) * 6px) #c890ff); }
.penta-slot .penta-halo { fill: var(--glow); opacity: 0; }
.penta-slot .penta-socket { fill: #140828; stroke: #4a2a78; stroke-width: 2; }
.penta-slot .penta-gem { fill: #2a1e3c; stroke: #4e3e66; stroke-width: 1.2; stroke-linejoin: round; }
.penta-slot .penta-shine { fill: #ffffff; opacity: 0; }
.penta-slot.lit .penta-halo { opacity: 0.35; animation: pentaGlow 2.4s ease-in-out infinite; }
.penta-slot.lit .penta-socket { stroke: var(--glow); }
.penta-slot.lit .penta-gem { fill: var(--glow); stroke: #ffffff; filter: drop-shadow(0 0 5px var(--glow)); }
.penta-slot.lit .penta-shine { opacity: 0.55; }
.penta-slot.flare { animation: pentaFlare 0.7s cubic-bezier(.3, 1.6, .5, 1); transform-box: fill-box; transform-origin: center; }
@keyframes pentaGlow { 50% { opacity: 0.6; } }
@keyframes pentaFlare { 0% { scale: 0.4; filter: brightness(4); } 60% { scale: 1.35; filter: brightness(2); } 100% { scale: 1; filter: none; } }
.penta-pct { margin: 2px 0 10px; font-size: 14px; color: #d8c4f8; }
.penta-pct b { font-size: 24px; color: #fff; font-weight: normal; text-shadow: 0 0 8px #b070ff; }
.penta-list { list-style: none; margin: 0 auto 10px; padding: 0; display: grid; gap: 4px; width: fit-content; text-align: left; font-size: 13px; }
.penta-town { display: grid; grid-template-columns: 14px auto auto; gap: 8px; align-items: center; color: #8a7aa8; }
.penta-town em { font-style: normal; font-size: 12px; opacity: 0.8; }
.penta-dot { width: 10px; height: 14px; clip-path: polygon(50% 0, 100% 30%, 100% 70%, 50% 100%, 0 70%, 0 30%); background: #3a2e4c; }
.penta-town.lit { color: #fff; }
.penta-town.lit .penta-dot { background: var(--glow); box-shadow: 0 0 6px var(--glow); }
.penta-town.lit em { color: var(--glow); }
.penta-line { margin: 0; font-size: 13px; line-height: 1.6; color: #e8dcff; }
.penta-card .gym-more { border-top-color: #a060f0; }
.penta-scene.calm .penta-card { transition: none; }
.penta-scene.calm .penta-slot :is(.penta-halo), .penta-scene.calm .penta-slot.flare { animation: none; }
@media (prefers-reduced-motion: reduce) { .penta-card { transition: none; } .penta-slot.lit .penta-halo, .penta-slot.flare { animation: none; } }

/* Kurt's bench (js/workshop.js's openWorkshop(), 2026-10-15, the user's ask: an aesthetic crafting window, easy to read
   and to track): a wooden workbench, Kurt's line on a tag, a tab per shelf, the picked recipe on a parchment card with
   each material's have / need, the shelf sorted ready first, and the forge over the card when something's made */
.dialog.craft {
  width: min(500px, calc(100vw - 24px)); max-height: 92dvh; padding: 14px; display: flex; flex-direction: column; gap: 10px;
  border: 3px solid #2a170c; border-radius: 18px; color: #3a2414;
  background: repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.06) 0 2px, transparent 2px 46px), linear-gradient(180deg, #8a5a32, #6a4224);
  box-shadow: 0 0 0 3px #c89a4a, 0 0 0 6px #2a170c, 0 24px 60px rgba(0, 0, 0, 0.6);
}
.craft-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.dialog.craft .craft-head h2 { margin: 0; padding: 0; border: 0; color: #ffe6a8; font-size: 1.05rem; letter-spacing: 0.06em; text-shadow: 0 2px 0 #2a170c; }
.craft-sub { color: #f0c888; font-size: 0.75rem; opacity: 0.8; }
.craft-talk { position: relative; margin-top: 8px; padding: 14px 14px 10px; border-radius: 14px; background: #fbf4df; box-shadow: 0 3px 0 #c8b088; }
.craft-tag { position: absolute; left: 12px; top: -12px; padding: 3px 12px; border-radius: 999px; background: #c8402c; color: #fff; font-size: 0.75rem; rotate: -3deg; box-shadow: 0 2px 0 #7a2014; }
.dialog.craft .craft-say { margin: 0; font-size: 0.8rem; line-height: 1.45; min-height: 2.9em; color: #5a3e28; }
.craft-tabs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.craft-tab { position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 7px 2px 6px; border: 2px solid #2a170c; border-radius: 10px 10px 6px 6px; background: #c89a62; color: #3a2414; font: inherit; cursor: pointer; box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.18); }
.craft-tab.on { background: #fbf4df; box-shadow: 0 0 0 2px #ffd860, inset 0 -3px 0 rgba(0, 0, 0, 0.08); }
.craft-tab-name { font-size: 0.75rem; }
.craft-tab-count { font-size: 0.75rem; opacity: 0.7; white-space: nowrap; }
.craft-dot { position: absolute; top: -9px; right: -6px; min-width: 22px; height: 22px; padding: 0 5px; box-sizing: border-box; display: grid; place-items: center; border-radius: 999px; background: #3aa83a; color: #fff; font-size: 0.75rem; box-shadow: 0 0 0 2px #2a170c, 0 0 10px rgba(120, 255, 120, 0.7); animation: craftPulse 1.6s ease-in-out infinite; }
@keyframes craftPulse { 50% { scale: 1.12; } }
.craft-card { flex: none; position: relative; padding: 12px; border-radius: 14px; overflow: hidden; background: linear-gradient(180deg, #fffaf0, #f4e8c8); box-shadow: inset 0 0 0 2px #d8c08a, 0 3px 0 #2a170c; }
.craft-top { display: flex; gap: 12px; align-items: center; }
.craft-pic { flex: none; width: 84px; height: 84px; display: grid; place-items: center; border-radius: 50%; background: radial-gradient(circle at 50% 40%, #fff, #e8d8b0); box-shadow: inset 0 0 0 3px #c8a868; }
.craft-pic.ready { box-shadow: inset 0 0 0 3px #3aa83a, 0 0 14px rgba(90, 200, 90, 0.6); }
.craft-pic > * { width: 64px; height: 64px; object-fit: contain; }
.craft-pic .wshop-glyph, .craft-row-pic .wshop-glyph, .craft-result .wshop-glyph { display: grid; place-items: center; font-size: 2.6rem; line-height: 1; }
.craft-info { min-width: 0; }
.dialog.craft .craft-name { margin: 0 0 3px; font-size: 0.95rem; color: #3a2414; }
.dialog.craft .craft-goes { margin: 0 0 4px; font-size: 0.75rem; color: #8a5a28; }
.dialog.craft .craft-text { margin: 0; font-size: 0.75rem; line-height: 1.4; color: #5a3e28; }
.dialog.craft .craft-earns { margin: 4px 0 0; font-size: 0.75rem; color: #b0306a; }
.dialog.craft .craft-label { margin: 10px 0 6px; font-size: 0.75rem; color: #8a5a28; letter-spacing: 0.08em; text-transform: uppercase; }
.craft-mats { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 6px; }
.craft-mat { display: grid; grid-template-columns: auto 1fr auto; grid-template-rows: auto 6px; column-gap: 6px; row-gap: 4px; align-items: center; padding: 6px 8px; border-radius: 10px; background: #fff; box-shadow: inset 0 0 0 2px #e0b0a0; }
.craft-mat.ok { box-shadow: inset 0 0 0 2px #8ac878; }
.craft-mat-ico { grid-row: 1 / 3; font-size: 1.5rem; line-height: 1; }
.craft-mat-name { font-size: 0.75rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.craft-mat-n { font-size: 0.75rem; color: #b04030; }
.craft-mat.ok .craft-mat-n { color: #2a8a2a; }
.craft-bar { grid-column: 2 / 4; height: 6px; border-radius: 3px; background: #ead8c8; overflow: hidden; }
.craft-bar i { display: block; height: 100%; border-radius: 3px; background: #e07a50; transition: width 0.4s; }
.craft-mat.ok .craft-bar i { background: #4ab84a; }
button.craft-mat { position: relative; border: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; }
button.craft-mat.on { box-shadow: inset 0 0 0 3px #f0a820; background: #fff8e0; }
.craft-mat-q { position: absolute; top: -6px; right: -6px; width: 18px; height: 18px; border-radius: 50%; background: #8a5a28; color: #fff; font-size: 0.75rem; line-height: 18px; text-align: center; }
.craft-where { grid-column: 1 / -1; padding: 8px 10px; border-radius: 10px; background: #fff8e0; box-shadow: inset 0 0 0 2px #f0a820; }
.dialog.craft .craft-where-head { margin: 0 0 4px; font-size: 0.8rem; color: #3a2414; }
.dialog.craft .craft-where-line { margin: 2px 0 0; font-size: 0.75rem; line-height: 1.4; color: #5a3e28; }
.dialog.craft .craft-where-line::before { content: '• '; color: #c08a10; }
.craft-make { display: block; min-width: 140px; margin: 8px auto 0; padding: 7px 18px; border: 2px solid #2a170c; border-radius: 10px; font: inherit; font-size: 0.8rem; cursor: pointer; background: #f0c040; color: #3a2414; box-shadow: inset 0 -3px 0 #c08a10; }
.craft-make.ready { background: linear-gradient(180deg, #ffd860, #f0a820); animation: craftGlow 1.4s ease-in-out infinite; }
@keyframes craftGlow { 50% { box-shadow: inset 0 -4px 0 #c08a10, 0 0 16px rgba(255, 210, 80, 0.85); } }
.craft-make:disabled { background: #d8ccb8; color: #8a7a68; box-shadow: inset 0 -3px 0 #b8a890; cursor: default; animation: none; }
.craft-make.made:disabled { background: #cfe8c0; color: #2a6a2a; box-shadow: inset 0 -3px 0 #9ac88a; }
.craft-list { flex: 1 1 auto; min-height: 120px; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding: 2px; }
.craft-row { display: flex; align-items: center; gap: 10px; padding: 6px 10px 6px 6px; border: 2px solid #2a170c; border-radius: 12px; background: #f4e8c8; color: #3a2414; font: inherit; font-size: 0.8rem; text-align: left; cursor: pointer; }
.craft-row.on { background: #fffaf0; box-shadow: 0 0 0 3px #ffd860; }
.craft-row.made, .craft-row.carried { opacity: 0.7; }
.craft-row-pic { flex: none; width: 40px; height: 40px; display: grid; place-items: center; border-radius: 50%; background: #fff; box-shadow: inset 0 0 0 2px #d8c08a; overflow: hidden; }
.craft-row-pic > * { width: 34px; height: 34px; object-fit: contain; }
.craft-row-pic .wshop-glyph { font-size: 1.5rem; }
.craft-row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.craft-held { font-size: 0.75rem; color: #b0306a; }
.craft-pill { flex: none; padding: 3px 8px; border-radius: 999px; font-size: 0.75rem; background: #ead8c8; color: #8a4030; }
.craft-pill.ready { background: #3aa83a; color: #fff; box-shadow: 0 0 8px rgba(90, 200, 90, 0.7); }
.craft-pill.made { background: #cfe8c0; color: #2a6a2a; }
.craft-pill.carried { background: #f0c040; color: #3a2414; }
.dialog.craft .craft-empty { margin: 12px 4px; text-align: center; font-size: 0.8rem; color: #fbe8c0; }
.craft-close {
  position: sticky; top: 0; z-index: 5; flex: none; align-self: flex-end; width: 36px; height: 36px; margin: 0 0 -46px; padding: 0;
  border: 2px solid #2a170c; border-radius: 50%; background: #fbf4df; color: #5a3e28; font: 14px/1 var(--pixel-font); cursor: pointer;
  box-shadow: 0 3px 0 #2a170c; -webkit-tap-highlight-color: transparent;
}
.craft-close:active { translate: 0 2px; box-shadow: 0 1px 0 #2a170c; }
.dialog.craft .craft-head { min-height: 36px; padding-right: 44px; }
/* more below (scrollCue() in js/ui.js, 2026-10-27, the user's ask): a ▼ MORE tag stuck to a scroll box's bottom edge
   while anything's hidden under it. It takes no room (its negative margin eats its height and the box's gap) and lets
   taps through to the row under it, then fades out at the end. */
.scroll-cue { --cue-gap: 0px; }
.scroll-cue::after {
  content: '▼ MORE ▼'; position: sticky; bottom: 4px; z-index: 4; flex: none; align-self: center; display: block; width: max-content;
  margin: calc(-26px - var(--cue-gap)) auto 0; padding: 0 12px; height: 26px; line-height: 26px; box-sizing: border-box;
  border: 2px solid #2a170c; border-radius: 999px; background: #ffd860; color: #3a2414; font-size: 0.75rem; letter-spacing: 0.06em;
  box-shadow: 0 3px 0 #2a170c, 0 0 14px 4px rgba(42, 23, 12, 0.55); pointer-events: none;
  opacity: 0; visibility: hidden; transition: opacity 0.2s, visibility 0.2s;
}
.scroll-cue.more::after { opacity: 1; visibility: visible; animation: cueBob 1.2s ease-in-out infinite; }
@keyframes cueBob { 50% { translate: 0 3px; } }
.scroll-cue.more .scroll-cue.more::after { opacity: 0; visibility: hidden; }
.calm-fx .scroll-cue.more::after { animation: none; }
@media (prefers-reduced-motion: reduce) { .scroll-cue.more::after { animation: none; } }
.dialog.craft { --cue-gap: 10px; }
.dialog.craft .craft-list { --cue-gap: 6px; }
.dialog.craft.busy .craft-tab, .dialog.craft.busy .craft-row, .dialog.craft.busy .craft-close { pointer-events: none; }
/* the forge */
.craft-forge { position: absolute; inset: 0; z-index: 3; cursor: pointer; background: rgba(40, 20, 8, 0); transition: background 0.3s, opacity 0.25s; }
.craft-forge.on { background: rgba(40, 20, 8, 0.55); }
.craft-forge.out { opacity: 0; }
.craft-pot { position: absolute; width: 70px; height: 70px; translate: -50% -50%; border-radius: 50%; background: radial-gradient(circle, #fff6c8, #ffb040 45%, rgba(255, 120, 40, 0) 70%); opacity: 0; transition: opacity 0.3s, scale 0.6s; }
.craft-forge.on .craft-pot { opacity: 0.85; }
.craft-pot.gulp { animation: craftGulp 0.25s ease-out; }
@keyframes craftGulp { 50% { scale: 1.25; } }
.craft-pot.hot { scale: 2.1; opacity: 1; animation: craftSpin 0.7s linear; }
@keyframes craftSpin { from { filter: hue-rotate(0deg) brightness(1); } to { filter: hue-rotate(40deg) brightness(1.6); } }
.craft-fly { position: absolute; font-size: 1.6rem; line-height: 1; translate: -50% -50%; pointer-events: none; }
.craft-spark { position: absolute; width: 7px; height: 7px; border-radius: 50%; background: #fff2a0; box-shadow: 0 0 8px #ffc040; translate: -50% -50%; pointer-events: none; }
.craft-result { position: absolute; translate: -50% -50%; display: grid; justify-items: center; gap: 4px; animation: craftPop 0.5s cubic-bezier(.3, 1.6, .5, 1); }
.craft-result > :first-child { width: 88px; height: 88px; object-fit: contain; filter: drop-shadow(0 0 14px rgba(255, 220, 120, 0.95)); }
.craft-result .wshop-glyph { font-size: 3.6rem; }
.craft-stamp { padding: 4px 14px; border: 3px solid #fff; border-radius: 8px; background: #c8402c; color: #fff; font-size: 0.95rem; letter-spacing: 0.1em; rotate: -6deg; box-shadow: 0 3px 0 #7a2014; animation: craftStamp 0.4s 0.25s cubic-bezier(.3, 1.8, .5, 1) both; }
@keyframes craftPop { from { scale: 0; rotate: -20deg; } }
@keyframes craftStamp { from { scale: 2.4; opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .craft-dot, .craft-make.ready, .craft-result, .craft-stamp, .craft-pot { animation: none; } }
/* a town's trade in a run (js/town-trade.js): an MMO's trade window (the user's ask, 2026-10-15), you and the trader
   across a table, an offer slot each, your Bag under yours and their offers under theirs; a slot's rim is its rarity */
.town-trade { --r-common: #5a6a7a; --r-uncommon: #2c64c8; --r-rare: #c08a10; }
.town-trade .ttrade-head { margin: 0 0 6px; font-size: 0.75rem; letter-spacing: 0.06em; color: #1f3a14; text-align: center; }
.town-trade .ttrade-head.dim { opacity: 0.5; }
.town-trade .tw-table { position: relative; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 6px; margin: 0 0 12px; }
.town-trade .tw-side { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 8px 6px 10px; border: 2px solid #1f3a14; border-radius: 10px; background: #d6e8b8; box-shadow: 0 3px 0 rgba(31, 58, 20, 0.35); transition: background 0.2s, box-shadow 0.2s; }
.town-trade .tw-who { display: flex; align-items: center; gap: 4px; min-height: 40px; font-size: 0.75rem; max-width: 100%; }
.town-trade .tw-who b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.town-trade .tw-face { width: 40px; height: 40px; object-fit: contain; image-rendering: pixelated; flex: none; }
.town-trade .tw-slot { display: grid; place-items: center; width: 72px; height: 72px; border: 3px dashed #3a5a28; border-radius: 12px; background: rgba(255, 255, 255, 0.35); }
.town-trade .tw-slot.full { border-style: solid; background: #f4fae8; box-shadow: inset 0 0 0 3px #fff, 0 0 0 2px #1f3a14; }
.town-trade .tw-slot .tw-pic { width: 56px; height: 56px; font-size: 2.4rem; transition: transform 0.5s cubic-bezier(0.5, 0, 0.3, 1); }
.town-trade .tw-table.crossing .tw-slot { z-index: 2; }
.town-trade .tw-q { font-size: 1.6rem; color: #3a5a28; opacity: 0.6; }
.town-trade .tw-tag { min-height: 2.5em; font-size: 0.75rem; line-height: 1.25; text-align: center; }
.town-trade .tw-ready { position: absolute; top: -10px; right: -6px; padding: 2px 8px; border: 2px solid #1f3a14; border-radius: 999px; background: #58b040; color: #fff; font-size: 0.75rem; letter-spacing: 0.06em; text-shadow: 1px 1px 0 #1f3a14; transform: scale(0); transition: transform 0.25s cubic-bezier(0.3, 1.6, 0.5, 1); }
.town-trade .tw-side.ready { background: #c4ecac; box-shadow: 0 0 0 3px #58b040, 0 3px 0 rgba(31, 58, 20, 0.35); }
.town-trade .tw-side.ready .tw-ready { transform: scale(1); }
.town-trade .tw-swap { display: flex; flex-direction: column; gap: 2px; color: #3a5a28; font-size: 1rem; line-height: 1; opacity: 0.45; transition: opacity 0.2s, color 0.2s; }
.town-trade .tw-table.set .tw-swap { opacity: 1; color: #1f3a14; }
.town-trade .tw-table.set .tw-arrow.r { animation: tw-nudge 1.2s ease-in-out infinite; }
.town-trade .tw-table.set .tw-arrow.l { animation: tw-nudge 1.2s ease-in-out infinite reverse; }
@keyframes tw-nudge { 50% { transform: translateX(3px); } }
.town-trade .tw-pools { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.town-trade .tw-pools section { padding: 8px 6px; border: 2px solid rgba(31, 58, 20, 0.45); border-radius: 10px; background: rgba(255, 255, 255, 0.18); }
.town-trade .tw-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(48px, 1fr)); gap: 6px; }
.town-trade .tw-cell { display: grid; place-items: center; aspect-ratio: 1; padding: 3px; border: 3px solid var(--rim, #3a5a28); border-radius: 8px; background: #eef6dc; color: #3a5a28; font: inherit; font-size: 1rem; cursor: pointer; transition: transform 0.12s; }
.town-trade .tw-cell:hover:not(.locked, .none) { transform: translateY(-2px); }
.town-trade .tw-cell.on { background: #fff6c8; box-shadow: 0 0 0 2px #e8b020, 0 0 10px #e8b020; transform: translateY(-2px); }
.town-trade .tw-cell.none { opacity: 0.4; filter: grayscale(1); }
.town-trade .tw-cell.locked { border-style: dashed; background: none; cursor: default; opacity: 0.55; }
.town-trade .tw-cell .tw-pic { width: 100%; height: 100%; display: grid; place-items: center; font-size: 1.6rem; }
.town-trade .tw-pic .item-sprite { width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
.town-trade .rar-common { --rim: var(--r-common); }
.town-trade .rar-uncommon { --rim: var(--r-uncommon); }
.town-trade .rar-rare { --rim: var(--r-rare); }
.town-trade .tw-slot.full { border-color: var(--rim); }
.town-trade .ttrade-info { margin: 10px 0 0; font-size: 0.75rem; line-height: 1.4; min-height: 2.8em; }
.town-trade .ttrade-info b { margin-right: 6px; }
.town-trade .tw-rar { display: inline-block; margin-right: 4px; padding: 0 6px; border-radius: 999px; background: var(--rim); color: #fff; text-transform: uppercase; letter-spacing: 0.04em; }
.town-trade .dev-screen { position: relative; }
.town-trade .tw-done { position: absolute; left: 50%; top: 38%; padding: 8px 16px; border: 3px solid #1f3a14; border-radius: 10px; background: #f8d048; color: #1f3a14; font-size: 0.9rem; letter-spacing: 0.08em; white-space: nowrap; box-shadow: 0 4px 0 #1f3a14, 0 8px 20px rgba(0, 0, 0, 0.35); transform: translate(-50%, -50%) scale(0); pointer-events: none; transition: transform 0.3s cubic-bezier(0.3, 1.6, 0.5, 1); }
.town-trade .tw-done.on { transform: translate(-50%, -50%) scale(1); }
@media (prefers-reduced-motion: reduce) { .town-trade .tw-arrow { animation: none !important; } }

/* Kenmatta's trial board (js/dojo.js, 2026-10-15): Kurt's bench's look (.dialog.craft) in his dojo's red and dark wood,
   your belt and the six above the ladder, the picked trial's two Pokémon facing off on its card, his rewards below */
.dialog.craft.dojo-win { background: repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.08) 0 2px, transparent 2px 38px), linear-gradient(180deg, #6a3a20, #3e2212); box-shadow: 0 0 0 3px #c8302a, 0 0 0 6px #2a170c, 0 24px 60px rgba(0, 0, 0, 0.6); }
.dojo-rank { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 4px 12px; padding: 10px 12px; border-radius: 14px; background: #fbf4df; box-shadow: 0 3px 0 #c8b088; }
.dojo-rank-text { display: flex; flex-direction: column; gap: 2px; font-size: 0.75rem; color: #5a3e28; }
.dojo-rank-text b { font-size: 0.95rem; color: #3a2414; }
.dojo-belt { position: relative; display: inline-block; width: 46px; height: 12px; border-radius: 3px; background: var(--belt); box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.35); }
.dojo-belt::after { content: ''; position: absolute; left: 50%; top: -3px; width: 10px; height: 18px; translate: -50% 0; border-radius: 3px; background: var(--knot); }
.dojo-belt.dim { opacity: 0.3; }
.dojo-belts { grid-column: 1 / 3; display: flex; justify-content: space-between; gap: 4px; padding-top: 6px; }
.dojo-belts .dojo-belt { width: 13%; }
.dojo-card { display: flex; flex-direction: column; gap: 6px; }
.dojo-vs { display: flex; align-items: center; justify-content: center; gap: 14px; }
.dojo-vs img { width: 72px; height: 72px; object-fit: contain; }
.dojo-vs-word { font-size: 1.1rem; font-weight: 900; color: #c8302a; letter-spacing: 0.08em; }
.dialog.craft .dojo-goal { color: #b02818; font-weight: bold; }
.dojo-no { flex: none; width: 26px; height: 26px; display: grid; place-items: center; border-radius: 50%; background: #3a2414; color: #ffe6a8; font-size: 0.75rem; }
.dojo-row.locked { opacity: 0.6; }
.dojo-row .craft-pill.made { background: #f0c040; color: #3a2414; }
.dialog.craft .dojo-gifts .craft-label { color: #ffe6a8; margin: 0 0 4px; }
.dojo-gifts { display: flex; flex-wrap: wrap; gap: 6px; }
.dojo-gifts .craft-label { width: 100%; }
.dojo-gift { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 62px; opacity: 0.45; filter: grayscale(0.8); }
.dojo-gift.got { opacity: 1; filter: none; }
.dojo-gift-name { font-size: 0.75rem; line-height: 1.1; text-align: center; color: #fbe8c0; }
.dialog.craft.dojo-win .craft-list { min-height: 90px; max-height: 26dvh; }

/* ---------- Kurt's Workshop's two repeatable shelves, Held berries and Run kit (2026-10-15): six tabs, two rows of three ---------- */
.craft-tabs { grid-template-columns: repeat(3, 1fr); row-gap: 12px; }
.held-row.used { opacity: 0.6; }
/* Kurt's bench made compact (2026-10-28, the user's ask: the tabs and the recipe card took most of a phone's height,
   leaving the shelf a row and a half): slimmer tabs, a smaller picture, no MATERIALS label, a smaller Make, and his
   line no longer repeats the card. Scoped to .kurt: the Garden and the dojo share .dialog.craft. */
.dialog.craft.kurt { gap: 8px; padding: 12px; }
.dialog.craft.kurt .craft-head h2 { font-size: 0.95rem; }
@media (max-width: 480px) { .dialog.craft.kurt .craft-sub { display: none; } }
.dialog.craft.kurt .craft-talk { margin-top: 6px; padding: 12px 12px 8px; }
.dialog.craft.kurt .craft-say { min-height: 0; line-height: 1.4; }
.dialog.craft.kurt .craft-tabs { row-gap: 8px; gap: 5px; }
.dialog.craft.kurt .craft-tab { gap: 0; padding: 3px 2px 4px; border-radius: 8px; line-height: 1.3; }
.dialog.craft.kurt .craft-dot { top: -8px; right: -5px; min-width: 18px; height: 18px; padding: 0 4px; }
.dialog.craft.kurt .craft-card { padding: 8px 10px 10px; }
.dialog.craft.kurt .craft-top { gap: 10px; align-items: flex-start; }
.dialog.craft.kurt .craft-pic { width: 52px; height: 52px; }
.dialog.craft.kurt .craft-pic > * { width: 40px; height: 40px; }
.dialog.craft.kurt .craft-pic .wshop-glyph { font-size: 1.8rem; }
.dialog.craft.kurt .craft-name { margin: 0 0 1px; font-size: 0.85rem; }
.dialog.craft.kurt .craft-goes { margin: 0 0 2px; }
.dialog.craft.kurt .craft-text { line-height: 1.3; }
.dialog.craft.kurt .craft-mats { margin-top: 8px; gap: 5px; }
.dialog.craft.kurt .craft-mat { row-gap: 3px; padding: 4px 7px; grid-template-rows: auto 4px; }
.dialog.craft.kurt .craft-mat-ico { font-size: 1.2rem; }
.dialog.craft.kurt .craft-bar { height: 4px; }
.dialog.craft.kurt .craft-make { margin-top: 7px; padding: 5px 16px; min-width: 120px; }

/* ---------- held berries' first-time tips (2026-10-16): the battle's LCD note on the first one eaten, the dock's Items key pulsing ---------- */
.held-tip {
  position: fixed; z-index: 40; top: calc(env(safe-area-inset-top) + 70px); left: 50%; translate: -50% 0; width: min(330px, calc(100vw - 32px));
  padding: 8px 12px; border: 3px solid var(--shell-rim, #1f3a14); border-radius: 8px; background: #b6d68e; color: #1f3a14;
  font: 0.75rem/1.6 var(--pixel-font); text-align: left; box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.12), 0 6px 16px rgba(0, 0, 0, 0.4);
  cursor: pointer; animation: heldTipIn 0.35s ease-out both;
}
.held-tip.calm { animation: none; }
@keyframes heldTipIn { from { opacity: 0; translate: -50% -10px; } }
.mdex-btn.berry-pulse { animation: berryPulse 1.2s ease-in-out 3; }
@keyframes berryPulse { 50% { box-shadow: 0 0 0 3px #ffd860, 0 0 14px rgba(255, 216, 96, 0.9); scale: 1.08; } }

/* the Safari Zone's locked door (js/safarilock.js): a bar per biome on the device's LCD */
.safari-lock-dialog { width: min(360px, calc(100vw - 32px)); }
.safari-lock-dialog .sl-why { font-size: 0.75rem; line-height: 1.6; }
.sl-bars { list-style: none; margin: 4px 0 10px; padding: 0; display: grid; gap: 10px; }
.sl-head { display: flex; justify-content: space-between; gap: 8px; margin-bottom: 4px; color: #1f3a14; font-size: 0.75rem; }
.sl-count { white-space: nowrap; }
.sl-bar { height: 12px; border: 2px solid #1f3a14; border-radius: 6px; background: #e4f0cc; overflow: hidden; }
.sl-fill { display: block; height: 100%; background: #3a7a28; transition: width 0.5s ease-out; }
.sl-row.done .sl-fill { background: #c89a20; }
.sl-row.done .sl-count { color: #6a4a00; }
.safari-lock-dialog .sl-total-line { font-size: 0.75rem; color: #1f3a14; }
@media (prefers-reduced-motion: reduce) { .sl-fill { transition: none; } }
.sl-toast {
  position: fixed; top: max(12px, env(safe-area-inset-top)); left: 50%; z-index: 1000; width: min(300px, calc(100vw - 32px));
  transform: translateX(-50%); padding: 8px 10px 10px; border: 2px solid #1f3a14; border-radius: 10px; background: #c4dca0;
  box-shadow: 0 0 0 3px var(--shell-rim, #8a1c1c), 0 4px 0 3px var(--shell-deep, #5a0e0e); color: #1f3a14; font: inherit; text-align: left;
  cursor: pointer; animation: slToastIn 0.35s ease-out both;
}
.sl-toast .sl-kicker { display: block; margin-bottom: 6px; font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; text-align: center; }
.sl-toast .sl-fill { transition-duration: 0.9s; transition-delay: 0.3s; }
.sl-toast.done .sl-fill { background: #c89a20; }
.sl-toast.out { animation: slToastOut 0.4s ease-in both; }
@keyframes slToastIn { from { transform: translate(-50%, -140%); } }
@keyframes slToastOut { to { transform: translate(-50%, -140%); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .sl-toast, .sl-toast.out { animation: none; } .sl-toast .sl-fill { transition: none; } }

/* a wild shiny in a Safari room (js/data/shinies.js): a gold rim and tag on its plate, sparkles on it all fight, a gold
   banner as it appears, a ball that shakes in gold, and a gold catch box */
#enemy-plate.shiny { box-shadow: 0 0 0 2px #f8d030, 0 0 14px rgba(248, 208, 48, 0.6); }
#enemy-plate.shiny #enemy-name { color: #a07000; }
.shiny-tag {
  flex: none; margin-left: auto; padding: 2px 5px 1px; border-radius: 3px;
  background: #f8d030; color: #4a3000; font-size: 0.75rem; line-height: 1.2; text-transform: uppercase;
}
.shiny-tag[hidden] { display: none; }
.shiny-aura { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.shiny-twinkle, .gold-spark, .sig-twinkle {
  position: absolute; background: #fff3b8;
  clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%);
}
.shiny-twinkle { width: 16px; height: 16px; opacity: 0; animation: shinyTwinkle 2.4s ease-in-out infinite; }
.shiny-twinkle.t0 { left: 18%; top: 22%; }
.shiny-twinkle.t1 { left: 72%; top: 14%; animation-delay: 0.5s; width: 12px; height: 12px; }
.shiny-twinkle.t2 { left: 80%; top: 58%; animation-delay: 1.1s; }
.shiny-twinkle.t3 { left: 10%; top: 64%; animation-delay: 1.6s; width: 12px; height: 12px; background: #ffd34a; }
.shiny-twinkle.t4 { left: 46%; top: 6%; animation-delay: 2s; width: 10px; height: 10px; background: #ffd34a; }
@keyframes shinyTwinkle { 0%, 100% { opacity: 0; transform: scale(0.3) rotate(0deg); } 50% { opacity: 1; transform: scale(1) rotate(45deg); } }
.enemy-portrait:is(.defeated, .sinking, .captured, .ran) .shiny-aura { display: none; }
.shiny-banner {
  position: absolute; left: 0; right: 0; top: 30%; z-index: 7;
  display: flex; justify-content: center; align-items: center; gap: 10px;
  padding: 9px 16px;
  background: linear-gradient(90deg, transparent, rgba(74, 46, 0, 0.88) 12%, rgba(74, 46, 0, 0.88) 88%, transparent);
  border-block: 2px solid #f8d030;
  color: #ffe590; text-align: center; text-transform: uppercase; text-shadow: 2px 2px 0 #3a2400;
  font-family: var(--pixel-font); font-synthesis-weight: none;
  pointer-events: none;
}
.shiny-banner strong { font-weight: normal; font-size: clamp(0.8rem, 3.8vw, 1.25rem); }
.shiny-banner-star { font-size: 1.1rem; }
.shiny-banner.show { animation: shinyBannerIn 2.6s ease-out both; }
@keyframes shinyBannerIn { 0% { transform: translateX(-110%); } 12%, 86% { transform: none; } 100% { transform: translateX(110%); } }
.thrown-ball.gold .ball3d { filter: drop-shadow(0 0 3px #ffd34a) drop-shadow(0 0 7px rgba(255, 211, 74, 0.75)); }
.thrown-ball.gold.caught .ball3d { filter: brightness(0.6) drop-shadow(0 0 3px #ffd34a); }
.gold-spark { left: -5px; top: -5px; width: 10px; height: 10px; background: #ffe27a; opacity: 0; animation: goldSpark 0.8s ease-out var(--delay) forwards; }
@keyframes goldSpark { 0% { opacity: 1; transform: translate(0, 0) scale(0.6); } 100% { opacity: 0; transform: translate(var(--dx), -48px) scale(1.2); } }
#reward-screen .reward-log.shiny-catch {
  border-color: #f8d030;
  box-shadow: 0 0 0 2px #6a4a00, inset 0 0 0 2px #6a4a00, 0 0 18px rgba(248, 208, 48, 0.65), 3px 3px 0 2px rgba(0, 0, 0, 0.4);
}
/* a duo's deck window: each partner's deck under its name (deckpreview.js) */
.deck-group-head {
  grid-column: 1 / -1; padding: 6px 10px; border-radius: 6px; background: #2c3866; color: #fff;
  font-family: var(--pixel-font); font-size: 0.85rem; text-shadow: 1px 1px 0 #10142a;
}

/* the type badges (js/type-badge.js) where an emoji stood: sized to the mark they sit in */
.map-match .type-badge, .map-revealed-type .type-badge { width: 16px; height: 16px; }
.card-type .type-badge { width: 1.15em; height: 1.15em; margin-top: -0.1em; }
.xr-wicon .type-badge { width: 1.2em; height: 1.2em; }
