/* Pokemon Heart & Soul documentation - shared styles
 *
 * Presentation is deliberately late-90s/early-2000s fan-site: Verdana, hard
 * bevels, gradient title bars, square corners, visible borders. Palette is the
 * Pokedex itself - red chrome, white paper, grey furniture, blue for anything
 * clickable. Layout mechanics (grid templates, flex-basis rules, sticky heads,
 * the [hidden] overrides) are unchanged from the functional version; only the
 * skin moved. */

:root {
  color-scheme: light dark;

  --page-width: 1180px;
  /* How far down the sticky route headings sit: the search toolbar is itself
     sticky at top:0, so they have to clear it. app.js measures the toolbar and
     overwrites this; the value here is only the no-JS fallback. */
  --stick-top: 72px;

  --bg: #c9d2dc;
  --surface: #ffffff;
  --surface-2: #e9edf2;
  --surface-3: #dbe1e9;
  --border: #8f9aa8;
  --border-soft: #c2cad4;
  --bevel-hi: #ffffff;
  --bevel-lo: #97a2b0;
  --text: #10151b;
  --text-dim: #55606d;

  /* Pokedex red - identity and chrome */
  --accent: #c8102e;
  --accent-dark: #8c0a20;
  --accent-soft: #fadfe3;
  /* Blue - links and subsection bars */
  --blue: #1f4fa8;
  --blue-dark: #16376f;
  --blue-soft: #dee7f7;

  --shadow: 2px 2px 0 rgba(16, 21, 27, .13);
  --radius: 0px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #12161b;
    --surface: #1b212a;
    --surface-2: #242c37;
    --surface-3: #2c3542;
    --border: #45505f;
    --border-soft: #333d4a;
    --bevel-hi: #3d4857;
    --bevel-lo: #10141a;
    --text: #e6eaf0;
    --text-dim: #99a5b4;

    --accent: #ff4d5e;
    --accent-dark: #a5122a;
    --accent-soft: #3b1c23;
    --blue: #7aa7ee;
    --blue-dark: #24406e;
    --blue-soft: #1d2739;

    --shadow: 2px 2px 0 rgba(0, 0, 0, .45);
  }
}

* { box-sizing: border-box; }

img {
  display: block;
  max-width: 100%;
  height: auto;
}

.image-preview {
  display: block;
  max-width: 100%;
  text-decoration: none;
  cursor: zoom-in;
}

.image-preview:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

.image-preview img {
  width: 100%;
  height: auto;
}

.hns-logo {
  max-width: 360px;
  margin: 0 auto;
}

body {
  margin: 0;
  background: var(--bg);
  /* Faint diagonal weave - the tiled-background habit of the era, done as a
     gradient so it costs no request.
     A bare repeating-linear-gradient is rasterised across the WHOLE element
     box, and body on the Pokedex is enormous and changes height every time a
     tab opens. That blew past the browser's gradient tile cap, so the weave
     was drawn at a coarser scale on tall/narrow pages (hence "zoomed in" on
     mobile) and re-scaled on every tab switch. Pinning background-size makes
     it a fixed 4px tile that repeats, so the pattern no longer depends on the
     document's dimensions at all. */
  background-image:
    linear-gradient(45deg,
      rgba(255, 255, 255, .16) 25%, transparent 25%,
      transparent 50%, rgba(255, 255, 255, .16) 50%,
      rgba(255, 255, 255, .16) 75%, transparent 75%);
  background-size: 4px 4px;
  color: var(--text);
  font: 13px/1.5 Verdana, Geneva, Tahoma, "DejaVu Sans", sans-serif;
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 0.75em;
  color: var(--text);
  font-family: "Trebuchet MS", Verdana, sans-serif;
  font-weight: 700;
  line-height: 1.3;
}

p, span, li, ul, ol, td, th, label, button, input, textarea, select {
  color: inherit;
  font: inherit;
  margin: 0 0 1em;
}

p {
  margin: 0 0 1em;
  line-height: 1.7;
}

a { color: var(--blue); text-decoration: underline; }
a:hover { color: var(--accent); }

/* Cross-page links keep the surrounding text's colour so lists don't turn into
   a wall of blue; the underline only appears on hover. */
a.xlink { color: inherit; text-decoration: none; }
a.xlink:hover { color: var(--accent); text-decoration: underline; }
a.xlink:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

/* ---------- header + nav ---------- */

.site-header {
  background: linear-gradient(180deg, var(--accent) 0%, var(--accent-dark) 100%);
  border-bottom: 3px solid var(--text);
  padding: 12px 16px 0;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35);
}

