@font-face {
  font-family: "Press Start 2P";
  src: url("assets/fonts/PressStart2P.ttf") format("truetype");
  font-display: swap;
}

@font-face {
  font-family: "VT323";
  src: url("assets/fonts/VT323.ttf") format("truetype");
  font-display: swap;
}

:root {
  --px: "Press Start 2P", monospace;
  --vt: "VT323", monospace;

  --paper: #f8efd8;
  --paper-2: #efe3c2;
  --paper-ink: #2a251a;
  --paper-dim: #6b6250;

  --c-normal: #a8a77a; --c-fire: #f08030; --c-water: #6390f0;
  --c-electric: #f7d02c; --c-grass: #7ac74c; --c-ice: #96d9d6;
  --c-fighting: #d3425f; --c-poison: #b567ce; --c-ground: #e2bf65;
  --c-flying: #a98ff3; --c-psychic: #f95587; --c-bug: #a6b91a;
  --c-rock: #b6a136; --c-ghost: #7975d4; --c-dragon: #6f35fc;
  --c-dark: #75574c; --c-steel: #b7b7ce; --c-fairy: #d685ad;
}

/* ---------- Handheld-screen palette (bright, reads on any wallpaper) ----------
   JS sets --wall, --scene, --accent, --accent-ink and --field per wallpaper. */

body {
  --field: #cbb78a;
  --wall: none;
  --scene: none;
  --accent: #e5484d;
  --accent-ink: #fff;

  --panel: color-mix(in srgb, var(--field) 14%, #f7f2e6);
  --panel-2: color-mix(in srgb, var(--field) 22%, #ece3cd);
  --edge: #37301f;
  --edge-hi: #fffdf3;
  --ink: #2b2519;
  --ink-dim: #7a7058;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

/* Site-wide: on iOS Safari the rubber-band overscroll bounce reveals blank
   space (or whatever sits behind a fixed overlay) past the top/bottom edge of
   the page. overscroll-behavior kills that bounce everywhere, cheaply -- no
   position:fixed body-locking hack needed (that trick pins the ENTIRE page as
   one compositor layer, which is expensive/crash-prone on a page this long). */
html, body { overscroll-behavior-y: none; }

body {
  margin: 0;
  font-family: var(--vt);
  color: var(--ink);
  background: var(--field) var(--wall) repeat top left;
  background-size: 96px auto;
  min-height: 100vh;
  transition: background-color 0.4s;
}

body.smooth-wall { background-size: cover; background-repeat: no-repeat; background-attachment: fixed; }

/* Particle field sits above the wallpaper, below the cards. */
#fx {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

img { image-rendering: pixelated; }
img.smooth, .smooth { image-rendering: auto; }

/* ---------- Pixel building blocks ---------- */

.pxbox {
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  box-shadow:
    inset 0 0 0 2px var(--edge-hi),
    4px 4px 0 rgba(0, 0, 0, 0.35);
}

/* ---------- Top bar ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--panel-2);
  border-bottom: 3px solid var(--edge);
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.3);
  /* Extend the opaque header up into the iOS status-bar / notch zone so scrolled
     content can't peek through it there. Zero on every device without a safe
     area (env resolves to 0px), so this changes nothing off iOS. */
  padding-top: env(safe-area-inset-top, 0px);
}

.topbar-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.brand-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.brand { display: flex; align-items: center; gap: 10px; }

.brand h1 {
  margin: 0;
  font-family: var(--px);
  font-size: 16px;
  letter-spacing: 0.04em;
  text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.4);
}

/* The wordmark logo replaces the "Bill's PC" text but keeps the <h1> for a11y.
   It's a high-res smooth render (not a pixel sprite), so let it downscale
   smoothly; the shadow/outline are baked into the artwork. */
.brand-logo {
  line-height: 0;
  text-shadow: none;
}
.brand-logo img {
  display: block;
  height: 30px;
  width: auto;
}

.brand-sprite {
  width: 34px;
  height: 34px;
  object-fit: contain;
  image-rendering: pixelated;
  /* Bill's art sits low in its frame, so nudge the sprite up to optically
     center him against the logo/buttons (boxes are already centered). */
  transform: translateY(-2px);
}

.hdr-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }

/* Desktop: .filters is transparent to layout, so the dex-tabs / controls / type
   rows sit directly in the header exactly as before. Mobile turns it into a
   collapsible overlay (see media query). */
.filters { display: contents; }

/* Shown only on mobile: the hamburger and the relocated search+shiny bar. */
.mobile-only { display: none; }
.mobile-primary { display: none; }

.count {
  font-family: var(--px);
  font-size: 8px;
  line-height: 1.6;
  color: var(--ink-dim);
  text-align: right;
  max-width: 300px;
}

/* Counter sits just right of the "Bill's PC" logo. */
.brand .count {
  align-self: center;
  margin-left: 2px;
  text-align: left;
  white-space: nowrap;
}

/* ---------- Theme picker ---------- */

/* ---------- Wallpaper picker ---------- */

.wp-wrap { position: relative; }

.wp-btn { display: flex; align-items: center; gap: 7px; }

/* Trim the vertical padding (higher specificity than .px-btn) so the swatch
   doesn't make this button taller than the plain buttons beside it. */
.px-btn.wp-btn { padding: 6px 12px; }

.wp-swatch {
  width: 18px;
  height: 15px;
  border: 2px solid var(--edge);
  background-size: cover;
  background-position: center;
  image-rendering: pixelated;
}

.wp-pop[hidden] { display: none; }

.wp-pop {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 120;
  width: 320px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  padding: 12px;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 4px;
  box-shadow: inset 0 0 0 2px var(--edge-hi), 6px 6px 0 rgba(0, 0, 0, 0.4);
  animation: pop-in 0.18s ease-out both;
}

.wp-opt {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 5px 4px 4px;
  background: none;
  border: 2px solid transparent;
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out;
}

.wp-opt img {
  width: 100%;
  height: 42px;
  object-fit: cover;
  object-position: top;
  border: 2px solid var(--edge);
  image-rendering: pixelated;
}

.wp-opt span {
  font-family: var(--px);
  font-size: 7px;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.wp-opt:hover { transform: translateY(-2px); }
.wp-opt:hover span { color: var(--ink); }

.wp-opt.on { border-color: var(--accent); }
.wp-opt.on span { color: var(--ink); }

/* ---------- Companion picker ---------- */

/* Same shape as the wallpaper picker, but the swatch/options are PMD portraits
   rather than scenery. "None" reuses Mew's portrait, greyed out. */
.fol-wrap { position: relative; }

.fol-btn { display: flex; align-items: center; gap: 7px; }
.px-btn.fol-btn { padding: 6px 12px; }

.fol-swatch {
  width: 18px;
  height: 15px; /* match .wp-swatch so the button isn't taller than its neighbours */
  border: 2px solid var(--edge);
  background-size: cover;
  background-position: center;
  image-rendering: pixelated;
}

.fol-swatch.dim { filter: grayscale(1) opacity(0.45); }

.fol-pop[hidden] { display: none; }

.fol-pop {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 120;
  width: 288px;
  display: grid;
  /* minmax(0, ...) rather than a bare 1fr: a plain 1fr can't shrink below the
     label's min-content width, which let the longest name (JIRACHI) steal space
     and squeeze the shorter ones into slivers. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  padding: 12px;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 4px;
  box-shadow: inset 0 0 0 2px var(--edge-hi), 6px 6px 0 rgba(0, 0, 0, 0.4);
  animation: pop-in 0.18s ease-out both;
}

.fol-opt {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 5px 4px 4px;
  background: none;
  border: 2px solid transparent;
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out;
}

/* A fixed square, not width:100%. Keeps every option the same shape whatever
   its label. 44px = the 40px portrait + 2px border each side (border-box), so
   the pixel art still renders 1:1 instead of at a blurry fractional scale. */
.fol-opt img {
  width: 44px;
  height: 44px;
  object-fit: contain;
  border: 2px solid var(--edge);
  background: var(--panel);
  image-rendering: pixelated;
}

.fol-opt img.dim { filter: grayscale(1) opacity(0.45); }

.fol-opt span {
  font-family: var(--px);
  font-size: 7px;
  text-transform: uppercase;
  color: var(--ink-dim);
  white-space: nowrap;
}

.fol-opt:hover { transform: translateY(-2px); }
.fol-opt:hover span { color: var(--ink); }

.fol-opt.on { border-color: var(--accent); }
.fol-opt.on span { color: var(--ink); }


/* ---------- Dex tabs ---------- */

.dex-tabs { display: flex; gap: 6px; flex-wrap: wrap; }

.dex-tab {
  font-family: var(--px);
  font-size: 9px;
  padding: 9px 13px 8px;
  color: var(--ink-dim);
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, box-shadow 0.12s ease-out, color 0.12s;
}

.dex-tab:hover { color: var(--ink); transform: translate(-1px, -1px); box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.3); }
.dex-tab:active { transform: translate(1px, 1px); box-shadow: none; }

.dex-tab.on {
  color: var(--accent-ink);
  background: var(--accent);
  box-shadow: inset 2px 2px 0 rgba(255, 255, 255, 0.25), 3px 3px 0 rgba(0, 0, 0, 0.3);
}

/* On desktop the action buttons (sprite toggle/wallpaper/team/mew/guide/shiny)
   sit on the dex-tabs row; the sprite toggle starts the right-aligned group so
   the count stays next to "Other" on the left. */
.dex-tabs { align-items: center; }
.dex-tabs > .spr-toggle { margin-left: auto; }

/* Sprite/HOME toggle: a plain square icon button, no label. */
.spr-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  flex: 0 0 auto;
}
.spr-toggle svg { width: 16px; height: 16px; }
.spr-toggle svg rect { fill: currentColor; }

