@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. */
/* Needs the .px-btn double-class specificity to zero the padding: plain
   .px-btn { padding: 9px 12px } is declared later and would otherwise win,
   leaving a 4px content box that squeezes the icon to a sliver. Same fix the
   wallpaper button uses. */
.px-btn.spr-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Square, sized to the 33px the sibling .px-btns resolve to (9px padding +
     9px line box + 3px borders), so the row of buttons lines up flush. */
  width: 33px;
  height: 33px;
  padding: 0;
  flex: 0 0 auto;
}
/* Sits a little inset in the 33px square. The disc relies on
   shape-rendering:crispEdges (set in the markup) rather than an exact integer
   scale to keep its steps hard-edged at this size. */
.spr-toggle svg { width: 20px; height: 20px; display: block; flex: 0 0 auto; }

/* Positive/negative pair, both carrying the active wallpaper's accent colour
   (JS sets --accent per wallpaper, so these follow the scenery automatically):
     pixel mode  -> blocky disc filled with the accent on the plain button
     HOME mode   -> inverted, the whole square fills with the accent and a
                    smooth circle is knocked out of it.
   The knockout uses --accent-ink, which JS derives per wallpaper as
   black-or-white against that accent, so it lands on white for these mid-dark
   accents and reads exactly like a punched hole. */
.spr-toggle .spr-px rect { fill: var(--accent); }
.spr-toggle .spr-round circle { fill: var(--accent-ink); }
.px-btn.spr-toggle.on { background: var(--accent); }

/* The tier toolbar stretches its controls to 38px (set by the search field's
   taller box), so the square is 38px there rather than the header's 33px.
   Both numbers are "match the siblings" -- aspect-ratio can't do it
   automatically, since a flex item's main size still comes from its content. */
.tier-toolbar .px-btn.spr-toggle {
  width: 38px;
  height: 38px;
}

/* .on marks HOME mode, so the smooth circle shows there and the disc otherwise. */
.spr-toggle .spr-round { display: none; }
.spr-toggle.on .spr-px { display: none; }
.spr-toggle.on .spr-round { display: block; }

/* 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);
}

/* Dream World nav + its Back link are <a>s styled as buttons, so they need the
   underline reset to match the <button>s beside them. */
.beta-back-short { display: none; }

.beta-link, .beta-back-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  color: var(--ink);
}

/* 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-dev {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 2px dashed var(--edge);
  color: var(--paper-ink);
}
.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; }

/* ---------- Dream World ---------- */

/* Dream World is its OWN page (dreamworld.html), not an overlay on the dex.
   That is deliberate: as a normal document it gets normal scrolling, a normal
   sticky header and nothing rendered behind it, so there is no second page to
   bleed past the screen edges on iOS -- the class of bug that dogged the
   overlay version. Layout here mirrors the main dex, which already works.

   The mode class lives on <html> (stamped pre-paint by an inline script in
   dreamworld.html so the palette never flashes), hence .dw-light / .dw-dark
   rather than body.*. */

.dw-body {
  min-height: 100vh;
  color: var(--ink);
}

/* The sky is a fixed backdrop rather than a scrolling background: at ~150k px
   of grid, background-attachment:fixed misbehaves on iOS and a scrolling image
   would stretch absurdly. body's background-color matches the sky so any
   overscroll past the artwork stays in-palette instead of flashing white. */
.dw-body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -2;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
.dw-light .dw-body { background-color: #b0479f; }
.dw-light .dw-body::before { background-image: url("assets/dreamworld/pink.png"); }
.dw-dark .dw-body { background-color: #061544; }
.dw-dark .dw-body::before { background-image: url("assets/dreamworld/night.png"); }

/* Header + generation tabs pin together as one unit, mirroring the main dex's
   .topbar. The safe-area padding sits on the wrapper so its opaque background
   fills the iOS status-bar / notch zone, which is what makes the menu colour
   read as one continuous block to the very top of the screen. */
.dw-topbar-wrap {
  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);
  padding-top: env(safe-area-inset-top, 0px);
}

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

.dw-light .dw-body {
  --field: #e7c4e6;
  --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;
  --accent-ink: #fff;
}
.dw-dark .dw-body {
  --field: #1a2244;
  --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;
  --accent-ink: #fff;
}

/* The logo is dark ink; flip it to white so it reads on the night sky. */
.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 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 20px;
}
.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 {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 0 20px 12px;
}
.beta-tabs { display: flex; gap: 6px; flex-wrap: wrap; }

/* Mobile-only "Dreams" picker: on desktop the three subcategories stay visible
   as the tab strip, so this stays hidden. Styled after the dex's Other menu. */
.dreams-wrap { display: none; position: relative; }
.dreams-pop[hidden] { display: none; }
.dreams-pop {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 120;
  width: max(220px, 100%);
  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;
}
.dreams-opt {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 10px 8px;
  font-family: var(--px);
  /* The names are long ("Spaceworld Demo Gen 1"); 7px keeps them on one line at
     phone widths, and the line-height stops any wrap from colliding. */
  font-size: 7px;
  line-height: 1.5;
  text-align: left;
  color: var(--ink-dim);
  background: var(--panel);
  border: 2px solid var(--edge);
  border-radius: 3px;
  cursor: pointer;
  transition: color 0.12s, background 0.12s;
}
.dreams-opt:hover { color: var(--ink); }
.dreams-opt.on { color: var(--accent-ink); background: var(--accent); }
.dreams-opt .do-count { opacity: 0.75; flex: 0 0 auto; }
.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 {
  display: block;
  max-width: 1280px;
  margin: 0 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 dreamworld.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; }
/* Hover-flip is for real pointers only. On a touchscreen :hover can stick after
   a tap, leaving the card showing its back sprite once the expanded view
   closes; touch users get that front+back view on tap instead. */
@media (hover: hover) {
  .flippable:hover .beta-front { opacity: 0; }
  .flippable:hover .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-modal-note {
  max-width: 380px;
  margin: 14px 0 0;
  font-size: 17px;
  line-height: 1.5;
  text-align: center;
  color: var(--ink-dim);
}

.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; }
  .beta-toolbar { padding: 0 14px 10px; 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)); }
  .beta-info { font-size: 16px; padding: 12px 14px; margin-bottom: 16px; }
  .beta-grid { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 12px; }

  /* Mobile trades the tab strip for one row: [buddy] [Dreams] [Back].
     dreamworld.js moves the buddy toggle and Back down into this row. */
  .beta-tabs { display: none; }
  .beta-count { display: none; }
  .beta-toolbar { flex-wrap: nowrap; align-items: stretch; }
  .beta-toolbar > #dwModeBtn,
  .beta-toolbar > #betaBack { flex: 0 0 auto; }
  /* The toolbar stretches its items to the tallest (the buddy toggle, whose
     swatch makes it 36px). The wrap stretches with them, but a block child
     wouldn't, so make it flex and let the button fill it -- otherwise Dreams
     sits ~3px shorter than the buttons either side. */
  .dreams-wrap { display: flex; flex: 1 1 auto; }
  .dreams-btn {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  /* 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-full { display: none; }
  .beta-back-short { display: inline; }
  .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; }
}