.site-title {
  margin: 0 0 2px;
  font-family: "Trebuchet MS", Verdana, sans-serif;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: .01em;
  color: #fff;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, .45);
}

.site-title a { color: inherit; text-decoration: none; }

.site-sub {
  margin: 0 0 10px;
  color: rgba(255, 255, 255, .82);
  font-size: 11px;
  letter-spacing: .05em;
  text-transform: uppercase;
}

/* Horizontal strips only. overflow-y must be stated: when one axis is not
   "visible" the other computes from "visible" to "auto", so overflow-x alone
   left these vertically scrollable, and the active item's negative bottom
   margin gave them just enough vertical range for touch to rubber-band the
   whole strip out of its box. The bottom padding is what that negative margin
   bleeds into, so clipping at the padding edge doesn't eat it; the container's
   own negative margin puts the layout back. overscroll-behavior-x stops a
   horizontal overscroll from chaining into browser back-navigation. */
.nav {
  display: flex;
  gap: 2px;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  margin: 0 -16px -3px;
  padding: 0 16px 3px;
}
.nav::-webkit-scrollbar { display: none; }

/* Raised tabs sitting on the header's bottom rule, the way every board of the
   era did its section strip. */
.nav a {
  flex: 0 0 auto;
  /* Tight enough that all 14 labels fit one desktop row - "Credits" was
     falling off the end. Tracking is dropped rather than the type size:
     letter-spacing on 14 uppercase labels costs ~40px across the strip and
     buys nothing at this size. */
  padding: 5px 8px;
  background: linear-gradient(180deg, var(--surface-2), var(--surface-3));
  border: 1px solid var(--border);
  border-bottom: 0;
  color: var(--text-dim);
  text-decoration: none;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  white-space: nowrap;
}
.nav a:hover { background: var(--surface); color: var(--text); }
.nav a[aria-current="page"] {
  background: var(--surface);
  color: var(--accent);
  padding-bottom: 7px;
  margin-bottom: -3px;
}

/* ---------- search ---------- */

.toolbar {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--surface-3);
  border-bottom: 2px solid var(--border);
  padding: 8px 16px;
}

.search-wrap { position: relative; max-width: var(--page-width); margin: 0 auto; }

/* Sunken well - the inset counterpart to every raised control on the page. */
#search {
  width: 100%;
  padding: 6px 8px;
  font-family: inherit;
  font-size: 16px; /* 16px stops iOS zooming on focus */
  color: var(--text);
  background: var(--surface);
  border: 2px inset var(--border-soft);
  border-radius: var(--radius);
}
#search:focus { outline: 2px solid var(--blue); outline-offset: -2px; }

.result-count {
  margin: 6px auto 0;
  max-width: var(--page-width);
  font-size: 11px;
  color: var(--text-dim);
}

/* ---------- layout ---------- */

main { max-width: var(--page-width); margin: 0 auto; padding: 16px 16px 64px; }

#home h2{
  font-size: 15px;
}

/* Pages whose entries read better as a tall column than a wide band. */
body.narrow { --page-width: 720px; }
/* Encounters needs room for all six methods side by side. */
body.wide { --page-width: 1360px; }

.empty {
  display: none;
  padding: 48px 16px;
  text-align: center;
  color: var(--text-dim);
}
.empty.show { display: block; }

/* ---------- loading state ---------- */

/* Sits in the markup above the card payload so it paints while the rest of
   the page is still downloading - the Pokedex is ~18 MB and used to show
   nothing but an empty column until it finished. app.js sets body.ready. */
.page-loader {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 56px 16px;
  color: var(--text-dim);
  text-align: center;
  font-size: 12px;
}
body.ready .page-loader { display: none; }

.page-loader-spin {
  width: 26px;
  height: 26px;
  border: 3px solid var(--border-soft);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: page-loader-spin .7s linear infinite;
}

.page-loader-note {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  opacity: .85;
}

@keyframes page-loader-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .page-loader-spin { animation-duration: 2.4s; }
}

/* ---------- panel furniture ----------
   One raised-box treatment shared by every container on the site. */

.loc, .card, .prose {
  background: var(--surface);
  border: 1px solid var(--border);
  border-top-color: var(--bevel-hi);
  border-left-color: var(--bevel-hi);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* Title bars: grey gradient under a red rule. */
.loc > h2, .card > h2 {
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface-3) 100%);
  border-bottom: 2px solid var(--accent);
  box-shadow: inset 0 1px 0 var(--bevel-hi);
  font-family: "Trebuchet MS", Verdana, sans-serif;
}

/* ---------- location cards ---------- */

/* No overflow:hidden here. It makes .loc the nearest scrollport, and a
   sticky child then sticks to a box that never scrolls - i.e. does nothing.
   It was only clipping rounded corners, and the radius is 0. */