/* Shiny toggle gets a golden sparkle when active. */
.shiny-tab.on {
  color: #3a2c00;
  background: linear-gradient(#ffe485, #f5c518);
  box-shadow: inset 2px 2px 0 rgba(255, 255, 255, 0.45), 3px 3px 0 rgba(0, 0, 0, 0.3);
}

/* ---------- "Other" category picker (dex-tabs row) ---------- */

.other-wrap { position: relative; display: inline-flex; }

.other-pop[hidden] { display: none; }

.other-pop {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 120;
  width: 230px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 4px;
  box-shadow: inset 0 0 0 2px var(--edge-hi), 6px 6px 0 rgba(0, 0, 0, 0.4);
  animation: pop-in 0.18s ease-out both;
}

.other-opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 10px 8px;
  font-family: var(--px);
  font-size: 9px;
  color: var(--ink-dim);
  background: var(--panel);
  border: 2px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, color 0.12s, background 0.12s;
}

.other-opt:hover { color: var(--ink); transform: translate(-1px, -1px); }

.other-opt.on {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--edge);
}

.other-all { color: var(--ink); }
.oc-count { font-size: 8px; color: var(--ink-dim); }
.other-opt.on .oc-count { color: var(--accent-ink); }

/* ---------- Controls ---------- */

.controls { display: flex; gap: 8px; flex-wrap: wrap; align-items: stretch; }

.search-wrap { position: relative; flex: 1 1 200px; min-width: 180px; }

.search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  translate: 0 -50%;
  width: 14px;
  height: 14px;
  color: var(--ink-dim);
  pointer-events: none;
}

#search, #tlSearch, .select, .px-btn {
  font-family: var(--vt);
  font-size: 19px;
  color: var(--ink);
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  outline: none;
}

#search, #tlSearch {
  width: 100%;
  padding: 7px 12px 6px 32px;
  transition: box-shadow 0.12s;
}

#search::placeholder, #tlSearch::placeholder { color: var(--ink-dim); }
#search:focus, #tlSearch:focus { box-shadow: inset 0 0 0 2px var(--accent); }

.select {
  appearance: none;
  -webkit-appearance: none;
  padding: 7px 30px 6px 12px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7'%3E%3Cpath d='M0 0h12L6 7z' fill='%23888'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  cursor: pointer;
  transition: transform 0.12s ease-out, box-shadow 0.12s;
}

.select:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.3); }
.select:focus { box-shadow: inset 0 0 0 2px var(--accent); }

.px-btn, .clear-btn {
  font-family: var(--px);
  font-size: 9px;
  padding: 9px 12px;
  color: var(--ink);
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, box-shadow 0.12s ease-out;
}

.px-btn:hover, .clear-btn:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.3); }
.px-btn:active, .clear-btn:active { transform: translate(1px, 1px); box-shadow: none; }

.clear-btn { color: #fff; background: #d3425f; border-color: #47101d; }

.px-btn.on {
  color: var(--accent-ink);
  background: var(--accent);
  box-shadow: inset 2px 2px 0 rgba(255, 255, 255, 0.25);
}

/* Donate: gold, with a gentle glow pulse so it catches the eye without shouting.
   An <a>, so it needs the flex/text-decoration reset to sit like the buttons. */
.donate-btn {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: #3a2c05;
  background: linear-gradient(180deg, #ffe27a, #f4c517);
  border-color: #7a5c0f;
  animation: donate-pulse 2.2s ease-in-out infinite;
}
@keyframes donate-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 197, 24, 0); }
  50%      { box-shadow: 0 0 9px 1px rgba(245, 197, 24, 0.8); }
}
.donate-btn:hover {
  transform: translate(-1px, -1px);
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.3), 0 0 9px 1px rgba(245, 197, 24, 0.7);
  filter: brightness(1.06);
  animation: none;
}
.donate-btn:active { transform: translate(1px, 1px); box-shadow: none; }
/* Respect reduced-motion: drop the pulse, keep the gold. */
@media (prefers-reduced-motion: reduce) { .donate-btn { animation: none; } }

/* ---------- Type chips ---------- */

/* Chips stretch to fill the row edge-to-edge (flush with the controls above),
   sitting on one line and wrapping to more flush rows on narrow viewports. */
.type-row { display: flex; gap: 5px; flex-wrap: wrap; }

.type-chip {
  --tc: #999;
  flex: 1 1 auto;
  text-align: center;
  padding: 6px 6px 5px;
  font-family: var(--px);
  font-size: 8px;
  text-transform: uppercase;
  color: var(--ink-dim);
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, box-shadow 0.12s ease-out, background 0.12s, color 0.12s;
}

.type-chip:hover { color: var(--ink); transform: translate(-1px, -2px); box-shadow: 2px 3px 0 rgba(0, 0, 0, 0.3); }
.type-chip:active { transform: translate(1px, 1px); box-shadow: none; }

.type-chip.on {
  color: #16130c;
  background: var(--tc);
  box-shadow: inset 2px 2px 0 rgba(255, 255, 255, 0.35), 2px 2px 0 rgba(0, 0, 0, 0.35);
}

/* Two types already picked: the rest go inert (no third type exists). */
.type-chip.chip-off {
  opacity: 0.3;
  pointer-events: none;
}

/* ---------- Grid ---------- */

main { max-width: 1280px; margin: 0 auto; padding: 24px; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(156px, 1fr));
  gap: 16px;
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px 10px 12px;
  font-family: inherit;
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  box-shadow: inset 0 0 0 2px var(--edge-hi), 4px 4px 0 rgba(0, 0, 0, 0.35);
  cursor: pointer;
  content-visibility: auto;
  contain-intrinsic-size: 208px;
  transition: transform 0.13s ease-out, box-shadow 0.13s ease-out;
  animation: pop-in 0.28s cubic-bezier(0.25, 1.4, 0.5, 1) both;
  animation-delay: calc(var(--i, 0) * 12ms);
}

@keyframes pop-in {
  from { opacity: 0; transform: scale(0.88) translateY(10px); }
  to { opacity: 1; transform: none; }
}

.card:hover {
  transform: translate(-3px, -3px);
  box-shadow: inset 0 0 0 2px var(--edge-hi), 8px 8px 0 rgba(0, 0, 0, 0.35);
}

.card:active { transform: translate(1px, 1px); box-shadow: inset 0 0 0 2px var(--edge-hi), 2px 2px 0 rgba(0, 0, 0, 0.35); }

.card .art {
  height: 96px;
  display: grid;
  place-items: center;
}

.card img { object-fit: contain; }

/* HOME (3D) renders fill their frame (~90%), while the Gen 1-5 pixel sprites
   only occupy ~40-70% of theirs, so the HOME renders looked much bigger in the
   grid. Shrink the smooth (HOME / form / Z-A) renders toward the pixel sprites'
   footprint. Uses the individual `scale` property (relative to the sprite's own
   size, so it tracks the pixel sprites at any viewport). Kept off `transform`
   so the hover bounce, which animates translateY, doesn't reset it. */
.card img.smooth { scale: 0.75; }

.card:hover img { animation: sprite-bounce 0.5s steps(2) infinite; }

@keyframes sprite-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

.card .num {
  position: absolute;
  top: 8px;
  right: 10px;
  font-family: var(--px);
  font-size: 8px;
  color: var(--ink-dim);
}

.card .name {
  margin-top: 8px;
  font-family: var(--px);
  font-size: 9px;
  line-height: 1.5;
  text-align: center;
  color: var(--ink);
}

.card .types { display: flex; gap: 4px; margin-top: 8px; }