.loc { margin-bottom: 14px; }
/* app.js filters by toggling .hidden on whatever carries data-search, and that
   is not always a card - the FAQ and Completion pages are tables, so their
   searchable elements are <tr>. Keying off the attribute covers every page;
   the element-specific rules below are kept as they were. */
[data-search].hidden { display: none; }

.loc.hidden { display: none; }

/* The route name clings to the top while you scroll a long route, the way the
   type chart's row heads cling to the left. Below the toolbar's z-index so it
   tucks under the search bar rather than colliding with it. */
.loc > h2 {
  position: sticky;
  top: var(--stick-top);
  z-index: 5;
  margin: 0;
  padding: 8px 12px;
  font-size: 15px;
  font-weight: 700;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(220px, 1fr));
  gap: 14px;
  padding: 16px;
}

.feature-grid.compact {
  grid-template-columns: repeat(3, minmax(180px, 1fr));
}

@media (max-width: 900px) {
  .feature-grid { grid-template-columns: 1fr; }
}

/* Version badge - small pill */
small.ver {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  font-size: 11px;
  line-height: 1;
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  vertical-align: middle;
}

.time-block { padding: 10px 12px; }
.time-block + .time-block { border-top: 1px dashed var(--border-soft); }

.time-label {
  display: inline-block;
  margin: 0 0 8px;
  padding: 2px 8px;
  color: var(--text);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
}

/* Day and night read faster as their own colours than as two identical red
   pills, and both want to be genuinely bright.
   Brightness is limited by the label text, not by the fill: a real orange is
   too light to carry white text (2.3:1) but carries near-black at 7.9:1, while
   a real purple is the opposite - too dark for black (3.5:1), fine for white
   at 5.3:1. So they get opposite text treatments rather than a compromise
   colour. Contrast is checked against the darker end of each gradient. */
.time-label.time-day {
  border-bottom: 2px solid #d97400;
  color: var(--text);
  text-shadow: none;
}

.time-label.time-day + .methods > .method > ul{
  border-left: 2px solid #d97400;
}

.time-label.time-night {
  border-bottom: 2px solid #7a0fc0;
  color: var(--text);
}

.time-label.time-night + .methods > .method > ul {
  border-left: 2px solid #7a0fc0;
}

.methods {
  display: grid;
  /* six methods have to fit on one row at the page's full width */
  grid-template-columns: repeat(auto-fit, minmax(186px, 1fr));
  gap: 12px;
}

.method h3 {
  margin: 0 0 6px;
  padding: 3px 7px;
  background-color: var(--blue-dark);
  color: #fff;
  font-size: 10px;
  text-wrap: balance;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, .3);
}

.method ul { margin: 0; padding: 0; list-style: none; }

.method li {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 0 8px;
  align-items: center;
  padding: 5px;
  border-bottom: 1px solid var(--border-soft);
}
/* Zebra striping - the table habit of the era, and genuinely useful on a
   six-column encounter grid. */
.method li:nth-child(even) { background: var(--surface-2); }

.monicon {
  grid-row: span 2;
  width: 32px;
  height: 32px;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}
/* keep names aligned when a species has no icon */
.method li > .mon:first-child { grid-column: 2; }
.method li:last-child { border-bottom: 0; }

.mon { font-weight: 700; }
.pct { color: var(--text-dim); font-variant-numeric: tabular-nums; }
.lv {
  grid-column: 2 / -1;
  font-size: 11px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

mark {
  background: #ffe95c;
  color: #10151b;
  border-radius: 0;
  padding: 0 2px;
}

.page-intro {
  margin: 0 0 14px;
  color: var(--text-dim);
  font-size: 12px;
}

.pokedex-tip {
  margin: 0 0 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-top-color: var(--bevel-hi);
  border-left-color: var(--bevel-hi);
  box-shadow: var(--shadow);
}

.pokedex-tip summary {
  list-style: none;
  cursor: pointer;
  padding: 12px 18px;
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface-3) 100%);
  border-bottom: 2px solid var(--accent);
  box-shadow: inset 0 1px 0 var(--bevel-hi);
  font-family: "Trebuchet MS", Verdana, sans-serif;
  font-weight: 700;
  color: var(--text);
}

.pokedex-tip summary::-webkit-details-marker { display: none; }

.pokedex-tip summary::before {
  content: "▸";
  display: inline-block;
  margin-right: 8px;
  color: var(--accent);
}

.pokedex-tip[open] summary::before {
  content: "▾";
}

.pokedex-tip-body {
  padding: 16px 18px 18px;
}

.pokedex-tip-body img {
  display: block;
  width: 100%;
  max-width: 960px;
  height: auto;
  margin: 0 auto;
  border: 1px solid var(--border-soft);
  background: var(--surface-2);
}

/* ---------- home page title art ---------- */

.title-art {
  display: block;
  width: 100%;
  max-width: 720px;
  height: auto;
  margin: 0 auto 18px;
  border: 3px double var(--border);
  background: var(--surface);
  padding: 4px;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

/* ---------- work in progress banner ---------- */

.wip {
  margin: 0 0 18px;
  padding: 20px 18px;
  border: 3px dashed var(--accent);
  background: var(--accent-soft);
  text-align: center;
  box-shadow: var(--shadow);
}

.wip h2 {
  margin: 0 0 8px;
  font-family: "Trebuchet MS", Verdana, sans-serif;
  font-size: clamp(22px, 6vw, 38px);
  line-height: 1.1;
  font-weight: 700;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--accent);
  text-shadow: 1px 1px 0 var(--bevel-hi);
}

.wip p {
  margin: 0 auto;
  max-width: 52ch;
  font-size: 12.5px;
  color: var(--text);
}

.feature-hero,
.feature-section,
.prose {
  margin: 0 0 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-top-color: var(--bevel-hi);
  border-left-color: var(--bevel-hi);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.feature-hero-header,
.feature-header,
.prose-header {
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface-3) 100%);
  border-bottom: 2px solid var(--accent);
  box-shadow: inset 0 1px 0 var(--bevel-hi);
  padding: 12px 18px;
  margin: 0;
}

.feature-hero-header h2,
.prose-header h2,
.feature-header h2 {
  margin: 0;
  font-size: clamp(1.05rem, 2vw, 1.35rem);
}

.feature-section {
  overflow: hidden;
}


.feature-section img,
.feature-header img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
  border-bottom: 1px solid var(--border-soft);
  background: var(--surface-2);
}

.feature-header h2 {
  padding: 12px 18px;
}

.feature-grid {
  /* Flex layout: three columns on wider screens, one on narrow devices */
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  padding: 16px;
}

.feature-grid.compact {
  gap: 12px;
}

/* Each card takes roughly a third of the available width minus gaps on wide screens. */
.feature-grid .feature-card {
  flex: 1 1 calc((100% - 28px) / 3);
  min-width: 220px;
}

@media (max-width: 500px) {
  .feature-grid .feature-card { flex-basis: 100%; }
}

/* Version badge - small pill */
small.ver {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  font-size: 11px;
  line-height: 1;
  color: var(--text-dim);
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  vertical-align: middle;
}

.feature-card {
  background: linear-gradient(180deg, var(--surface) 0%, var(--surface-2) 100%);
  border: 1px solid var(--border-soft);
}

.feature-card h3 {
  margin: 0 0 8px;
  font-family: "Trebuchet MS", Verdana, sans-serif;
  font-size: 0.95rem;
  font-weight: 700;
  border-bottom: 2px solid var(--blue-dark);
  letter-spacing: .02em;
  padding: 10px 14px;
}

.feature-card p {
  padding: 0 14px 10px 14px;
  margin: 0;
  color: var(--text);
  line-height: 1.6;
}

.home-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: 8px 16px;
  margin: 12px 0 0;
  padding-left: 20px;
}

.home-links li {
  margin: 0;
  padding: 2px 0;
}

/* ---------- walkthrough ---------- */

/* The disclaimer follows you down the page - the walkthrough is ~500 KB of
   sections and the caveat matters just as much 200 sections in as it does at
   the top. Sits below the sticky search toolbar using the same measured offset
   the encounters page uses for its route headings. */
.wt-note {
  position: sticky;
  top: var(--stick-top);
  z-index: 4;
  margin: 0 0 14px;
  padding: 8px 12px;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  border-left: 5px solid var(--accent);
  color: var(--text);
  font-size: 12.5px;
  line-height: 1.45;
}

.wt-section h2 { scroll-margin-top: calc(var(--stick-top) + 60px); }
.wt-section p { margin: 0 0 10px; }
.wt-section p:last-child { margin-bottom: 0; }

.wt-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.wt-table th, .wt-table td {
  border: 1px solid var(--border-soft);
  padding: 4px 7px;
  text-align: left;
  vertical-align: top;
}
.wt-table th {
  background: var(--surface-2);
  font-weight: 700;
  white-space: nowrap;
}

/* ---------- prose pages ---------- */

.prose-body,
.feature-hero-body {
  padding: 16px 18px 18px;
}

.prose-body > p,
.prose-body > ul {
  margin-bottom: 12px;
}