.type-badge {
  --tc: #888;
  padding: 4px 6px 3px;
  font-family: var(--px);
  font-size: 7px;
  text-transform: uppercase;
  color: #16130c;
  background: var(--tc);
  border: 2px solid var(--edge);
  border-radius: 2px;
  box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.35);
}

/* ---------- Empty state ---------- */

.empty { text-align: center; padding: 80px 0; }
.empty-title { font-family: var(--px); font-size: 14px; margin: 0 0 10px; }
.empty-sub { font-size: 20px; color: var(--ink-dim); margin: 0; }

/* ---------- Detail dialog ---------- */

.detail {
  width: min(880px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  padding: 0;
  border: 4px solid var(--edge);
  border-radius: 4px;
  background: var(--panel);
  color: var(--ink);
  box-shadow: inset 0 0 0 3px var(--edge-hi), 10px 10px 0 rgba(0, 0, 0, 0.45);
  overflow: hidden;
}

.detail::backdrop { background: rgba(8, 6, 4, 0.65); }

.detail[open] { animation: dialog-pop 0.24s cubic-bezier(0.25, 1.4, 0.5, 1) both; }
.detail[open]::backdrop { animation: fade-in 0.2s ease both; }

@keyframes dialog-pop {
  from { opacity: 0; transform: scale(0.88) translateY(16px); }
  to { opacity: 1; transform: none; }
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.detail-body {
  display: grid;
  grid-template-columns: 310px 1fr;
  max-height: calc(100vh - 72px);
  overflow: auto;
}

.d-left {
  position: sticky;
  top: 0;
  align-self: start;
  padding: 26px 20px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.d-hero-box {
  height: 200px;
  display: grid;
  place-items: center;
}

.d-hero {
  width: 192px;
  height: 192px;
  object-fit: contain;
  image-rendering: pixelated;
  animation: hero-pop 0.3s cubic-bezier(0.25, 1.5, 0.5, 1) both;
}

@keyframes hero-pop {
  from { opacity: 0; transform: scale(0.7); }
  to { opacity: 1; transform: none; }
}

.d-num { font-family: var(--px); font-size: 9px; color: var(--ink-dim); margin-top: 10px; }
.d-name { font-family: var(--px); font-size: 17px; margin: 6px 0 0; }
.d-genus { font-size: 19px; color: var(--ink-dim); margin-top: 4px; }

.d-types { display: flex; gap: 6px; margin-top: 10px; }
.d-types .type-badge { font-size: 8px; padding: 5px 8px 4px; }

/* ---------- Detail stat block ---------- */

/* Sits between the types and the sprite thumbs. --tc is the species' primary
   type colour, already set on .detail-body by renderVariant. */
.d-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  width: 100%;
  margin-top: 14px;
  padding: 10px;
  background: var(--tc);
  border: 3px solid var(--edge);
  border-radius: 4px;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.25);
}

.d-fact { display: flex; flex-direction: column; gap: 3px; }

.d-fact-k {
  font-family: var(--px);
  font-size: 7px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.35);
}

.d-fact-v {
  font-size: 16px;
  color: #fff;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.35);
}

.d-sec-h {
  align-self: flex-start;
  font-family: var(--px);
  font-size: 8px;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 14px 0 7px;
}

/* Two columns spanning the full width of the height/weight bar above: normal
   abilities left, hidden right. Multiples stack vertically inside their column. */
.d-abils {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
  gap: 6px 8px;
  width: 100%;
  margin-top: 14px; /* matches the leading on .d-sec-h, which this grid replaces */
}

.d-abil-col { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.d-abil-col .d-sec-h { margin: 0 0 1px; }

.ab-chip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  width: 100%;
  padding: 6px 8px;
  font-family: inherit;
  font-size: 13px;
  text-align: left;
  color: var(--ink);
  background: var(--panel-2);
  border: 2px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out;
}

.ab-chip > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.ab-chip:hover { transform: translateY(-2px); }
.ab-chip.hidden-ab { border-style: dashed; }
.ab-chip.on { border-color: var(--accent); }

/* Non-interactive chips: a new Z-A ability with no blurb, or an unrevealed one. */
.ab-chip.static { cursor: default; }
.ab-chip.static:hover { transform: none; }
.ab-chip.unk { color: var(--ink-dim); font-style: italic; }
.d-fact-v.unk { color: var(--ink-dim); }

/* Spans both columns so the blurb gets full width, not half. */
.ab-pop-slot { grid-column: 1 / -1; }
.ab-pop-slot:empty { display: none; }

/* The "?" affordance that hints the blurb is one click away. */
.ab-q {
  display: grid;
  place-items: center;
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
  font-family: var(--px);
  font-size: 7px;
  color: var(--panel-2);
  background: var(--ink-dim);
  border-radius: 50%;
}

.ab-chip:hover .ab-q { background: var(--accent); color: var(--accent-ink); }

.ab-pop {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 9px 10px;
  background: var(--panel);
  border: 2px solid var(--edge);
  border-radius: 3px;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.3);
  animation: pop-in 0.15s ease-out both;
}

.ab-pop b { font-family: var(--px); font-size: 8px; text-transform: uppercase; }
.ab-pop span { font-size: 14px; line-height: 1.45; color: var(--ink-dim); }
.ab-pop .dim { font-style: italic; }

.d-weaks { display: flex; flex-wrap: wrap; gap: 5px; width: 100%; }

.weak-badge {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 7px 4px;
  font-family: var(--px);
  font-size: 8px;
  text-transform: uppercase;
  color: #fff;
  background: var(--tc);
  border: 2px solid var(--edge);
  border-radius: 3px;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.3);
}

.weak-badge b { font-size: 7px; opacity: 0.85; }

/* Chips are a FIXED width rather than flex-grow: a wrapped row with fewer chips
   would otherwise stretch them larger than the rows above (Eevee's last row).
   Card size wins over edge alignment, though at 78px a three-stage family still
   lands flush with the sprite grid: 3*78 + 2*10 (arrows) + 4*4 (gaps) = 270. */
.d-evos {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: center;
  gap: 4px;
  width: 100%;
}

.evo-arrow {
  display: flex;
  flex: 0 0 10px;
  width: 10px;
  align-items: center;
  justify-content: center;
  font-family: var(--px);
  font-size: 10px;
  color: var(--ink-dim);
}

.evo-chip {
  display: flex;
  flex: 0 0 78px;
  width: 78px;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 5px 3px 4px;
  background: var(--panel-2);
  border: 2px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out;
}

/* Branching families (Eevee, Charcadet, Ralts) stack their stages vertically
   with a turned arrow between them, so siblings read as parallel options rather
   than as a sequence. Deliberately distinct from the linear single-row form. */
.d-evos.branched { flex-direction: column; align-items: center; gap: 2px; }

.evo-stage {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: 4px;
  width: 100%;
}

.evo-arrow.down {
  flex: 0 0 auto;
  width: auto;
  transform: rotate(90deg);
  padding: 3px 0;
}

.evo-chip img { width: 40px; height: 40px; object-fit: contain; image-rendering: pixelated; }
.evo-chip span {
  font-family: var(--px);
  font-size: 6px;
  color: var(--ink-dim);
  text-align: center;
  line-height: 1.3;
  width: 100%;
  overflow-wrap: anywhere; /* long names (e.g. Gigantamax forms) shouldn't widen the chip */
}
.evo-chip:hover { transform: translateY(-2px); }
.evo-chip:hover span { color: var(--ink); }

/* The species you're already looking at: highlighted and inert. */
.evo-chip.on { border-color: var(--accent); cursor: default; }
.evo-chip.on span { color: var(--ink); }
.evo-chip.on:hover { transform: none; }

.d-thumbs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  width: 100%;
}

.d-thumb {
  aspect-ratio: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 6px 2px 4px;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, box-shadow 0.12s;
}

.d-thumb:hover { transform: translate(-1px, -1px); box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3); }

.d-thumb.on { box-shadow: inset 0 0 0 2px var(--accent); }

.d-thumb img { width: 42px; height: 42px; object-fit: contain; }
.d-thumb .tl { font-family: var(--px); font-size: 6px; text-transform: uppercase; color: var(--ink-dim); }

.d-cat {
  font-family: var(--px);
  font-size: 7px;
  color: var(--accent-ink);
  background: var(--accent);
  border: 2px solid var(--edge);
  border-radius: 2px;
  padding: 2px 4px 1px;
  margin-left: 4px;
  vertical-align: middle;
}

/* ---------- Form switcher ---------- */

.d-forms-h {
  width: 100%;
  margin: 18px 0 8px;
  font-family: var(--px);
  font-size: 9px;
  text-transform: uppercase;
  color: var(--ink-dim);
  border-top: 2px dashed var(--edge);
  padding-top: 12px;
}

.d-forms {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  width: 100%;
}

.form-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 2px 4px;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, box-shadow 0.12s;
}

.form-chip img { width: 46px; height: 46px; object-fit: contain; image-rendering: auto; }
.form-chip span {
  font-family: var(--px);
  font-size: 6px;
  line-height: 1.4;
  text-align: center;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.form-chip:hover { transform: translate(-1px, -1px); box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3); }
.form-chip:hover span { color: var(--ink); }
.form-chip.on { box-shadow: inset 0 0 0 2px var(--accent); }
.form-chip.on span { color: var(--ink); }

/* Grid card "has forms" marker */
.card .forms-tag {
  position: absolute;
  top: 8px;
  left: 10px;
  font-family: var(--px);
  font-size: 7px;
  color: var(--ink-dim);
}

/* Entries read like a paper dex page in every theme */
.d-right {
  padding: 16px 24px 20px;
  background: var(--paper);
  color: var(--paper-ink);
  border-left: 3px solid var(--edge);
}

.d-right h3 {
  margin: 0 0 14px;
  font-family: var(--px);
  font-size: 10px;
  text-transform: uppercase;
  color: var(--paper-ink);
  border-bottom: 3px solid var(--paper-ink);
  padding-bottom: 8px;
}

/* ---------- Detail tabs ---------- */

.d-tabs {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  gap: 5px;
  padding: 8px 0 8px;
  margin-bottom: 8px;
  background: var(--paper);
  border-bottom: 3px solid var(--paper-ink);
}

.d-tab {
  font-family: var(--px);
  font-size: 9px;
  padding: 8px 11px 7px;
  color: var(--paper-dim);
  background: var(--paper-2);
  border: 3px solid var(--paper-ink);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, color 0.12s;
}

.d-tab:hover { color: var(--paper-ink); transform: translateY(-1px); }
.d-tab.on { color: var(--paper); background: #c23a2f; }

/* Mew's tour highlight on the detail tabs. */
.d-tabs.tour-hl {
  outline: 4px solid #ffd94a;
  outline-offset: 3px;
  border-radius: 4px;
  animation: spot-blink 1s steps(2) infinite;
}

.d-sub { margin: 0 0 12px; font-size: 18px; color: var(--paper-dim); }
.d-sub b { color: var(--paper-ink); }
.d-empty { font-size: 19px; color: var(--paper-dim); padding: 10px 0; }

/* ---------- Evolution tab ---------- */

.evo-step {
  padding: 12px 0 14px;
  border-bottom: 2px dashed color-mix(in srgb, var(--paper-dim) 40%, transparent);
}
.evo-step:last-child { border-bottom: none; }

.evo-step-mons { display: flex; align-items: center; gap: 6px; }

.evo-mon {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px 4px 4px;
  background: none;
  border: 2px solid transparent;
  border-radius: 4px;
  cursor: pointer;
  font-family: var(--vt);
  font-size: 19px;
  color: var(--paper-ink);
}
.evo-mon img { width: 44px; height: 44px; object-fit: contain; image-rendering: pixelated; }
.evo-mon:hover { border-color: color-mix(in srgb, var(--paper-dim) 55%, transparent); }

.evo-step-arrow { font-family: var(--px); font-size: 12px; color: var(--paper-dim); }

.evo-methods { list-style: none; margin: 6px 0 0; padding: 0 0 0 6px; }
.evo-methods li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 4px 0;
  font-size: 18px;
  line-height: 1.45;
  color: var(--paper-ink);
}

/* The generation/form label on a method that only applies in some games. */
.evo-when {
  flex: 0 0 auto;
  font-family: var(--px);
  font-size: 8px;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--paper-dim);
  padding: 3px 6px 2px;
  border-radius: 3px;
}

.move-h {
  margin: 16px 0 8px;
  font-family: var(--px);
  font-size: 9px;
  text-transform: uppercase;
  color: #c23a2f;
}
.move-h span { color: var(--paper-dim); }
.move-h:first-child { margin-top: 4px; }

.move-list, .loc-list { display: flex; flex-direction: column; }

.move {
  display: grid;
  grid-template-columns: 52px 1fr auto auto 34px;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 2px dashed var(--paper-2);
  font-size: 18px;
}
.move:last-child { border-bottom: none; }

.move-lead { font-family: var(--px); font-size: 8px; color: var(--paper-dim); }
.move-name { font-size: 19px; }
.move .type-badge { font-size: 7px; padding: 3px 5px 2px; border-width: 2px; }

.move-cat-ic {
  height: 17px;
  width: auto;
  display: block;
  image-rendering: pixelated;
}
.move-pow { font-family: var(--px); font-size: 8px; text-align: right; color: var(--paper-ink); }

.loc {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 2px dashed var(--paper-2);
  font-size: 19px;
}
.loc:last-child { border-bottom: none; }
.loc-method { font-family: var(--px); font-size: 7px; color: var(--paper); background: #7a7058; padding: 3px 6px 2px; border-radius: 2px; }
.loc-lv { font-family: var(--px); font-size: 8px; color: var(--paper-dim); }

.entry {
  padding: 12px 0;
  border-bottom: 2px dashed var(--paper-2);
  animation: pop-in 0.25s ease both;
  animation-delay: calc(var(--i, 0) * 25ms);
}

.entry:last-child { border-bottom: none; }

.entry .vers { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 6px; }

.ver-chip {
  font-family: var(--px);
  font-size: 7px;
  text-transform: uppercase;
  padding: 3px 6px 2px;
  border-radius: 2px;
  color: var(--paper-dim);
  background: var(--paper-2);
  border: 2px solid var(--paper-dim);
}

.ver-chip.hl {
  color: var(--paper);
  background: #c23a2f;
  border-color: #7a1f16;
}

.entry p { margin: 0; font-size: 20px; line-height: 1.35; }

.entry.hl { background: #fff8e6; outline: 3px solid #c23a2f; outline-offset: -3px; padding: 12px 8px; }

/* ---------- Dialog buttons ---------- */

.dclose, .dnav {
  position: absolute;
  z-index: 5;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  font-family: var(--px);
  font-size: 12px;
  color: var(--ink);
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, box-shadow 0.12s;
}

.dclose:hover, .dnav:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.35); }
.dclose:active, .dnav:active { transform: translate(1px, 1px); box-shadow: none; }

.dclose { top: 12px; right: 12px; }
.dnav-prev { bottom: 12px; right: 56px; }
.dnav-next { bottom: 12px; right: 12px; }

/* ---------- Footer ---------- */

footer {
  max-width: 1280px;
  margin: 0 auto;
  padding: 8px 24px 28px;
  display: flex;
  justify-content: center;
  gap: 8px;
}

/* Credits live in a popover so the text sits on a solid panel (readable on any
   wallpaper) rather than straight on the background. */
.credits-modal {
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  padding: 0;
  border: 4px solid var(--edge);
  border-radius: 4px;
  background: var(--panel);
  color: var(--ink);
  box-shadow: inset 0 0 0 3px var(--edge-hi), 10px 10px 0 rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.credits-modal::backdrop { background: rgba(8, 6, 4, 0.65); }
.credits-modal[open] { animation: dialog-pop 0.24s cubic-bezier(0.25, 1.4, 0.5, 1) both; }
.credits-modal[open]::backdrop { animation: fade-in 0.2s ease both; }

.credits-body {
  padding: 28px 26px 26px;
  overflow-y: auto;
  max-height: calc(100vh - 72px);
}
.credits-title {
  margin: 0 0 16px;
  font-family: var(--px);
  font-size: 13px;
  text-transform: uppercase;
  border-bottom: 3px solid var(--ink);
  padding-bottom: 10px;
}
.credits-body p {
  font-size: 18px;
  line-height: 1.6;
  color: var(--ink-dim);
  margin: 0 0 14px;
}
.credits-body p:last-child { margin-bottom: 0; }
.credits-body a { color: var(--ink); text-decoration: underline; }
.credits-body a:hover { color: var(--accent); }

/* ---------- Mew guide ---------- */

#mew {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 300;
  pointer-events: none;
  image-rendering: pixelated;
  background-repeat: no-repeat;
  display: none;
}

.mew-overlay {
  position: fixed;
  inset: 0;
  z-index: 250;
  background: rgba(8, 6, 4, 0.55);
  animation: fade-in 0.25s ease both;
}

.mew-spot {
  position: fixed;
  z-index: 260;
  border: 4px solid #ffd94a;
  border-radius: 4px;
  box-shadow: 0 0 0 4000px rgba(8, 6, 4, 0.55);
  pointer-events: none;
  transition: all 0.35s cubic-bezier(0.3, 1.2, 0.4, 1);
  animation: spot-blink 1s steps(2) infinite;
}