.prose-body > p:last-child,
.prose-body > ul:last-child {
  margin-bottom: 0;
}

footer {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: 0 16px 40px;
  color: var(--text-dim);
  font-size: 11px;
  text-align: center;
}

@media (max-width: 640px) {
  main { padding: 12px 10px 56px; }
  .toolbar { padding: 8px 10px; }
  .site-header { padding: 10px 12px 0; }
  .nav { margin: 0 -12px; padding: 0 12px; }
  .methods { grid-template-columns: 1fr; gap: 12px; }
}

/* ---------- generic data card ---------- */

.card { margin-bottom: 12px; overflow: hidden; }
.card.hidden { display: none; }

.card > h2 {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 8px 12px;
  font-size: 14px;
  font-weight: 700;
}

.card-num {
  color: var(--text-dim);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  margin: 0;
}

.card-body { padding: 10px 12px; }

.card-note {
  margin: 0 0 10px;
  color: var(--text-dim);
  font-size: 12px;
}

.card-note.big { color: var(--text); font-size: 13px; line-height: 1.55; }

.setting-note { margin: 0; font-size: 11px; color: var(--text-dim); }
.setting-note code {
  font-family: "Courier New", ui-monospace, Menlo, monospace;
  font-size: 11px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  padding: 0 3px;
}

/* ---------- move name highlight ----------
   Tinted with its own type's colour, from assets/type-colors.css. Alpha rather
   than a fixed colour so it works in both themes and the text stays readable. */

.mv {
  border-radius: 0;
  padding: 0 4px;
  background: rgba(var(--type, 128, 128, 128), .45);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

@media (prefers-color-scheme: dark) {
  .mv { background: rgba(var(--type, 128, 128, 128), .55); }
}

/* ---------- type plates ---------- */

.typeicon {
  display: block;
  width: 64px;
  height: 32px;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

/* The sprite, name and types of one form sit on a single line, with the type
   plates pushed to the right edge of the card. */
.formswap {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
}
/* display:flex would otherwise beat the hidden attribute and show every form */
.formswap[hidden] { display: none; }

.mon-name { min-width: 0; overflow-wrap: anywhere; margin: 0}

.trainerpic {
  flex: 0 0 64px;
  width: 64px;
  height: 64px;
  margin: -10px 4px -10px 0;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

.itemicon {
  flex: 0 0 48px;
  width: 48px;
  height: 48px;
  margin: -6px 2px -6px 0;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

.caticon {
  display: block;
  width: 32px;
  height: 32px;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

.types { display: flex; flex-wrap: wrap; gap: 4px; margin-left: auto; align-items: center; }

@media (max-width: 640px) {
  .formswap { gap: 6px; }
  .typeicon { width: 52px; height: 26px; }
}

/* ---------- badges ---------- */

.badges { display: flex; flex-wrap: wrap; gap: 5px; margin-left: auto; }

.badge {
  padding: 1px 7px;
  border-bottom: 2px solid var(--border);
  font-size: 10.5px;
  font-weight: 700;
  color: var(--text-dim);
  white-space: nowrap;
}
.badge.strong {
  border-color: var(--accent-dark);
  color: var(--text);
  text-shadow: 1px 1px 0 rgba(0, 0, 0, .3);
}

/* species that exist in the build but aren't part of normal play */
.badge.randomizer {
  background: var(--surface-2);
  border-style: dashed;
  border-color: var(--border);
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: .05em;
}

/* ---------- stat strip ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  margin-bottom: 12px;
}

.stat {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-top-color: var(--bevel-hi);
  border-left-color: var(--bevel-hi);
  padding: 5px 3px;
  text-align: center;
}
.stat b { display: block; font-size: 13px; font-variant-numeric: tabular-nums; }
.stat span {
  display: block;
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--text-dim);
}

/* ---------- key/value grid ---------- */

.kv { display: block; margin: 0; font-size: 12.5px; }
.kv > div {
  display: flex;
  align-items: baseline;
  gap: 10px;
  border-bottom: 1px solid var(--border-soft);
  padding: 5px 0;
}
.kv > div:last-child { border-bottom: 0; }
.kv dt {
  flex: 0 0 132px;
  color: var(--text-dim);
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
}
.kv dd { margin: 0; flex: 1; min-width: 0; }

/* ---------- inline lists (moves, locations) ---------- */

.block { margin-bottom: 12px; }
.block:last-child { margin-bottom: 0; }

/* Blue title bar. Loud on purpose: these head short lists that otherwise run
   together, especially where the grid wraps. */
.block h3 {
  margin: 0 0 6px;
  padding: 3px 7px;
  background-color: var(--blue-dark);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, .3);
}

.inline-list { margin: 0; font-size: 12.5px; line-height: 1.65; }
.inline-list .lvl { color: var(--text-dim); font-variant-numeric: tabular-nums; }
.inline-list .sep { color: var(--border); padding: 0 3px; }

.stack { margin: 0; padding: 0; list-style: none; font-size: 12.5px; }
.stack li {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  padding: 5px 0;
  border-bottom: 1px solid var(--border-soft);
}
.stack li:last-child { border-bottom: 0; margin-bottom: 0; }
.stack li:last-child > span { margin-bottom: 0; }
.stack .where { font-weight: 700; flex-basis: 100%; }
.stack .how { color: var(--text-dim); font-size: 11.5px; }
/* "~", not "+": a location with several encounters (the Day/Night split is
   the common one) has one .how per entry, and the adjacent combinator indented
   only the first - the rest fell back to the flex line's left edge. Each entry
   is its own fact, so each gets its own row at the same indent. */
.stack .where ~ .how { flex-basis: 100%; padding-left: 12px; }

.ability-lists {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
}
.ability-lists .block { margin-bottom: 0; }

/* ---------- species lists ----------
   Vertical lists that wrap into columns, so 70 species stay readable rather
   than becoming one very long strip. */

.monlist {
  /* Multi-column so entries run top-to-bottom. The column COUNT is set inline
     per list from the number of species: a width-based rule gives one item per
     column on short lists, which reads as a horizontal row. */
  column-gap: 16px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.monlist li {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
  font-size: 12px;
  border-bottom: 1px solid var(--border-soft);
  break-inside: avoid;          /* don't split a row across a column break */
  -webkit-column-break-inside: avoid;
}

/* Collapsed by default - a move with 150 learners would otherwise bury the
   rest of the card. Native <details>, so it works in cards the windowed
   renderer builds after app.js has already run. */
.learners > summary {
  cursor: pointer;
  color: var(--blue);
  font-weight: 700;
  padding: 2px 0;
  list-style-position: inside;
}
.learners > summary:hover { color: var(--accent); }
.learners > summary:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.learners[open] > summary { margin-bottom: 4px; }

.monlist img {
  flex: 0 0 32px;
  width: 32px;
  height: 32px;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

@media (max-width: 640px) {
  .monlist { column-count: 2 !important; }
}

/* ---------- group headings ---------- */

.group-heading {
  margin: 24px 0 8px;
  padding: 4px 9px;
  background: linear-gradient(180deg, var(--surface-2), var(--surface-3));
  border: 1px solid var(--border);
  border-left: 5px solid var(--accent);
  font-family: "Trebuchet MS", Verdana, sans-serif;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text);
  box-shadow: var(--shadow);
}
.group-heading:first-child { margin-top: 4px; }

/* ---------- party (trainers) ---------- */

.party {
  display: grid;
  /* Fixed six slots rather than auto-fit: a smaller party leaves the remaining
     slots empty instead of stretching, so team sizes are comparable down the
     page at a glance. */
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 8px;
}

@media (max-width: 1200px) {
  .party { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.mon-card {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-top-color: var(--bevel-hi);
  border-left-color: var(--bevel-hi);
  padding: 7px 8px;
}
.mon-head { display: flex; align-items: center; gap: 4px; margin-bottom: 2px; }
.mon-head .monicon { flex: 0 0 32px; margin: -4px 0; }
.mon-card h4 { margin: 0; font-size: 12.5px; }
.mon-card .meta { color: var(--text-dim); font-size: 11px; margin-bottom: 5px; }
.mon-card ul { margin: 0; padding-left: 15px; font-size: 11.5px; }

/* ---------- prose tables ---------- */

.prose table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.prose th, .prose td {
  text-align: left;
  vertical-align: top;
  padding: 6px 9px;
  border: 1px solid var(--border-soft);
}
.prose th {
  background-color: var(--blue-dark);
  color: #fff;
  font-size: 11px;
  text-transform: uppercase;
  font-weight: bold;
  letter-spacing: .05em;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, .3);
}
.prose tbody tr:nth-child(even) { background: var(--surface-2); }
/* Same axis fix. No negative margins inside a table, so nothing to absorb. */
.table-scroll { overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; }

@media (max-width: 640px) {
  .stats { grid-template-columns: repeat(4, 1fr); }
  .kv { grid-template-columns: 1fr; }
  .party { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .badges { margin-left: 0; width: 100%; }
}

/* ---------- sprite in the card header ----------
   Sitting beside the name keeps it visible on every tab. */

.monpic {
  flex: 0 0 56px;
  width: 56px;
  height: 56px;
  margin: -6px 2px -6px 0;
  image-rendering: pixelated;          /* keep the GBA pixels crisp when scaled */
  image-rendering: crisp-edges;
}

@media (max-width: 640px) {
  .monpic { flex-basis: 44px; width: 44px; height: 44px; }
}

/* ---------- attribute rows ----------
   One attribute per line: label on the left, everything else running
   horizontally to its right. */

.rows { font-size: 12.5px; }

.row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 5px 0;
  border-bottom: 1px solid var(--border-soft);
}
.row:last-child { border-bottom: 0; }

.row-label {
  flex: 0 0 132px;
  color: var(--text-dim);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
}

.row-value { flex: 1; min-width: 0; line-height: 1.65; }

/* Base stats: seven items overflow a phone card, so "Spe" drops to a second
   row on its own and reads as a rendering fault rather than a line break.
   Shrunk below 640px until the set fits; wrap stays on as a safety valve.
   Spacing is in em so it tightens with the type instead of eating the width
   the smaller font just freed. Tahoma first because Verdana is wide enough to
   cost roughly a stat's worth of room across the row. */
.statline {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-family: Tahoma, Verdana, Geneva, sans-serif;
}
.statline span { color: var(--text-dim); font-size: 11px; text-transform: uppercase;
                 letter-spacing: .02em; }
.statline b { font-variant-numeric: tabular-nums; font-weight: 700; margin-left: 4px;
              color: var(--text); }
.statline .total b { color: var(--accent); }

@media (max-width: 640px) {
  .statline { gap: 4px .5em; font-size: 10px; }
  .statline span { font-size: inherit; letter-spacing: 0; }
  .statline b { margin-left: .25em; }
}

/* Small phones lose another ~30px of card width. */
@media (max-width: 380px) {
  .statline { font-size: 9px; }
}

.row-value .evo-line { padding: 2px 0; }

@media (max-width: 640px) {
  .row { flex-direction: column; gap: 2px; }
  .row-label { flex: none; }
  .kv > div { flex-direction: column; gap: 1px; }
  .kv dt { flex: none; }
}

/* ---------- move columns ----------
   One column per source, each a vertical list. */

.movecols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  /* Row gap is deliberately larger than the column gap: when the grid wraps,
     a section starts level with the middle of the list beside it, and an even
     gap left it looking like more of that list. */
  gap: 20px 12px;
}

/* Blue title bar, matching .block h3. A dim label was lighter than the move
   names under it, so a wrapped section read as a continuation of the list
   above rather than a new heading. */
.movecol h3 {
  margin: 0 0 6px;
  padding: 3px 7px;
  background-color: var(--blue-dark);
  color: var(--text);
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, .3);
}

.movecol ul { margin: 0; padding: 0; list-style: none; font-size: 12px; }
.movecol li { padding: 3px 0; border-bottom: 1px solid var(--border-soft); }
.movecol li:last-child { border-bottom: 0; }
.movecol .lvl {
  display: inline-block;
  min-width: 22px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  .movecols { grid-template-columns: repeat(2, 1fr); gap: 20px 12px; }
}

/* ---------- form selector ---------- */

.forms-label {
  align-self: center;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-dim);
  margin-right: 4px;
}

.forms {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 7px 12px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border-soft);
}

/* Raised push-buttons; the pressed one is genuinely inset. */
.formpill {
  appearance: none;
  border: 1px solid var(--border);
  border-top-color: var(--bevel-hi);
  border-left-color: var(--bevel-hi);
  background: linear-gradient(180deg, var(--surface), var(--surface-3));
  border-radius: var(--radius);
  padding: 2px 9px;
  font-family: inherit;
  font-size: 11px;
  color: var(--text-dim);
  cursor: pointer;
  white-space: nowrap;
}
.formpill:hover { color: var(--text); background: var(--surface); }
.formpill[aria-pressed="true"] {
  background: linear-gradient(180deg, var(--accent) 0%, var(--accent-dark) 100%);
  border-color: var(--accent-dark);
  color: #fff;
  font-weight: 700;
  text-shadow: 1px 1px 0 rgba(0, 0, 0, .3);
}
.formpill:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

.formlist { display: flex; flex-wrap: wrap; gap: 8px 14px; }
.formlist figure { margin: 0; width: 72px; text-align: center; }
.formlist img { width: 48px; height: 48px; image-rendering: pixelated; }
.formlist figcaption { font-size: 10.5px; color: var(--text-dim); line-height: 1.3; }

/* ---------- pokedex tabs ---------- */

.tabs {
  display: flex;
  gap: 3px;
  /* bottom padding absorbs the selected tab's -1px bleed - see .nav */
  padding: 5px 8px 1px;
  margin-bottom: -1px;
  background: var(--surface-3);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }

.tab {
  flex: 0 0 auto;
  appearance: none;
  background: linear-gradient(180deg, var(--surface-2), var(--surface-3));
  border: 1px solid var(--border);
  border-bottom: 0;
  padding: 4px 10px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--text-dim);
  cursor: pointer;
  white-space: nowrap;
}
.tab:hover { background: var(--surface); color: var(--text); }
.tab[aria-selected="true"] {
  background: var(--surface);
  color: var(--accent);
  padding-bottom: 5px;
  margin-bottom: -1px;
}
.tab:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }

.panel[hidden] { display: none; }

.evo-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 3px 8px;
  padding: 3px 0;
}
.evo-line .arrow { color: var(--accent); font-weight: 700; flex: 0 0 auto; }

.evopic {
  flex: 0 0 40px;
  width: 40px;
  height: 40px;
  margin: -6px 0;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}

.evo-name { font-weight: 700; }
.evo-line .how { flex-basis: 100%; padding-left: 60px; }


/* ---------- type chart ---------- */

/* border-collapse must stay "separate" here. WebKit does not support
   position:sticky on a table cell when borders are collapsed - it paints
   borders and backgrounds at the table level instead of the cell, so the stuck
   row-head loses its background and the rest of the chart scrolls straight over
   it. On Safari that reads as the left column simply not being there.
   With separate borders each cell owns its own edges, so only one side is drawn
   per cell and the shared 1px grid is rebuilt from right+bottom edges plus a
   left edge on the first column and a top edge on the header. */
.typechart {
  border-collapse: separate;
  border-spacing: 0;
  font-variant-numeric: tabular-nums;
  /* Keep the chart at its natural size and let .table-scroll scroll it. A
     table only grows to max-content if it fits; otherwise it shrinks toward
     min-content, which crushed the columns instead of overflowing. */
  width: max-content;
}