@keyframes spot-blink {
  0%, 100% { border-color: #ffd94a; }
  50% { border-color: #fff; }
}

/* Mystery Dungeon style dialogue: navy gradient panel, peach rounded frame,
   emotion portrait on the left. */
.mew-box {
  position: fixed;
  left: 50%;
  bottom: 28px;
  translate: -50% 0;
  z-index: 270;
  width: min(680px, calc(100vw - 32px));
  display: flex;
  gap: 14px;
  padding: 15px 18px;
  font-family: var(--vt);
  color: #fdfdff;
  background: linear-gradient(#28457a, #14264c);
  border: 4px solid #f7ddac;
  border-radius: 16px;
  box-shadow: 0 0 0 3px #0a1120, 10px 10px 0 rgba(0, 0, 0, 0.45);
  animation: dialog-pop 0.25s cubic-bezier(0.25, 1.4, 0.5, 1) both;
}

.mew-portrait {
  flex: 0 0 auto;
  align-self: center;
  width: 74px;
  height: 74px;
  image-rendering: pixelated;
  background: #0e1830;
  border: 3px solid #f7ddac;
  border-radius: 10px;
}

.mew-box .content { flex: 1 1 auto; min-width: 0; }

.mew-box .who {
  display: inline-block;
  font-family: var(--px);
  font-size: 9px;
  padding: 4px 8px 3px;
  margin-bottom: 7px;
  color: #14264c;
  background: #f7ddac;
  border-radius: 4px;
}

.mew-box .txt {
  min-height: 46px;
  font-size: 22px;
  line-height: 1.3;
}

.mew-box .txt::after {
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  margin-left: 6px;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-top: 9px solid #f7ddac;
  vertical-align: middle;
  animation: spot-blink 0.8s steps(2) infinite;
  opacity: 0;
}

.mew-box.done .txt::after { opacity: 1; }

.mew-box .row {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 10px;
}

.mew-box .px-btn { font-size: 8px; background: #33518a; color: #fff; border-color: #0a1120; }
.mew-box .px-btn.primary { background: #e8b64a; color: #14264c; }

/* Contextual speech bubble that follows Mew around. */
.mew-bubble {
  position: fixed;
  z-index: 260;
  display: flex;
  gap: 8px;
  align-items: center;
  max-width: 270px;
  padding: 8px 11px;
  font-family: var(--vt);
  font-size: 18px;
  line-height: 1.2;
  color: #fdfdff;
  background: linear-gradient(#28457a, #14264c);
  border: 3px solid #f7ddac;
  border-radius: 12px;
  box-shadow: 0 0 0 2px #0a1120, 4px 4px 0 rgba(0, 0, 0, 0.4);
  pointer-events: none;
  animation: dialog-pop 0.2s cubic-bezier(0.25, 1.4, 0.5, 1) both;
}

.mew-bubble img {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  image-rendering: pixelated;
  background: #0e1830;
  border: 2px solid #f7ddac;
  border-radius: 6px;
}

/* ---------- Add-to-team button (detail) ---------- */

.d-team-add {
  margin-top: 10px;
  font-size: 8px;
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--edge);
}

.d-allsprites {
  margin-top: 12px;
  width: 100%;
  font-size: 8px;
}

/* ---------- Sprite archive modal ---------- */

.arch-modal {
  width: min(760px, calc(100vw - 32px));
  max-height: calc(100vh - 64px);
  padding: 0;
  border: 4px solid var(--edge);
  border-radius: 4px;
  background: var(--panel);
  color: var(--ink);
  box-shadow: inset 0 0 0 3px var(--edge-hi), 10px 10px 0 rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.arch-modal::backdrop { background: rgba(8, 6, 4, 0.65); }
.arch-modal[open] { animation: dialog-pop 0.24s cubic-bezier(0.25, 1.4, 0.5, 1) both; }

.arch-head {
  padding: 16px 20px 12px;
  border-bottom: 3px solid var(--edge);
  background: var(--panel-2);
}
.arch-head h2 {
  margin: 0;
  font-family: var(--px);
  font-size: 13px;
}
.arch-note {
  margin: 6px 0 0;
  font-family: var(--vt);
  font-size: 15px;
  color: var(--ink-dim);
}

.arch-body {
  padding: 14px 20px 20px;
  max-height: calc(100vh - 168px);
  overflow-y: auto;
}

.arch-gen { margin-bottom: 16px; }
.arch-gen h3 {
  margin: 0 0 8px;
  font-family: var(--px);
  font-size: 9px;
  color: var(--ink-dim);
  border-bottom: 2px solid var(--edge);
  padding-bottom: 6px;
}

.arch-games {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 10px;
}

.arch-game {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px 6px 6px;
  background: var(--panel-2);
  border: 2px solid var(--edge);
  border-radius: 3px;
}
.arch-imgs { display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 68px; }
.arch-img {
  width: 68px;
  height: 68px;
  object-fit: contain;
  image-rendering: auto;
}
.arch-img.px { image-rendering: pixelated; }
.arch-shiny { width: 56px; height: 56px; opacity: 0.97; }

.arch-label {
  font-family: var(--px);
  font-size: 7px;
  text-align: center;
  color: var(--ink-dim);
  line-height: 1.5;
}
.arch-empty {
  font-family: var(--vt);
  font-size: 17px;
  color: var(--ink-dim);
  text-align: center;
  padding: 30px 0;
}

/* ---------- Team dock ---------- */

.team-dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 180;
  background: var(--panel-2);
  border-top: 3px solid var(--edge);
  box-shadow: 0 -3px 0 rgba(0, 0, 0, 0.3);
}

.team-dock[hidden] { display: none; }

.team-dock-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 10px 24px;
  display: flex;
  align-items: center;
  gap: 14px;
}

.team-label {
  font-family: var(--px);
  font-size: 10px;
  color: var(--ink-dim);
  flex: 0 0 auto;
}

.team-slots { display: flex; gap: 8px; flex: 1 1 auto; }

.team-slot {
  position: relative;
  width: 62px;
  height: 62px;
  display: grid;
  place-items: center;
  background: var(--panel);
  border: 3px dashed var(--edge);
  border-radius: 4px;
  transition: transform 0.12s, box-shadow 0.12s;
}

.team-slot.filled { border-style: solid; box-shadow: inset 2px 2px 0 var(--edge-hi); }
.team-slot.over { transform: translateY(-3px); box-shadow: 0 0 0 3px var(--accent); }

.team-slot img { width: 54px; height: 54px; object-fit: contain; image-rendering: auto; }
.slot-plus { font-family: var(--px); font-size: 16px; color: var(--ink-dim); }

.slot-x {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  font-family: var(--px);
  font-size: 9px;
  color: #fff;
  background: #d3425f;
  border: 2px solid var(--edge);
  border-radius: 50%;
  cursor: pointer;
}

.team-dock-actions { display: flex; gap: 8px; flex: 0 0 auto; }
.card-btn { color: var(--accent-ink); background: var(--accent); }
.card-btn:disabled { opacity: 0.5; cursor: not-allowed; filter: grayscale(0.6); }
.team-clear { color: #fff; background: #d3425f; border-color: #47101d; }

/* ---------- Trainer card editor ---------- */

.card-modal {
  width: min(1040px, calc(100vw - 32px));
  max-height: calc(100vh - 48px);
  padding: 0;
  border: 4px solid var(--edge);
  border-radius: 6px;
  background: var(--panel);
  color: var(--ink);
  box-shadow: inset 0 0 0 3px var(--edge-hi), 10px 10px 0 rgba(0, 0, 0, 0.45);
  overflow: hidden;
}
.card-modal::backdrop { background: rgba(8, 6, 4, 0.66); }

.card-modal-body {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  max-height: calc(100vh - 48px);
}

.card-canvas-wrap {
  padding: 22px;
  display: grid;
  place-items: center;
  background: var(--panel-2);
}
#cardCanvas { width: 100%; height: auto; image-rendering: auto; }

.card-controls {
  padding: 22px 22px 20px;
  border-left: 3px solid var(--edge);
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.cc-field { display: flex; flex-direction: column; gap: 8px; }
.cc-field > span {
  font-family: var(--px);
  font-size: 9px;
  text-transform: uppercase;
  color: var(--ink-dim);
}

#cardName {
  font-family: var(--vt);
  font-size: 22px;
  padding: 8px 12px;
  color: var(--ink);
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 3px;
  outline: none;
  text-transform: uppercase;
}
#cardName:focus { box-shadow: inset 0 0 0 2px var(--accent); }

.cc-row3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
.cc-row3 .cc-field > span { font-size: 8px; }

.cc-input {
  width: 100%;
  font-family: var(--vt);
  font-size: 20px;
  padding: 8px 10px;
  color: var(--ink);
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 3px;
  outline: none;
}
.cc-input:focus { box-shadow: inset 0 0 0 2px var(--accent); }

.cc-select {
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--vt);
  font-size: 19px;
  padding: 8px 30px 8px 12px;
  color: var(--ink);
  background: var(--panel-2)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7'%3E%3Cpath d='M0 0h12L6 7z' fill='%23888'/%3E%3C/svg%3E")
    no-repeat right 12px center;
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  outline: none;
}
.cc-select:focus { box-shadow: inset 0 0 0 2px var(--accent); }

.party-shiny { display: flex; gap: 6px; flex-wrap: wrap; }
.party-opt {
  position: relative;
  width: 50px;
  height: 50px;
  display: grid;
  place-items: center;
  padding: 2px;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s;
}
.party-opt:hover { transform: translateY(-2px); }
.party-opt img { width: 42px; height: 42px; object-fit: contain; }
.party-opt .party-star {
  position: absolute;
  top: -7px;
  right: -7px;
  width: 18px;
  height: 18px;
  display: grid;
  place-items: center;
  font-size: 10px;
  color: #7a7058;
  background: var(--panel);
  border: 2px solid var(--edge);
  border-radius: 50%;
}
.party-opt.on { border-color: #f5c518; box-shadow: inset 0 0 0 2px #f5c518; }
.party-opt.on .party-star { color: #14264c; background: #f5c518; border-color: #a8850a; }

.cc-swatches { display: flex; gap: 6px; flex-wrap: wrap; }
.cc-swatch {
  width: 26px;
  height: 26px;
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s;
}
.cc-swatch:hover { transform: translateY(-2px); }
.cc-swatch.on { box-shadow: 0 0 0 2px var(--accent-ink), 0 0 0 5px var(--accent); }

.cc-custom {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--vt);
  font-size: 17px;
  color: var(--ink-dim);
}
.cc-custom input { width: 34px; height: 26px; padding: 0; border: 3px solid var(--edge); border-radius: 3px; background: none; cursor: pointer; }

.trainer-pick {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(52px, 1fr));
  gap: 6px;
  max-height: 240px;
  overflow: auto;
  padding: 8px;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 3px;
}
.trainer-opt {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  padding: 2px;
  background: none;
  border: 2px solid transparent;
  border-radius: 3px;
  cursor: pointer;
}
.trainer-opt img { width: 90%; height: 90%; object-fit: contain; image-rendering: pixelated; }
.trainer-opt:hover { background: rgba(0, 0, 0, 0.08); }
.trainer-opt.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, transparent); }

.cc-actions { margin-top: auto; }
.card-export {
  width: 100%;
  font-size: 11px;
  padding: 12px;
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--edge);
}

/* ---------- Tier list builder ---------- */

/* Full-page, stream-friendly view: takes over the whole viewport (no dex behind
   it), with its own top bar. Sits over everything else, including the team dock. */
.tier-page {
  position: fixed;
  inset: 0;
  z-index: 190;
  display: flex;
  flex-direction: column;
  background: var(--field) var(--wall) repeat top left;
  background-size: 96px auto;
  color: var(--ink);
  animation: fade-in 0.18s ease both;
}
.tier-page[hidden] { display: none; }
body.smooth-wall .tier-page { background-size: cover; background-position: center; }
body.tier-open { overflow: hidden; }

.tier-topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
  background: var(--panel-2);
  border-bottom: 3px solid var(--edge);
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.3);
}
.tier-topbar .brand h1 { font-size: 15px; }
.tier-topbar-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.tl-export { color: var(--accent-ink); background: var(--accent); }