/* The global "img { max-width: 100% }" lets the type plates shrink with the
   column, which is what made the header squash rather than the table overflow.
   These are fixed-size sprites - they should never scale. */
.typechart img { max-width: none; }
.typechart th, .typechart td {
  border: 0;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  text-align: center;
  padding: 0;
}
.typechart tr > *:first-child { border-left: 1px solid var(--border); }
.typechart thead th { border-top: 1px solid var(--border); }
.typechart th { background: var(--surface-3); padding: 2px; }
/* Opaque background is load-bearing: the cells it overlaps must not show
   through. z-index above the body cells, below the header row. */
.typechart .rowhead {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--surface-3);
}
.typechart td {
  width: 34px;
  height: 30px;
  font-size: 11px;
  font-weight: 700;
  color: var(--text-dim);
}
.typeicon.small { width: 48px; height: 24px; }

.typechart .x2, .chip.x2 { background: rgba(64, 168, 96, .35); color: var(--text); }
.typechart .x05, .chip.x05 { background: rgba(200, 120, 40, .30); color: var(--text); }
.typechart .x0, .chip.x0 { background: rgba(120, 120, 130, .45); color: var(--text); }

.chip {
  display: inline-block;
  min-width: 20px;
  padding: 0 5px;
  border: 1px solid var(--border-soft);
  text-align: center;
  font-weight: 700;
}

/* Pickup odds grid: many columns, so it scrolls like the type chart. */
.pickup { border-collapse: collapse; font-size: 11.5px; width: max-content; }
.pickup th, .pickup td {
  border: 1px solid var(--border-soft);
  padding: 3px 7px;
  text-align: center;
  white-space: nowrap;
}
.pickup thead th { background: var(--surface-2); font-weight: 700; }
.pickup tbody th { text-align: left; font-weight: 550; }
/* Icon and name on one line. The shared .itemicon rule is sized for a card
   heading, so the flex basis and negative margins are overridden here. */
.pickup-item { display: flex; align-items: center; gap: 4px; }
.pickup-item .itemicon {
  flex: 0 0 24px;
  width: 24px;
  height: 24px;
  margin: -2px 0;
}
.pickup td:empty { background: var(--surface-2); }

/* ---------- shiny pairs ---------- */

.shinypair { display: flex; gap: 18px; }
.shinypair figure { margin: 0; text-align: center; }
.shinypair img { image-rendering: pixelated; image-rendering: crisp-edges; }
.shinypair figcaption { font-size: 10.5px; color: var(--text-dim); }

.typerow { display: flex; flex-wrap: wrap; gap: 5px; }
.block h3 .caticon { vertical-align: -8px; margin-right: 4px; }