.tier-toolbar {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 8px;
  padding: 12px 20px;
  background: var(--panel-2);
  border-bottom: 3px solid var(--edge);
}
.tier-toolbar .select { flex: 0 1 220px; }
.tl-search-wrap { flex: 1 1 260px; min-width: 200px; }

/* Live search-add results, styled like the "Other" category popover. */
.tl-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 60;
  max-height: 260px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 6px;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 4px;
  box-shadow: inset 0 0 0 2px var(--edge-hi), 6px 6px 0 rgba(0, 0, 0, 0.4);
}
.tl-results[hidden] { display: none; }

.tl-result {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  font-family: var(--vt);
  font-size: 17px;
  color: var(--ink);
  background: var(--panel);
  border: 2px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  text-align: left;
}
.tl-result:hover { background: var(--accent); color: var(--accent-ink); }
.tl-result img { width: 26px; height: 26px; object-fit: contain; }
.tl-result .tl-r-num { font-family: var(--px); font-size: 7px; color: var(--ink-dim); }
.tl-result:hover .tl-r-num { color: var(--accent-ink); }
.tl-result.empty { cursor: default; color: var(--ink-dim); justify-content: center; }
.tl-result.empty:hover { background: var(--panel); color: var(--ink-dim); }

/* The wallpaper lives on .tier-page; this lays out the rows + pool to fill the
   full remaining height (the pool flex-grows into whatever's left, rather than
   sitting at a fixed height with dead space below it). Tier rows keep their
   natural height but cap at 55% with their own scrollbar as a safety valve for
   very full tiers, so the pool always keeps meaningful room. */
.tier-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  padding: 16px 20px 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* flex:0 0 auto (not shrinkable): a shrinkable flex item with overflow:auto
   defaults its min-size to 0, so it would get crushed toward nothing by
   .tier-pool's flex-grow instead of keeping its natural content height. */
.tier-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 0 0 auto;
  max-height: 55%;
  overflow-y: auto;
}

.tier-row {
  display: flex;
  align-items: stretch;
  gap: 0;
  flex: 0 0 auto;
  min-height: 100px;
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 4px;
  box-shadow: inset 0 0 0 2px var(--edge-hi), 4px 4px 0 rgba(0, 0, 0, 0.3);
  overflow: hidden;
}

.tier-label {
  flex: 0 0 74px;
  display: grid;
  place-items: center;
  font-family: var(--px);
  font-size: 22px;
  color: #2a2113;
  border-right: 3px solid var(--edge);
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.3);
}
.tier-label.tier-S { background: linear-gradient(#ffe485, #f5c518); }
.tier-label.tier-A { background: linear-gradient(#ff9c8a, #e8543f); color: #fff; text-shadow: 1px 1px 0 rgba(0,0,0,.35); }
.tier-label.tier-B { background: linear-gradient(#ffc978, #f0a030); }
.tier-label.tier-C { background: linear-gradient(#c3e896, #7ac74c); }
.tier-label.tier-D { background: linear-gradient(#a6c6ff, #6390f0); color: #fff; text-shadow: 1px 1px 0 rgba(0,0,0,.35); }
.tier-label.tier-F { background: linear-gradient(#c9b6d9, #8a6ba3); color: #fff; text-shadow: 1px 1px 0 rgba(0,0,0,.35); }

.tier-cell {
  flex: 1 1 auto;
  min-height: 94px;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 8px;
  padding: 8px;
  transition: background 0.12s;
}
.tier-cell.over { background: color-mix(in srgb, var(--accent) 18%, transparent); }

/* flex:0 1 auto (not grow): the pool sizes to its own content (so a small
   pool like Gigantamax's 34 stays compact) but can still SHRINK if that
   content is taller than the space left in .tier-scroll, at which point
   .tier-pool-grid's own overflow-y:auto takes over as a scrollbar (e.g. the
   full 1113-species dex). min-height is just a floor for the empty state. */
.tier-pool {
  flex: 0 1 auto;
  min-height: 140px;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 4px;
  box-shadow: inset 0 0 0 2px var(--edge-hi), 4px 4px 0 rgba(0, 0, 0, 0.3);
  overflow: hidden;
}
.tier-pool-head {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 10px 12px 8px;
  font-family: var(--px);
  font-size: 9px;
  text-transform: uppercase;
  color: var(--ink-dim);
  border-bottom: 2px solid var(--edge);
}
.tl-count { color: var(--ink); }
.tier-pool-grid {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 8px;
  padding: 12px;
  transition: background 0.12s;
}
.tier-pool-grid.over { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.tl-empty {
  width: 100%;
  padding: 16px 4px;
  text-align: center;
  font-family: var(--vt);
  font-size: 16px;
  color: var(--ink-dim);
}

/* A single draggable Pokemon tile: just the PNG, no card/border. Hover grows it
   and selection glows the sprite's own silhouette (drop-shadow hugs the alpha,
   so there's no square outline). */
.tl-sprite {
  position: relative;
  width: 76px;
  height: 76px;
  display: grid;
  place-items: center;
  background: none;
  border: none;
  cursor: grab;
  transition: transform 0.1s;
}
.tl-sprite:active { cursor: grabbing; }
.tl-sprite img {
  width: 70px;
  height: 70px;
  object-fit: contain;
  transition: filter 0.1s;
}
.tl-sprite:hover { transform: scale(1.12); z-index: 1; }
.tl-sprite.selected img {
  filter: drop-shadow(0 0 2px var(--accent)) drop-shadow(0 0 2px var(--accent)) drop-shadow(0 0 1px var(--accent));
}
.tl-sprite .slot-x {
  opacity: 0;
  transition: opacity 0.1s;
}
.tl-sprite:hover .slot-x { opacity: 1; }

/* Drag-to-reorder insertion point: a bar in the gap on the side of the tile
   the dragged item would land on. */
.tl-sprite.drop-before::before,
.tl-sprite.drop-after::after {
  content: "";
  position: absolute;
  top: 4px;
  bottom: 4px;
  width: 3px;
  border-radius: 2px;
  background: var(--accent);
}
.tl-sprite.drop-before::before { left: -6px; }
.tl-sprite.drop-after::after { right: -6px; }

/* ---------- Beta Dex ---------- */

/* Full-page view over the live wallpaper, mirroring .tier-page. */
.beta-page {
  position: fixed;
  inset: 0;
  /* lvh = the viewport with the browser toolbars retracted, i.e. the full
     screen. dvh (the *visible* area) would stop the overlay exactly where
     Safari's toolbar begins, leaving a bar below it showing the Pokedex
     underneath; lvh runs the dreamscape under the toolbar instead, so it
     scrolls through edge to edge like the main dex. vh is the fallback. */
  height: 100vh;
  height: 100lvh;
  z-index: 190;
  display: flex;
  flex-direction: column;
  background: var(--field) var(--wall) repeat top left;
  background-size: 96px auto;
  color: var(--ink);
  animation: fade-in 0.18s ease both;
}
.beta-page[hidden] { display: none; }
body.smooth-wall .beta-page { background-size: cover; background-position: center; }
body.beta-open { overflow: hidden; }

/* ---------- Dream World themes (light: Musharna / dark: Darkrai) ---------- */

/* The mode swaps the cloud sky behind the page and re-colours the whole UI via
   these variable overrides on <body>, so cards, tabs, the info box and the
   expanded modal all follow along. */
body.dw-light .beta-page {
  background: url("assets/dreamworld/pink.png") center / cover no-repeat;
}
body.dw-dark .beta-page {
  background: url("assets/dreamworld/night.png") center / cover no-repeat;
}

/* --field, --accent and --accent-ink are set inline on <body> by the wallpaper
   theme, so they need !important here to win while Dream World is open. */
body.dw-light {
  --field: #e7c4e6 !important;
  --panel: #fbeef8;
  --panel-2: #f4dcef;
  --edge: #5a3a58;
  --edge-hi: #fffdfb;
  --ink: #3a2438;
  --ink-dim: #8a6288;
  --paper: #fdf3fb;
  --paper-2: #f6e6f3;
  --paper-ink: #3a2438;
  --paper-dim: #8a6288;
  --accent: #e879bb !important;
  --accent-ink: #fff !important;
}
body.dw-dark {
  --field: #1a2244 !important;
  --panel: #222d52;
  --panel-2: #2b3865;
  --edge: #0a0f24;
  --edge-hi: #4a5a8e;
  --ink: #e9eefc;
  --ink-dim: #a6b4dc;
  --paper: #1d2749;
  --paper-2: #26325a;
  --paper-ink: #e9eefc;
  --paper-dim: #a4b2da;
  --accent: #8272ff !important;
  --accent-ink: #fff !important;
}

/* Dream World sits in a fixed 100dvh overlay, so iOS's rubber-band scroll
   reveals the page *behind* it -- which was still painted with the Pokedex
   wallpaper tile (the tan/brown bars). Repaint that backdrop to match the
   dreamscape: the menu's own colour at the top so the bar reads as the topbar
   extending upward, blending into the sky's real bottom edge colour (sampled
   from the artwork) below. Only those two slivers are ever visible; the
   overlay covers the middle. */
body.dw-light { background: linear-gradient(#f4dcef 0%, #7c1176 100%) !important; }
body.dw-dark { background: linear-gradient(#2b3865 0%, #002390 100%) !important; }

/* The particle canvas normally sits behind everything; float it over the Dream
   World page so the bubbles/wisps drift across the dreamscape. */
body.beta-open #fx { z-index: 195; }

/* The logo is dark ink; flip it to white so it reads on the night sky. */
body.dw-dark .beta-topbar .brand-logo img { filter: brightness(0) invert(1); }

/* Mode toggle: the current buddy's portrait + name, like the wallpaper button. */
.dw-mode-btn { display: flex; align-items: center; gap: 7px; }
.px-btn.dw-mode-btn { padding: 6px 12px; }
.dw-mode-swatch {
  width: 18px;
  height: 18px;
  border: 2px solid var(--edge);
  border-radius: 50%;
  background-size: cover;
  background-position: center top;
  image-rendering: pixelated;
}

.beta-topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
  /* Same trick as the main dex's .topbar: run the opaque bar up through the
     iOS status-bar / notch zone so the menu colour (pink for Musharna, navy
     for Darkrai) reads as one continuous block to the top of the screen,
     instead of a mismatched strip above it. Zero off iOS. */
  padding-top: calc(12px + env(safe-area-inset-top, 0px));
  background: var(--panel-2);
  border-bottom: 3px solid var(--edge);
  box-shadow: 0 3px 0 rgba(0, 0, 0, 0.3);
}
.beta-topbar .brand { display: flex; align-items: center; gap: 10px; }
/* The Beta Dex logo SVG is cropped tight to its letters, whereas the Bill's PC
   and Tier logos carry vertical padding in their viewBox (glyphs ~145 of a
   245.23 box). Scale the height down by that ratio so the letters match. */
.beta-topbar .brand-logo img { height: 17.7px; }
.beta-topbar-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }

.beta-toolbar {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  background: var(--panel-2);
  border-bottom: 3px solid var(--edge);
}
.beta-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.beta-tab {
  font-family: var(--px);
  font-size: 9px;
  padding: 9px 12px 8px;
  color: var(--ink-dim);
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: transform 0.12s ease-out, color 0.12s;
}
.beta-tab:hover { color: var(--ink); transform: translateY(-1px); }
.beta-tab.on { color: var(--accent-ink); background: var(--accent); }
.beta-count {
  margin-left: auto;
  font-family: var(--px);
  font-size: 8px;
  color: var(--ink-dim);
  white-space: nowrap;
}

.beta-scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 20px;
}

/* Discovery-history blurb above each generation's grid. */
.beta-info {
  max-width: 900px;
  margin: 0 auto 20px;
  padding: 14px 16px;
  font-size: 18px;
  line-height: 1.55;
  color: var(--paper-ink);
  background: var(--paper);
  border: 3px solid var(--edge);
  border-radius: 4px;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.3);
}
.beta-info[hidden] { display: none; }

/* Slightly denser than the main grid since the cards carry less. */
.beta-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }

.beta-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px 10px 12px;
  font-family: inherit;
  background: var(--panel);
  border: 3px solid var(--edge);
  border-radius: 3px;
  box-shadow: inset 0 0 0 2px var(--edge-hi), 4px 4px 0 rgba(0, 0, 0, 0.35);
  transition: transform 0.13s ease-out, box-shadow 0.13s ease-out;
  animation: pop-in 0.28s cubic-bezier(0.25, 1.4, 0.5, 1) both;
}
.beta-card.flippable { cursor: pointer; }
.beta-card:not(.flippable) { cursor: default; }
.beta-card:hover {
  transform: translate(-3px, -3px);
  box-shadow: inset 0 0 0 2px var(--edge-hi), 8px 8px 0 rgba(0, 0, 0, 0.35);
}

/* Sprite frame. Front and back are stacked; the back is revealed on hover
   (desktop) or when the card carries .flipped (tap, set in betadex.js). */
.beta-art {
  position: relative;
  height: 104px;
  width: 100%;
  display: grid;
  place-items: center;
}
.beta-sprite {
  grid-area: 1 / 1;
  max-height: 96px;
  max-width: 96px;
  object-fit: contain;
  image-rendering: pixelated;
  transition: opacity 0.15s ease;
}
.beta-sprite.beta-back { opacity: 0; }
.flippable:hover .beta-front,
.flippable.flipped .beta-front { opacity: 0; }
.flippable:hover .beta-back,
.flippable.flipped .beta-back { opacity: 1; }

/* Concept-art fallback (the two Gen 3 mons with no sprite) is a photo, so it
   renders smoothly rather than pixelated. */
.beta-concept {
  max-height: 100px;
  max-width: 100px;
  object-fit: contain;
  border-radius: 3px;
}
.beta-nosprite { font-family: var(--px); font-size: 22px; color: var(--ink-dim); }

.beta-name {
  margin-top: 8px;
  font-family: var(--px);
  font-size: 9px;
  line-height: 1.5;
  text-align: center;
  color: var(--ink);
}
.beta-final {
  margin-top: 4px;
  font-size: 15px;
  color: var(--ink-dim);
  text-align: center;
}
.beta-final.scrapped { font-style: italic; }
.beta-card .num {
  position: absolute;
  top: 8px;
  right: 10px;
  font-family: var(--px);
  font-size: 8px;
  color: var(--ink-dim);
}
.beta-card .types { display: flex; gap: 4px; margin-top: 8px; flex-wrap: wrap; justify-content: center; }

/* "Type Unknown" reuses the badge shell in a neutral grey. */
.type-badge.type-unknown {
  --tc: var(--edge-hi);
  color: var(--ink-dim);
  text-transform: none;
}

/* ---------- Beta Dex expanded view ---------- */

.beta-modal {
  width: min(560px, calc(100vw - 32px));
  padding: 0;
  border: 4px solid var(--edge);
  border-radius: 4px;
  background: var(--panel);
  color: var(--ink);
  box-shadow: inset 0 0 0 3px var(--edge-hi), 10px 10px 0 rgba(0, 0, 0, 0.45);
  overflow: visible;
}
.beta-modal::backdrop { background: rgba(8, 6, 4, 0.65); }
.beta-modal[open] { animation: dialog-pop 0.24s cubic-bezier(0.25, 1.4, 0.5, 1) both; }
.beta-modal[open]::backdrop { animation: fade-in 0.2s ease both; }

.beta-modal-body {
  padding: 26px 24px 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.beta-modal-name { margin: 0; font-family: var(--px); font-size: 14px; text-align: center; }
.beta-modal-sub { font-size: 17px; color: var(--ink-dim); }
.beta-modal-sub.scrapped { font-style: italic; }
.beta-modal-types { margin-top: 2px; }

/* Front + back side by side on desktop, stacked on mobile. */
.beta-modal-sprites { display: flex; flex-direction: row; gap: 20px; margin-top: 10px; }
.beta-fig { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.beta-fig img {
  width: 132px;
  height: 132px;
  object-fit: contain;
  image-rendering: pixelated;
  background: var(--panel-2);
  border: 3px solid var(--edge);
  border-radius: 4px;
  padding: 10px;
}
.beta-fig figcaption {
  font-family: var(--px);
  font-size: 8px;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ---------- Responsive ---------- */

@media (max-width: 720px) {
  /* The stacked detail column was sizing to its CONTENT's min-content width --
     a `1fr` track's automatic minimum is min-content, and the four never-wrapping
     .d-tabs are ~397px wide, so the column blew out ~100px past the dialog and
     pushed every row off both edges. minmax(0, 1fr) + min-width:0 pins the
     column to the dialog instead, and the tab strip wraps to fit. */
  .detail { width: calc(100vw - 16px); max-width: none; }
  .detail-body { grid-template-columns: minmax(0, 1fr); }
  .d-left, .d-right { min-width: 0; }
  .d-left { position: static; padding: 20px 14px 16px; }
  .d-right {
    border-left: none;
    border-top: 3px solid var(--edge);
    padding: 14px 14px 18px;
  }
  /* Four tabs on one row would need the 9px label dropped to 7px and would
     still overflow at 320px, so use an even 2x2 instead: equal buttons, full
     size type at every phone width. */
  .d-tabs { display: grid; grid-template-columns: 1fr 1fr; }

  /* Same auto-minimum trap one level down, on the narrowest phones: the move
     row's 1fr name column and the evolution row's mon buttons wouldn't shrink
     below their text. Both are no-ops once there's room. */
  .move { grid-template-columns: 52px minmax(0, 1fr) auto auto 34px; }
  .move-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .evo-step-mons { flex-wrap: wrap; justify-content: center; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); }
  .count { display: none; }
  .card-modal-body { grid-template-columns: 1fr; }
  .card-controls { border-left: none; border-top: 3px solid var(--edge); }
  .team-label { display: none; }

  /* Mobile is a sleek pokedex scroller: brand alone, then a wallpaper+shiny row
     and a search+filters row. Mew, Guide and all team-building are desktop-only;
     everything else drops into the Advanced-filters overlay. */
  .topbar-inner { padding: 10px 16px 8px; }
  .hide-mobile { display: none !important; }
  .mobile-only { display: inline-block; }
  .d-team-add { display: none; }
  .team-dock { display: none !important; }
  .tier-page { display: none !important; }

  /* Dream World stays available on mobile (unlike Team/Tier). Tighten it up. */
  .beta-topbar { padding: 10px 14px; padding-top: calc(10px + env(safe-area-inset-top, 0px)); }
  .beta-toolbar { padding: 10px 14px; gap: 8px; }
  /* The page runs under Safari's toolbar (100lvh), so pad the scroll area past
     it and the home indicator or the last row of cards can't be reached. */
  .beta-scroll { padding: 14px; padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px) + 64px); }
  .beta-info { font-size: 16px; padding: 12px 14px; margin-bottom: 16px; }
  .beta-grid { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 12px; }

  /* Generation tabs sit on a single row across the mobile menu. */
  .beta-tabs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; flex: 1 1 100%; }
  .beta-tab { font-size: 7px; padding: 10px 2px 9px; text-align: center; white-space: nowrap; }

  /* The mobile menu keeps just the logo and a compact "Back" (which is centered
     against the logo by the topbar's align-items:center). Donate and wallpaper
     live on the main mobile bar instead. */
  /* Mobile Dream World topbar: logo, the day/night toggle, and a compact Back. */
  .beta-topbar-actions #betaDonate { display: none; }
  .beta-back-x { display: none; }
  .dw-mode-btn .dw-mode-name { display: none; }

  /* Expanded view stacks the two sprites on mobile. */
  .beta-modal-sprites { flex-direction: column; gap: 14px; }
  body.adv-open .adv-toggle {
    color: var(--accent-ink); background: var(--accent);
  }

  /* Two-row mobile bar: [wallpaper .. shiny] then [search .. filters]. */
  .mobile-primary { display: flex; flex-direction: column; gap: 8px; }
  .mp-row { display: flex; gap: 8px; align-items: stretch; }
  /* The three top buttons grow to equal width so the only gaps left are the
     shared 8px, matching the space between the search bar and Filters below.
     white-space:nowrap keeps each label on one line and makes the equal-width
     split deterministic (without it the wallpaper button gets starved and wraps). */
  #mpTop { gap: 6px; }
  #mpTop > * { flex: 1 1 0; }
  #mpTop .spr-toggle { flex: 0 0 34px; }
  #mpTop .wp-wrap { display: flex; }
  #mpTop .wp-btn { flex: 1 1 auto; justify-content: center; }
  #mpTop .wp-btn, #mpTop .px-btn, #mpTop .dex-tab { white-space: nowrap; }
  /* Four buttons plus "Dream World" (longer than the old "Beta Dex" label)
     no longer fit at the base 9px/12px size on narrow phones -- trim both
     down within this row only, so nothing spills past the viewport edge. */
  #mpTop .wp-btn, #mpTop .px-btn, #mpTop .dex-tab { font-size: 8px; padding-left: 8px; padding-right: 8px; }
  #mpTop .wp-btn { gap: 5px; }
  .mp-row .search-wrap { flex: 1 1 auto; }
  .mp-row .shiny-tab { margin-left: 0; }

  .filters {
    display: flex;
    flex-direction: column;
    gap: 10px;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    padding: 12px 16px 16px;
    background: var(--panel-2);
    border-bottom: 3px solid var(--edge);
    box-shadow: 0 8px 0 rgba(0, 0, 0, 0.25);
    max-height: 78vh;
    overflow-y: auto;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    pointer-events: none;
    transition: opacity 0.22s ease, transform 0.22s ease, visibility 0.22s;
    z-index: 40;
  }
  body.adv-open .filters {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    pointer-events: auto;
  }
  .filters .controls .select { flex: 1 1 44%; }
  .other-pop { width: 200px; }

  /* The wallpaper button sits on the left of the mobile bar, so the desktop
     right:0 anchor throws the popover off the left edge. Re-anchor to the left
     and cap the width to the viewport. */
  .wp-pop {
    left: 0;
    right: auto;
    width: min(340px, calc(100vw - 28px));
    max-height: 72vh;
    overflow-y: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
}
