/* A dark-fantasy-tabletop palette (warm near-blacks, bronze/gold trim, a
   parchment off-white for text) crossed with the Pokédex's own signature
   fire-red, instead of the cool neutral grays this started as -- see
   --gold/--gold-dim below, the ::before corner brackets on .card, and the
   Cinzel display font used for headings/nav/buttons throughout this file. */
:root {
  --bg: #ddc79e;
  --panel: #efe2c2;
  --panel-alt: #e6d5ab;
  --border: #b39962;
  --text: #2a2116;
  --text-dim: #5c4a30;
  --accent: #b3301a;
  --accent-dim: #f0d3c4;
  --accent-2: #3d6fa8;
  --gold: #9c7a2e;
  --gold-dim: #e4d5ab;
  --good: #3f7d3a;
  --warn: #b06a1e;
  --bad: #a5291c;
  --radius: 8px;
  /* UI density. Every font-size / padding / margin / gap below is written as
     calc(Npx * var(--s)): 1 reproduces the original sizing (phones and
     tablets keep their carefully tuned values), below 1 tightens the roomy
     desktop sizing, and ultrawide screens get a little more back. */
  --s: .82;
  --sidenav-w: calc(226px * var(--s));
  --topbar-h: calc(58px * var(--s) + env(safe-area-inset-top, 0px));
  --content-max: 2400px; /* widest the page content grows on ultrawides */
  --col-min: 640px;      /* narrowest a card column gets (so 1080p = 2 columns, 3440 = 3) */
  --font-display: "Cinzel", Georgia, "Segoe UI", serif;
  --font-body: "Alegreya Sans", "Palatino Linotype", Palatino, Georgia, serif;
  --font-lore: "Alegreya", "EB Garamond", "Palatino Linotype", Palatino, Georgia, serif;   /* long reading text: rules, spells, notes */
  --font-title: "Cinzel", Georgia, serif;                                                 /* page and creature titles */
  font-family: var(--font-body);
  font-size-adjust: .5;
  font-variant-numeric: lining-nums;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #14100a;
    --panel: #1e170f;
    --panel-alt: #261e13;
    --border: #4a3a22;
    --text: #ece2cc;
    --text-dim: #a8987a;
    --accent: #e2461f;
    --accent-dim: #3d2015;
    --accent-2: #6fa2e0;
    --gold: #c9a24a;
    --gold-dim: #453a20;
  }
}
:root[data-theme="dark"] {
  --bg: #14100a;
  --panel: #1e170f;
  --panel-alt: #261e13;
  --border: #4a3a22;
  --text: #ece2cc;
  --text-dim: #a8987a;
  --accent: #e2461f;
  --accent-dim: #3d2015;
  --accent-2: #6fa2e0;
  --gold: #c9a24a;
  --gold-dim: #453a20;
}

* { box-sizing: border-box; }
html, body { height: 100%; }

/* Scrollbars -- thin and theme-matched instead of the OS default, on
   every scrollable element (the side nav, tables, panels, ...). Firefox
   gets the standard properties; WebView2 (Chromium) and WKWebView (Mac)
   both support the older ::-webkit-scrollbar pseudo-elements, which is
   what actually renders in the desktop app either way. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background-color: var(--border); border-radius: 999px;
  border: 2px solid transparent; background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background-color: var(--text-dim); }
*::-webkit-scrollbar-corner { background: transparent; }
body {
  margin: 0;
  padding-left: env(safe-area-inset-left, 0px); /* landscape iPhone notch */
  padding-right: env(safe-area-inset-right, 0px);
  background: var(--bg);
  color: var(--text);
  font-size: calc(22px * var(--s));
  line-height: 1.5;
  /* A faint vignette instead of a flat fill -- there's no texture image
     bundled with the app, so this is the whole "worn parchment / dim
     tavern lighting" effect: pure CSS, no extra asset to ship. */
  background-image: radial-gradient(ellipse at 50% -10%, color-mix(in srgb, var(--gold) 10%, transparent), transparent 60%);
}

/* Density by screen: roomy ultrawides (3440x1440) get a bit more than 1080p;
   tablets and phones use the original sizing. */
@media (min-width: 2400px) { :root { --s: .96; } }
@media (max-width: 900px) { :root { --s: 1; } }

#app {
  display: grid;
  grid-template-columns: var(--sidenav-w) minmax(0, 1fr);
  grid-template-rows: var(--topbar-h) 1fr;
  grid-template-areas: "top top" "nav main";
  height: 100vh;
  height: 100dvh; /* iOS Safari: 100vh ignores the collapsing toolbar and cuts content off */
}
/* Campaign-select screen (js/views/campaignSelect.js) -- shown before the
   sidebar/nav mean anything, since every page needs a campaign selected
   first. */
#app.gate-mode {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "top" "main";
}
#app.gate-mode .sidenav, #app.gate-mode .nav-toggle { display: none; }
/* Desktop: the menu can be folded away (the toggle in the top bar; remembered per device) */
@media (min-width: 781px) {
  html.nav-collapsed { --sidenav-w: 0px; }
  html.nav-collapsed .sidenav { display: none; }
  html.nav-collapsed .lava-tower-wrap, html.nav-collapsed .lava-debris { display: none; }
}

.topbar {
  grid-area: top;
  display: flex;
  align-items: center;
  gap: calc(12px * var(--s));
  padding: env(safe-area-inset-top, 0px) calc(18px * var(--s)) 0;
  box-sizing: border-box;
  background: var(--panel);
  border-bottom: 2px solid var(--gold-dim);
  position: relative;
  z-index: 5;
  min-width: 0;
}
.brand { font-weight: 700; display: flex; align-items: center; gap: calc(10px * var(--s)); }
.brand-logo { height: 34px; width: auto; display: block; filter: drop-shadow(0 0 6px color-mix(in srgb, var(--gold) 45%, transparent)); }
.brand-text {
  font-family: var(--font-display); font-size: calc(22px * var(--s)); font-weight: 700;
  letter-spacing: .03em; white-space: nowrap; color: var(--text);
}
@media (max-width: 480px) { .brand-text { display: none; } }
.nav-toggle {
  display: inline-block;
  background: none; border: 1px solid var(--border); border-radius: 8px;
  color: var(--text); font-size: calc(24.5px * var(--s)); padding: calc(5px * var(--s)) calc(11px * var(--s)); cursor: pointer;
}

.sidenav {
  grid-area: nav;
  background: var(--panel);
  border-right: 2px solid var(--gold-dim);
  padding: calc(14px * var(--s)) calc(11px * var(--s));
  overflow-y: auto;
}
.nav-item {
  display: flex; align-items: center; gap: calc(10px * var(--s)); width: 100%; text-align: left;
  background: none; border: 1px solid transparent; color: var(--text);
  padding: calc(13px * var(--s)) calc(15px * var(--s)); margin: calc(2px * var(--s)) 0; border-radius: 7px;
  font-family: var(--font-display); font-size: calc(18.5px * var(--s)); font-weight: 600;
  letter-spacing: .015em; cursor: pointer;
}
.nav-item:hover { background: var(--panel-alt); border-color: var(--gold-dim); }
.nav-item.active {
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 70%, #000));
  border-color: var(--gold); color: #fff; box-shadow: 0 2px 10px color-mix(in srgb, var(--accent) 40%, transparent);
}
.nav-icon { width: 28px; height: 28px; flex-shrink: 0; object-fit: contain; image-rendering: pixelated; }
.nav-icon svg { width: 100%; height: 100%; display: block; }
.nav-sep {
  font-family: var(--font-display); font-size: max(12px, calc(15px * var(--s))); text-transform: uppercase; letter-spacing: .12em;
  color: var(--gold); margin: calc(16px * var(--s)) calc(12px * var(--s)) calc(7px * var(--s)); padding-bottom: calc(4px * var(--s));
  border-bottom: 1px solid var(--gold-dim);
}
.nav-item.nav-hidden, .nav-sep.nav-hidden { display: none; }

.main {
  grid-area: main;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: calc(22px * var(--s)) 0 calc(60px * var(--s));
  /* content is centered with a max width on ultrawides; (100% - max) / 2 is
     the side gutter once the window is wider than --content-max */
  padding-left: max(calc(26px * var(--s)), calc((100% - var(--content-max)) / 2));
  padding-right: max(calc(40px * var(--s)), calc((100% - var(--content-max)) / 2)); /* clears the LOG tab on the right edge */
}
.main::after { content: ""; display: block; height: env(safe-area-inset-bottom, 0px); grid-column: 1 / -1; }

.loading { color: var(--text-dim); padding: calc(40px * var(--s)); text-align: center; }

h1.view-title {
  margin: 0 0 calc(5px * var(--s)); font-size: calc(34.5px * var(--s)); font-family: var(--font-display); font-weight: 700;
  letter-spacing: .015em; color: var(--text);
}
.view-sub { color: var(--text-dim); margin: 0 0 calc(20px * var(--s)); font-size: calc(18.5px * var(--s)); }

h4 { font-family: var(--font-display); letter-spacing: .01em; }

/* Small gold corner brackets on every card -- like an inventory-slot frame
   -- instead of a plain flat-bordered box. Pure CSS (two tiny gradient
   pseudo-elements), no image asset needed. */
.card {
  position: relative;
  background: linear-gradient(160deg, var(--panel), color-mix(in srgb, var(--panel) 92%, var(--gold) 8%));
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: calc(22px * var(--s)) calc(24px * var(--s));
  margin-bottom: calc(20px * var(--s));
  box-shadow: 0 2px 10px rgba(0,0,0,.12);
}
.card::before, .card::after {
  content: ""; position: absolute; width: 16px; height: 16px; pointer-events: none; opacity: .8;
}
.card::before {
  top: -1px; left: -1px; border-top: 2px solid var(--gold); border-left: 2px solid var(--gold);
  border-radius: var(--radius) 0 0 0;
}
.card::after {
  bottom: -1px; right: -1px; border-bottom: 2px solid var(--gold); border-right: 2px solid var(--gold);
  border-radius: 0 0 var(--radius) 0;
}

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: calc(17px * var(--s)); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: calc(17px * var(--s)); }
/* Grid items default to a content-based min-width (not 0), so a wide
   nowrap table sitting inside one (Pokédex/Move Dex's list column) can
   force the whole grid -- and everything above it up to the page -- wider
   than the viewport. Zeroing it lets .table-wrap's own overflow:auto
   scroll internally instead, the same way it already behaves outside a
   grid (e.g. Type Chart, which has never had this problem). */
.grid-2 > *, .grid-3 > * { min-width: 0; }
@media (max-width: 900px) { .grid-2, .grid-3 { grid-template-columns: 1fr; } }

label.field { display: block; margin-bottom: calc(13px * var(--s)); font-size: calc(18px * var(--s)); color: var(--text-dim); }
label.field > span { display: block; margin-bottom: calc(4px * var(--s)); }
input, select {
  width: 100%; padding: calc(13px * var(--s)) calc(15px * var(--s)); border-radius: 7px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text);
  font-size: calc(20px * var(--s)); font-family: var(--font-body);
}
input:focus, select:focus { outline: 2px solid var(--accent-2); outline-offset: 1px; }

button.btn {
  background: linear-gradient(160deg, color-mix(in srgb, var(--accent), #fff 18%), var(--accent));
  color: #fff; border: 1px solid color-mix(in srgb, var(--accent) 60%, #000);
  border-radius: 7px; padding: calc(14px * var(--s)) calc(22px * var(--s)); font-size: calc(19.5px * var(--s)); font-weight: 600; cursor: pointer;
  font-family: var(--font-display); letter-spacing: .01em;
  box-shadow: 0 1px 0 color-mix(in srgb, var(--gold) 50%, transparent) inset;
}
button.btn:hover { border-color: var(--gold); }
button.btn.secondary {
  background: var(--panel-alt); color: var(--text); border: 1px solid var(--border);
  box-shadow: none;
}
button.btn.secondary:hover { border-color: var(--gold); }
button.btn:active { transform: translateY(1px); }
button.btn:disabled { opacity: .45; cursor: not-allowed; }

table.data-table { width: 100%; border-collapse: collapse; font-size: calc(18.5px * var(--s)); }
table.data-table th, table.data-table td {
  text-align: left; padding: calc(12px * var(--s)) calc(14px * var(--s)); border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
table.data-table th {
  color: var(--gold); font-weight: 700; position: sticky; top: 0; background: var(--panel);
  font-family: var(--font-display); font-size: calc(16px * var(--s)); text-transform: uppercase; letter-spacing: .06em;
}
table.data-table tr:hover td { background: var(--panel-alt); }
table.data-table tr.hi td { background: var(--accent-dim); font-weight: 700; }
.table-wrap { overflow: auto; max-height: 65vh; border: 1px solid var(--border); border-radius: var(--radius); }

.combo { position: relative; }
.combo-list {
  position: absolute; z-index: 20; left: 0; right: 0; top: calc(100% + 4px);
  max-height: 260px; overflow-y: auto;
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.3);
  display: none;
}
.combo-list.open { display: block; }
.combo-opt { padding: calc(8px * var(--s)) calc(11px * var(--s)); cursor: pointer; font-size: calc(19.5px * var(--s)); }
.combo-opt:hover, .combo-opt.hi { background: var(--accent); color: #fff; }

.trainer-sprite-picker { display: flex; align-items: center; gap: calc(12px * var(--s)); }
.trainer-sprite-preview {
  width: 108px; height: 108px; object-fit: contain; image-rendering: pixelated;
  background: var(--panel-alt); border: 1px solid var(--border); border-radius: 8px; padding: calc(4px * var(--s)); flex-shrink: 0;
}
.trainer-sprite-picker-controls { display: flex; align-items: center; gap: calc(8px * var(--s)); flex: 1; min-width: 0; flex-wrap: wrap; }
.trainer-sprite-name { font-size: calc(17px * var(--s)); color: var(--text-dim); text-transform: capitalize; margin-right: auto; }
.trainer-portrait-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.trainer-portrait-item img { width: 120px; height: 120px; }
.trainer-portrait-item.selected { border-color: var(--good); box-shadow: 0 0 0 2px var(--good); }

.type-pill {
  display: inline-block; padding: calc(3px * var(--s)) calc(10px * var(--s)); border-radius: 999px;
  font-size: calc(16px * var(--s)); font-weight: 700; color: #fff; text-transform: uppercase;
  letter-spacing: .03em; margin-right: calc(4px * var(--s)); box-shadow: 0 1px 3px rgba(0,0,0,.25);
}
.stat-bars .row { display: grid; grid-template-columns: 78px 1fr 44px; align-items: center; gap: calc(9px * var(--s)); margin: calc(5px * var(--s)) 0; font-size: calc(18px * var(--s)); }
.stat-bars .bar-bg { background: var(--panel-alt); border-radius: 5px; height: 11px; overflow: hidden; border: 1px solid var(--border); }
.stat-bars .bar-fill { height: 100%; background: linear-gradient(90deg, var(--accent-2), color-mix(in srgb, var(--accent-2) 70%, var(--gold))); }
.team-stats-block { margin-top: calc(13px * var(--s)); padding-top: calc(13px * var(--s)); border-top: 1px solid var(--border); }

.result-banner {
  font-family: var(--font-display); font-size: calc(28px * var(--s)); font-weight: 700; text-align: center; padding: calc(17px * var(--s));
  border-radius: var(--radius); margin: calc(11px * var(--s)) 0; border: 1px solid transparent;
}
.result-banner.good { background: color-mix(in srgb, var(--good) 15%, transparent); color: var(--good); border-color: color-mix(in srgb, var(--good) 35%, transparent); }
.result-banner.bad { background: color-mix(in srgb, var(--bad) 15%, transparent); color: var(--bad); border-color: color-mix(in srgb, var(--bad) 35%, transparent); }
.result-banner.neutral { background: var(--panel-alt); color: var(--text); border-color: var(--border); }

/* Ability score rows -- modeled on Baldur's Gate 3's character creation
   screen: a name, a score, two single-checkbox "assign bonus" columns
   (+2 / +1), and the resulting modifier, all in one aligned grid so the
   bonus columns actually line up under their header like BG3's do. */
.ability-grid {
  display: grid; grid-template-columns: 1fr 90px 60px 60px 90px;
  align-items: center; gap: calc(8px * var(--s)) calc(14px * var(--s));
}
.ability-grid-header {
  padding: 0 calc(4px * var(--s)) calc(8px * var(--s)); font-family: var(--font-display); font-size: max(12px, calc(13px * var(--s)));
  text-transform: uppercase; letter-spacing: .08em; color: var(--gold); text-align: center;
}
.ability-grid-header span:first-child, .ability-grid-header span:nth-child(2) { text-align: left; }
.ability-bonus-head { font-size: max(12px, calc(12px * var(--s))); }
.ability-row-wrap {
  background: var(--panel-alt); border: 1px solid var(--border); border-radius: var(--radius);
  padding: calc(12px * var(--s)) calc(14px * var(--s)); margin-bottom: calc(10px * var(--s));
}
.ability-name { font-weight: 700; font-family: var(--font-display); }
.ability-bonus-cell {
  display: flex; justify-content: center; align-items: center; cursor: pointer;
}
.ability-bonus-cell input[type="checkbox"] {
  width: 22px; height: 22px; padding: 0; accent-color: var(--gold); cursor: pointer;
}
.ability-mod-badge { padding: calc(6px * var(--s)) calc(14px * var(--s)) !important; font-size: calc(17px * var(--s)) !important; margin: 0 !important; text-align: center; }
/* Narrow phones: the five fixed columns above add up to more than the screen,
   so tighten them (the name column is the flexible one and keeps ~100px). */
@media (max-width: 480px) {
  .ability-grid { grid-template-columns: minmax(64px, 1fr) 62px 30px 30px 54px; gap: 6px; }
  .ability-name { font-size: 15px; }
  .ability-mod-badge { padding-left: 4px !important; padding-right: 4px !important; }
  .ability-bonus-cell input[type="checkbox"] { width: 20px; height: 20px; }
}
.ability-row-foot { display: flex; align-items: center; gap: calc(12px * var(--s)); margin-top: calc(10px * var(--s)); }

.kv-table { width: 100%; border-collapse: collapse; font-size: calc(18.5px * var(--s)); }
.kv-table td { padding: calc(6px * var(--s)) calc(9px * var(--s)); border-bottom: 1px solid var(--border); }
.kv-table td:first-child { color: var(--gold); width: 45%; font-weight: 600; }

.tc-table { border-collapse: collapse; font-size: calc(16.5px * var(--s)); }
.tc-table th, .tc-table td { border: 1px solid var(--border); padding: calc(5px * var(--s)) calc(7px * var(--s)); text-align: center; min-width: 36px; }
.tc-table th { background: var(--panel-alt); position: sticky; top: 0; }
.tc-table th:first-child, .tc-table td:first-child { position: sticky; left: 0; background: var(--panel-alt); text-align: left; }
.tc-0 { background: #3b0a0a; color: #ff9b9b; }
.tc-0\.5 { background: rgba(201,42,42,.12); }
.tc-1 { color: var(--text-dim); }
.tc-2 { background: rgba(47,158,68,.18); font-weight: 700; }
.tc-4 { background: rgba(47,158,68,.35); font-weight: 800; }
.tc-0\.25 { background: #3b0a0a; color: #ff9b9b; }

.pill-btn {
  display: inline-block; padding: calc(6px * var(--s)) calc(13px * var(--s)); margin: calc(3px * var(--s)) calc(4px * var(--s)) calc(3px * var(--s)) 0; border-radius: 999px;
  border: 1px solid var(--border); background: var(--panel-alt); color: var(--text);
  font-family: var(--font-display); font-size: calc(17px * var(--s)); cursor: pointer;
}
.pill-btn.active { background: var(--accent); color: #fff; border-color: var(--gold); }

.detail-header { display: flex; align-items: center; gap: calc(15px * var(--s)); flex-wrap: wrap; }
.detail-header .name { font-family: var(--font-display); font-size: calc(33.5px * var(--s)); font-weight: 700; }
.detail-header .dex { color: var(--gold); font-weight: 700; }
.dex-sprite { width: 108px; height: 108px; object-fit: contain; image-rendering: pixelated; }
.dex-row-sprite { width: 46px; height: 46px; object-fit: contain; image-rendering: pixelated; display: block; }

.moveset-group h4 { margin: calc(17px * var(--s)) 0 calc(7px * var(--s)); font-size: calc(17px * var(--s)); text-transform: uppercase; letter-spacing: .06em; color: var(--gold); }
.moveset-chip { display: inline-block; padding: calc(5px * var(--s)) calc(10px * var(--s)); margin: calc(2px * var(--s)) calc(3px * var(--s)) calc(2px * var(--s)) 0; border-radius: 6px; background: var(--panel-alt); font-size: calc(17px * var(--s)); border: 1px solid var(--border); cursor: pointer; }
.moveset-chip .lvl { color: var(--text-dim); margin-right: calc(5px * var(--s)); font-weight: 700; }
.moveset-chip.stub { opacity: .55; font-style: italic; }
.moveset-chip.clickable:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
.moveset-chip.clickable:hover .lvl { color: rgba(255,255,255,.8); }

.formula-note { font-size: calc(17px * var(--s)); color: var(--text-dim); background: var(--panel-alt); border-radius: 8px; padding: calc(9px * var(--s)) calc(11px * var(--s)); margin-top: calc(11px * var(--s)); border-left: 3px solid var(--gold); }

/* Evolution box (Pokédex detail panel) -- a small "family tree" strip:
   pre-evolution, current species (highlighted), evolutions, each clickable
   to jump straight to that entry. */
.evo-chain { display: flex; align-items: center; gap: calc(10px * var(--s)); flex-wrap: wrap; margin: calc(4px * var(--s)) 0 calc(6px * var(--s)); }
.evo-node {
  display: flex; flex-direction: column; align-items: center; gap: calc(3px * var(--s));
  padding: calc(8px * var(--s)) calc(10px * var(--s)); border-radius: 8px; border: 1px solid var(--border); background: var(--panel-alt);
  cursor: pointer; min-width: 76px; text-align: center;
}
.evo-node:hover { border-color: var(--gold); }
.evo-node.current { border-color: var(--accent); background: var(--accent-dim); cursor: default; }
.evo-node img { width: 44px; height: 44px; object-fit: contain; image-rendering: pixelated; }
.evo-node .evo-name { font-size: calc(15.5px * var(--s)); font-weight: 600; }
.evo-node .evo-method { font-size: max(12px, calc(14px * var(--s))); color: var(--text-dim); }
.evo-arrow { color: var(--gold); font-size: calc(23px * var(--s)); }

/* ---------------- Battle view ---------------- */

/* Positioning context for the text box overlaying the bottom of the scene
   (see .battle-textbox) -- js/views/battleview.js wraps sceneEl+dialogEl
   in this instead of stacking them as separate blocks. */
.battle-stage { position: relative; }

.battle-scene {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  min-height: 320px;
  padding: calc(18px * var(--s));
  /* Extra clearance at the bottom so the overlaid text box (roughly
     140px tall) never covers the ally row's sprite/HUD. */
  padding-bottom: 152px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: calc(12px * var(--s));
  background: linear-gradient(160deg, var(--panel), color-mix(in srgb, var(--panel) 92%, var(--gold) 8%));
  border: 1px solid var(--border);
  /* A DM-picked background (js/views/battleview.js sets background-image
     inline) is small pixel art stretched to fill the scene — nearest-
     neighbor scaling keeps it crisp instead of the browser's default
     blurry bilinear smoothing. */
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
}

.battle-enemies { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: flex-start; gap: calc(10px * var(--s)) calc(16px * var(--s)); }
.battle-allies { display: flex; flex-wrap: wrap; justify-content: flex-start; align-items: flex-end; gap: calc(10px * var(--s)) calc(16px * var(--s)); margin-top: auto; }

.battle-combatant-slot { display: flex; flex-direction: column; align-items: center; gap: calc(2px * var(--s)); transition: opacity .2s ease; }
.battle-combatant-slot.fainted { opacity: .4; }
.battle-combatant-slot.selectable { cursor: pointer; }
.battle-combatant-slot.selectable .battle-platform::after {
  content: ""; position: absolute; inset: 4px; border-radius: 50%;
  border: 3px dashed var(--accent-2); animation: battle-target-pulse 1.1s ease-in-out infinite;
}
.battle-combatant-slot.selected .battle-platform::after {
  content: ""; position: absolute; inset: 4px; border-radius: 50%;
  border: 3px solid var(--good); animation: none;
}
@keyframes battle-target-pulse { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }
.battle-combatant-slot.active-turn { filter: drop-shadow(0 0 7px var(--good)); }
.battle-combatant-slot.mine .battle-hud { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-dim); }
.enemy-hud { min-width: 130px; padding: calc(6px * var(--s)) calc(10px * var(--s)); }

.battle-platform {
  width: 130px; height: 130px;
  display: flex; align-items: center; justify-content: center;
  position: relative;
  flex-shrink: 0;
}
.battle-platform::before {
  content: ""; position: absolute; bottom: 6px; left: 50%; transform: translateX(-50%);
  width: 100px; height: 28px; border-radius: 50%;
  background: rgba(0,0,0,.18);
}
.battle-sprite {
  position: relative; z-index: 1;
  width: 110px; height: 110px; object-fit: contain;
  image-rendering: pixelated;
  filter: drop-shadow(0 6px 4px rgba(0,0,0,.25));
}

.battle-hud {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: calc(8px * var(--s)) calc(12px * var(--s));
  min-width: 190px;
  box-shadow: 0 4px 10px rgba(0,0,0,.15);
}
.battle-hud-row { display: flex; justify-content: space-between; align-items: baseline; gap: calc(10px * var(--s)); margin-bottom: calc(6px * var(--s)); }
.battle-name { font-weight: 700; font-size: calc(18.5px * var(--s)); }
.battle-level { color: var(--text-dim); font-size: calc(16px * var(--s)); }
.battle-hpbar-bg { background: var(--panel-alt); border-radius: 5px; height: 9px; overflow: hidden; border: 1px solid var(--border); }
.battle-hpbar-fill { height: 100%; transition: width .4s ease; }
.battle-hpbar-fill.good { background: #2f9e44; }
.battle-hpbar-fill.warn { background: #e8b800; }
.battle-hpbar-fill.bad { background: #c92a2a; }
.battle-hp-numbers { text-align: right; font-size: max(12px, calc(15px * var(--s))); color: var(--text-dim); margin-top: calc(3px * var(--s)); }
.battle-status { display: inline-block; margin-top: calc(5px * var(--s)); padding: calc(1px * var(--s)) calc(7px * var(--s)); border-radius: 999px; background: var(--accent-dim); color: var(--accent); font-size: max(12px, calc(14px * var(--s))); font-weight: 700; text-transform: uppercase; }
.battle-opp-switch { margin: calc(4px * var(--s)) 0; font-size: calc(15.5px * var(--s)); padding: calc(3px * var(--s)) calc(6px * var(--s)); }

/* The dialogue box overlaid on the bottom of the scene (see .battle-stage/
   .battle-scene's padding-bottom above) -- styled like the rest of the
   site's cards (same panel/border/gold-corner treatment as .card) rather
   than a standalone reskin, so the battle screen doesn't look like a
   different app from everything around it. */
.battle-textbox {
  position: absolute; left: 14px; right: 14px; bottom: 14px;
  background: linear-gradient(160deg, var(--panel), color-mix(in srgb, var(--panel) 92%, var(--gold) 8%));
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: calc(14px * var(--s)) calc(18px * var(--s));
  min-height: 110px;
  box-shadow: 0 10px 26px rgba(0,0,0,.3);
  z-index: 2;
}
.battle-prompt { font-weight: 700; margin-bottom: calc(12px * var(--s)); line-height: 1.5; }
.battle-message { font-weight: 700; text-align: center; padding: calc(20px * var(--s)) 0; line-height: 1.5; color: var(--text); }

.battle-menu-grid { display: grid; grid-template-columns: 1fr 1fr; gap: calc(8px * var(--s)); }
.battle-menu-grid.moves { grid-template-columns: 1fr 1fr; margin-bottom: calc(10px * var(--s)); }
.battle-menu-btn {
  background: linear-gradient(160deg, color-mix(in srgb, var(--accent), #fff 18%), var(--accent));
  color: #fff; border: 1px solid color-mix(in srgb, var(--accent) 60%, #000);
  border-radius: 7px; padding: calc(13px * var(--s)) calc(12px * var(--s)); font-size: calc(15.5px * var(--s)); font-weight: 600;
  cursor: pointer; font-family: var(--font-display); letter-spacing: .01em;
  box-shadow: 0 1px 0 color-mix(in srgb, var(--gold) 50%, transparent) inset;
}
.battle-menu-btn:hover { border-color: var(--gold); }
.battle-menu-btn:active { transform: translateY(1px); }
.battle-menu-btn.move { background: var(--panel-alt); color: var(--text); border: 1px solid var(--border); box-shadow: none; }
.battle-menu-btn.move:hover { border-color: var(--gold); }
.battle-back { margin-top: calc(4px * var(--s)); }

.battle-party-list { display: flex; flex-direction: column; gap: calc(6px * var(--s)); margin-bottom: calc(10px * var(--s)); }
.battle-party-btn { text-align: left; }

/* ---------------- VS Screen (Battle Control's "vs" phase, Battle screen) ---------------- */

.vs-screen {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: calc(20px * var(--s)); min-height: 320px; padding: calc(28px * var(--s)) calc(16px * var(--s)); border-radius: var(--radius);
  border: 1px solid var(--border); text-align: center;
  background: linear-gradient(160deg, var(--panel), color-mix(in srgb, var(--panel) 92%, var(--gold) 8%));
}
.vs-symbol {
  font-size: 2.2em; font-weight: 800; letter-spacing: .08em; color: var(--accent);
  text-shadow: 0 2px 10px rgba(0,0,0,.35);
}
.vs-sides { display: flex; justify-content: space-between; align-items: flex-start; width: 100%; gap: calc(14px * var(--s)); }
.vs-side { display: flex; flex-wrap: wrap; gap: calc(10px * var(--s)); flex: 1; }
.vs-side-a { justify-content: flex-start; }
.vs-side-b { justify-content: flex-end; }
.vs-portrait {
  display: flex; flex-direction: column; align-items: center; gap: calc(5px * var(--s));
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: calc(12px * var(--s)) calc(14px * var(--s)); min-width: 150px; box-shadow: 0 4px 10px rgba(0,0,0,.15);
}
.vs-portrait-sprite { width: 130px; height: 130px; object-fit: contain; image-rendering: pixelated; }
.vs-portrait-name { font-weight: 700; font-size: calc(19px * var(--s)); text-align: center; }
.vs-portrait-trainer { font-size: calc(16px * var(--s)); color: var(--text-dim); text-align: center; }
@media (max-width: 700px) {
  .vs-sides { flex-direction: column; }
  .vs-side-a, .vs-side-b { justify-content: center; }
}

/* ---------------- Generic modal (level-up move swap, ...) ---------------- */

.modal-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 1000; padding: calc(20px * var(--s));
}
.modal-box {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: calc(20px * var(--s)); max-width: 420px; width: 100%; box-shadow: 0 12px 40px rgba(0,0,0,.35);
}
.modal-slot-list { display: flex; flex-direction: column; gap: calc(8px * var(--s)); margin: calc(12px * var(--s)) 0; }
.modal-slot-btn { text-align: left; }

/* ---------------- Turn order strip (Battle screen) ---------------- */

.turn-order-box {
  display: flex; gap: calc(8px * var(--s)); overflow-x: auto; padding: calc(8px * var(--s)) calc(10px * var(--s)); margin-bottom: calc(10px * var(--s));
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
}
.turn-order-item {
  display: flex; flex-direction: column; align-items: center; gap: calc(2px * var(--s));
  flex-shrink: 0; width: 76px; padding: calc(4px * var(--s)); border-radius: 8px; opacity: .6;
}
.turn-order-item.active { opacity: 1; background: var(--accent-dim); box-shadow: 0 0 0 2px var(--accent); }
.turn-order-item.mine .turn-order-name { color: var(--accent); font-weight: 700; }
.turn-order-sprite { width: 50px; height: 50px; object-fit: contain; image-rendering: pixelated; }
.turn-order-name { font-size: max(12px, calc(13.5px * var(--s))); text-align: center; line-height: 1.2; max-width: 76px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.has-info { cursor: help; }

/* Generic hover/tap info popover (js/infoTooltip.js) -- the Battle screen's
   combatant popover, and the Pokédex/Move Dex/Bag's item descriptions. */
.info-tooltip {
  position: fixed; z-index: 1000; max-width: 280px;
  background: var(--panel); border: 1px solid var(--gold); border-radius: 8px;
  padding: calc(12px * var(--s)) calc(14px * var(--s)); box-shadow: 0 12px 34px rgba(0,0,0,.5); font-size: calc(19.5px * var(--s));
}
.info-tooltip-title { font-family: var(--font-display); font-weight: 700; font-size: calc(22px * var(--s)); margin-bottom: calc(5px * var(--s)); color: var(--gold); }
.info-tooltip-row { color: var(--text-dim); margin-top: calc(3px * var(--s)); line-height: 1.4; }

/* ---------------- Dice roll FX (Battle screen) ---------------- */

.dice-fx-card {
  position: fixed; bottom: 20px; left: 20px; z-index: 950;
  display: flex; align-items: center; gap: calc(10px * var(--s));
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: calc(10px * var(--s)) calc(16px * var(--s)) calc(10px * var(--s)) calc(12px * var(--s)); box-shadow: 0 8px 28px rgba(0,0,0,.35);
  animation: dice-fx-in .2s ease-out;
}
.dice-fx-card.fade-out { animation: dice-fx-out .4s ease-in forwards; }
@keyframes dice-fx-in { from { transform: translateY(12px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@keyframes dice-fx-out { to { transform: translateY(12px); opacity: 0; } }
.dice-fx-die {
  font-size: calc(33.5px * var(--s)); width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
  border-radius: 8px; background: var(--panel-alt); border: 2px solid var(--border); flex-shrink: 0;
}
.dice-fx-die.rolling { animation: dice-fx-spin .6s linear infinite; }
@keyframes dice-fx-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.dice-fx-die.hit { border-color: var(--good); color: var(--good); font-size: calc(23px * var(--s)); font-weight: 800; }
.dice-fx-die.miss { border-color: var(--bad); color: var(--bad); font-size: calc(23px * var(--s)); font-weight: 800; }
.dice-fx-label { font-weight: 700; font-size: calc(17px * var(--s)); }
.dice-fx-roll { font-size: calc(16px * var(--s)); color: var(--text-dim); }

/* ---------------- Bag page ---------------- */

.bag-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: calc(12px * var(--s)); margin-bottom: calc(20px * var(--s)); }
.bag-item-card {
  position: relative;
  background: var(--panel); border: 2px solid var(--border); border-radius: var(--radius);
  padding: calc(10px * var(--s)); display: flex; flex-direction: column; align-items: center; gap: calc(4px * var(--s)); text-align: center;
}
.bag-item-rarity-tag {
  position: absolute; top: -8px; right: -6px; font-size: max(12px, calc(11.5px * var(--s))); font-weight: 800; text-transform: uppercase;
  letter-spacing: .03em; color: #fff; padding: calc(2px * var(--s)) calc(6px * var(--s)); border-radius: 999px; box-shadow: 0 2px 6px rgba(0,0,0,.3);
}
.bag-item-icon { width: 68px; height: 68px; object-fit: contain; image-rendering: pixelated; margin-top: calc(4px * var(--s)); }
.bag-item-name { font-size: calc(16px * var(--s)); font-weight: 600; line-height: 1.25; }
.bag-item-count { font-size: calc(15.5px * var(--s)); color: var(--text-dim); }
.bag-item-actions { display: flex; gap: calc(6px * var(--s)); margin-top: calc(4px * var(--s)); flex-wrap: wrap; justify-content: center; }
.bag-item-mini-btn { padding: calc(3px * var(--s)) calc(8px * var(--s)) !important; font-size: max(12px, calc(15px * var(--s))) !important; }

/* ---------------- Icon picker modal ---------------- */
/* Sized off the viewport (not a fixed px cap) so it actually fills most of
   the current window instead of sitting small in the middle of it, with
   much larger icon tiles than the generic modal box defaults to. */

.icon-picker-box { width: min(94vw, 1000px); max-width: none; max-height: 88vh; display: flex; flex-direction: column; }
.icon-picker-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: calc(12px * var(--s));
  overflow-y: auto; max-height: 68vh; margin: calc(8px * var(--s)) 0 calc(14px * var(--s)); padding: calc(4px * var(--s));
}
.icon-picker-item {
  cursor: pointer; border: 1px solid var(--border); border-radius: 10px; background: var(--panel-alt);
  padding: calc(10px * var(--s)); display: flex; align-items: center; justify-content: center;
}
.icon-picker-item:hover { border-color: var(--accent); background: var(--accent-dim); }
.icon-picker-item img { width: 76px; height: 76px; object-fit: contain; image-rendering: pixelated; }

/* ---------------- Log drawer (Battle screen, My Team) ---------------- */

.log-drawer-toggle {
  position: fixed; top: 50%; right: 0; transform: translateY(-50%);
  z-index: 880; background: var(--panel); color: var(--text-dim);
  border: 1px solid var(--border); border-right: none; border-radius: 8px 0 0 8px;
  padding: calc(14px * var(--s)) calc(7px * var(--s)); cursor: pointer; box-shadow: -4px 0 12px rgba(0,0,0,.15);
  font-size: max(12px, calc(14.5px * var(--s))); font-weight: 800; letter-spacing: .08em;
}
.log-drawer-toggle.open { background: var(--accent); color: #fff; border-color: var(--accent); }
.log-drawer-panel {
  position: fixed; top: 10%; right: 0; bottom: 10%; z-index: 879;
  width: 320px; max-width: calc(100vw - 20px);
  background: var(--panel); border: 1px solid var(--border); border-right: none;
  border-radius: 10px 0 0 10px; box-shadow: -8px 0 28px rgba(0,0,0,.3);
  flex-direction: column; overflow: hidden;
}
.log-drawer-header { display: flex; align-items: center; justify-content: space-between; gap: calc(10px * var(--s)); padding: calc(12px * var(--s)) calc(14px * var(--s)); border-bottom: 1px solid var(--border); }
.log-drawer-tabs { display: flex; gap: calc(6px * var(--s)); }
.log-drawer-body { flex: 1; overflow-y: auto; padding: calc(12px * var(--s)) calc(14px * var(--s)); }
.log-drawer-entry { background: var(--panel-alt); border-radius: 8px; padding: calc(8px * var(--s)) calc(10px * var(--s)); margin-bottom: calc(8px * var(--s)); font-size: calc(16.5px * var(--s)); }

@media (max-width: 480px) {
  .log-drawer-panel { top: 5%; bottom: 5%; width: calc(100vw - 40px); }
}

/* ---------------- Widget dock (Dice Tray + Quick Console buttons) ---------------- */
/* Both floating buttons live in ONE fixed flex row (js/widgetDock.js), so
   they always share a baseline, size and spacing -- no per-button offsets to
   drift apart at different window sizes. Their panels anchor to the same
   variables. env(safe-area-inset-*) keeps them clear of phone notches and
   home indicators. */
:root { --dock-size: 54px; --dock-gap: 10px; --dock-edge: 20px; }
@media (max-width: 480px) { :root { --dock-size: 50px; --dock-edge: 12px; } }
.widget-dock {
  position: fixed; z-index: 900;
  right: max(var(--dock-edge), env(safe-area-inset-right));
  bottom: max(var(--dock-edge), env(safe-area-inset-bottom));
  display: flex; flex-direction: row; align-items: center; justify-content: flex-end; gap: var(--dock-gap);
}
.dice-widget-btn, .quick-console-btn {
  flex: 0 0 var(--dock-size); width: var(--dock-size); height: var(--dock-size); box-sizing: border-box;
  display: grid; place-items: center; padding: 0; line-height: 1;
  border-radius: 50%; cursor: pointer; box-shadow: 0 6px 18px rgba(0,0,0,.3);
}
.dice-widget-btn { order: 1; background: var(--panel); color: var(--text); border: 1px solid var(--border); font-size: calc(var(--dock-size) * .62); }
.dice-widget-btn.open { background: var(--accent); color: #fff; border-color: var(--accent); }
.dice-widget-btn:active, .quick-console-btn:active { transform: translateY(1px); }

/* ---------------- Dice widget ---------------- */

.dice-widget-panel {
  position: fixed; z-index: 900;
  /* opens above the dice button: the dock's right edge, plus the BAG button and the gap */
  right: calc(max(var(--dock-edge), env(safe-area-inset-right)) + var(--dock-size) + var(--dock-gap));
  bottom: calc(max(var(--dock-edge), env(safe-area-inset-bottom)) + var(--dock-size) + var(--dock-gap));
  grid-template-columns: repeat(3, auto); justify-content: center; gap: calc(10px * var(--s));
  max-width: calc(100vw - 2 * var(--dock-edge)); box-sizing: border-box;
  max-height: 70vh; max-height: min(70vh, calc(100dvh - var(--topbar-h) - var(--dock-edge) * 2 - var(--dock-size) - var(--dock-gap)));
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 12px 40px rgba(0,0,0,.35); padding: calc(14px * var(--s));
}
.dice-widget-item { display: flex; flex-direction: column; align-items: center; gap: calc(6px * var(--s)); min-width: 0; }
.dice-widget-die {
  width: 56px; height: 56px; border-radius: 10px; border: 1px solid var(--border); padding: 0;
  background: var(--panel-alt); color: var(--text); font-weight: 800; font-size: calc(19.5px * var(--s)); cursor: pointer;
}
.dice-widget-die:active { transform: translateY(1px); }
.dice-widget-die.rolling { animation: dice-fx-spin .55s linear infinite; background: var(--accent-dim); }
.dice-widget-result { font-size: calc(19.5px * var(--s)); font-weight: 800; min-height: 24px; line-height: 24px; color: var(--accent); }

/* ---------------- Trainer presence toasts ---------------- */

.presence-toast-stack {
  position: fixed; top: calc(var(--topbar-h) + 12px); left: 50%; transform: translateX(-50%);
  z-index: 960; display: flex; flex-direction: column; gap: calc(8px * var(--s)); align-items: center; pointer-events: none;
}
.presence-toast {
  background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
  padding: calc(8px * var(--s)) calc(18px * var(--s)); font-size: calc(17px * var(--s)); font-weight: 600; box-shadow: 0 8px 24px rgba(0,0,0,.3);
  opacity: 0; transform: translateY(-10px); transition: opacity .25s ease, transform .25s ease;
}
.presence-toast.show { opacity: 1; transform: translateY(0); }
.presence-toast.online { border-color: var(--good); color: var(--good); }
.presence-toast.offline { border-color: var(--text-dim); color: var(--text-dim); }

/* ---------------- Floating Quick Console ---------------- */

.quick-console-btn { order: 2; background: var(--accent); color: #fff; border: none; font-size: calc(var(--dock-size) * .29); font-weight: 800; letter-spacing: .04em; }
.quick-console-panel {
  position: fixed; z-index: 900; box-sizing: border-box;
  right: max(var(--dock-edge), env(safe-area-inset-right));
  bottom: calc(max(var(--dock-edge), env(safe-area-inset-bottom)) + var(--dock-size) + var(--dock-gap));
  width: min(340px, calc(100vw - 2 * var(--dock-edge)));
  max-height: 70vh; max-height: min(70vh, calc(100dvh - var(--topbar-h) - var(--dock-edge) * 2 - var(--dock-size) - var(--dock-gap)));
  overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: 0 12px 40px rgba(0,0,0,.35); padding: calc(14px * var(--s));
  font-size: max(12px, calc(15px * var(--s)));
}
/* Everything inside is sized for a ~300px box, not the full page: the page's
   own 20px inputs / 19.5px buttons / two-column grids are what used to squash
   and spill. Layouts collapse on the PANEL's width (auto-fit), since the
   page-level media queries only know the window's. */
.quick-console-panel * { min-width: 0; }
.quick-console-panel input, .quick-console-panel select {
  font-size: calc(16px * var(--s)); /* >=16px stops iOS zooming the page on focus */
  padding: calc(8px * var(--s)) calc(11px * var(--s)); min-height: 40px; max-width: none !important;
}
.quick-console-panel label.field { font-size: max(12px, calc(14px * var(--s))); margin-bottom: calc(10px * var(--s)); }
.quick-console-panel .grid-2, .quick-console-panel .grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 130px), 1fr)); gap: calc(10px * var(--s)); }
.quick-console-stack { display: flex; flex-direction: column; gap: calc(10px * var(--s)); }
.quick-console-panel .btn {
  width: auto; /* undo the phone rule that makes every .btn full-width: it crushed the bag rows */
  font-size: calc(15.5px * var(--s)); padding: calc(9px * var(--s)) calc(12px * var(--s)); min-height: 40px; line-height: 1.25;
  white-space: normal; overflow-wrap: anywhere; text-align: center;
}
.quick-console-panel h4 { font-size: calc(16px * var(--s)); margin: calc(12px * var(--s)) 0 calc(8px * var(--s)); }
.quick-console-panel .view-sub { font-size: max(12px, calc(14.5px * var(--s))); margin: 0 0 calc(8px * var(--s)); }
.quick-console-panel .formula-note { font-size: max(12px, calc(14.5px * var(--s))); padding: calc(7px * var(--s)) calc(9px * var(--s)); overflow-wrap: anywhere; }
.quick-console-panel .combo-opt { font-size: calc(15.5px * var(--s)); padding: calc(7px * var(--s)) calc(10px * var(--s)); overflow-wrap: anywhere; }
.quick-console-header { display: flex; justify-content: space-between; align-items: center; gap: calc(8px * var(--s)); margin-bottom: calc(8px * var(--s)); }
.quick-console-header strong { font-family: var(--font-display); font-size: calc(17px * var(--s)); }
.quick-console-close { flex: none; background: none; border: none; font-size: calc(19.5px * var(--s)); line-height: 1; padding: calc(6px * var(--s)); cursor: pointer; color: var(--text-dim); }
.quick-console-tabs { display: flex; flex-wrap: wrap; gap: calc(6px * var(--s)); margin-bottom: calc(10px * var(--s)); }
.quick-console-tabs .pill-btn { flex: 1 1 auto; font-size: max(12px, calc(14px * var(--s))); padding: calc(7px * var(--s)) calc(10px * var(--s)); white-space: nowrap; }
.quick-console-bag-list { display: flex; flex-direction: column; gap: calc(6px * var(--s)); }
.quick-console-bag-row {
  display: flex; justify-content: space-between; align-items: center; gap: calc(8px * var(--s));
  font-size: max(12px, calc(15px * var(--s))); background: var(--panel-alt); padding: calc(6px * var(--s)) calc(9px * var(--s)); border-radius: 6px;
}
.quick-console-bag-row > span { flex: 1 1 auto; overflow-wrap: anywhere; line-height: 1.25; }
.quick-console-bag-row .btn { flex: none; }
.quick-console-mini-btn { padding: calc(2px * var(--s)) calc(10px * var(--s)) !important; font-size: max(12px, calc(15px * var(--s))) !important; min-height: 32px !important; }
.quick-console-bag-link { display: block; margin-top: calc(10px * var(--s)); font-size: max(12px, calc(15px * var(--s))); color: var(--accent-2); text-align: right; }

@media (max-width: 480px) {
  /* padding-bottom stays large (not reset by the shorthand above) so the
     overlaid .battle-textbox still clears the ally row at phone width. */
  .battle-scene { min-height: 260px; padding: calc(12px * var(--s)); padding-bottom: 140px; }
  .battle-textbox { left: 8px; right: 8px; bottom: 8px; padding: calc(11px * var(--s)) calc(13px * var(--s)); }
  .battle-platform { width: 92px; height: 92px; }
  .battle-sprite { width: 80px; height: 80px; }
  .battle-hud { min-width: 140px; padding: calc(6px * var(--s)) calc(9px * var(--s)); }
  .battle-menu-btn { padding: calc(14px * var(--s)) calc(10px * var(--s)); font-size: max(12px, calc(13.5px * var(--s))); }
  .enemy-hud { min-width: 100px; }
  .battle-enemies { justify-content: center; }
}

@media (max-width: 780px) {
  :root { --sidenav-w: 200px; }
  .nav-toggle { display: inline-block; }
  /* grid-template-areas must drop to one column too, not just
     grid-template-columns -- otherwise "nav main" still implies 2 columns,
     the sidenav (now position:fixed, so it never actually sizes one) leaves
     a phantom auto-sized track behind, and .main ends up sized to its own
     content instead of the full viewport -- shows up as .main getting
     shoved right with a dead gap on the left on pages whose content
     doesn't happen to be wide enough to fill that phantom column. */
  #app { grid-template-columns: minmax(0, 1fr); grid-template-areas: "top" "main"; }
  .sidenav {
    position: fixed; top: var(--topbar-h); left: 0; bottom: 0; width: var(--sidenav-w);
    transform: translateX(-100%); transition: transform .18s ease; z-index: 15;
  }
  .sidenav.open { transform: translateX(0); box-shadow: 4px 0 18px rgba(0,0,0,.25); }
  .main { padding: calc(14px * var(--s)) calc(14px * var(--s)) calc(50px * var(--s)); }
}

/* Phone-sized touchscreens: bigger tap targets, no accidental iOS zoom,
   tighter spacing so more fits without horizontal scrolling. One size
   step larger across the board than a typical mobile stylesheet, since
   everything here otherwise ends up feeling cramped on an actual phone. */
@media (max-width: 480px) {
  html { -webkit-text-size-adjust: 100%; }
  body { font-size: calc(16px * var(--s)); }

  h1.view-title { font-size: calc(21px * var(--s)); }
  .view-sub { font-size: max(12px, calc(14px * var(--s))); margin-bottom: calc(15px * var(--s)); }
  .main { padding: calc(11px * var(--s)) calc(11px * var(--s)) calc(58px * var(--s)); }
  .card { padding: calc(14px * var(--s)); margin-bottom: calc(13px * var(--s)); }

  /* Inputs stay well above 16px regardless, which is what actually stops
     Mobile Safari from auto-zooming the page on focus. */
  input, select {
    font-size: calc(17px * var(--s)); padding: calc(12px * var(--s)) calc(13px * var(--s)); min-height: 47px;
  }
  label.field { margin-bottom: calc(15px * var(--s)); }

  button.btn {
    padding: calc(13px * var(--s)) calc(19px * var(--s)); font-size: calc(16px * var(--s)); width: 100%; min-height: 48px;
  }
  /* only for buttons stacked in normal flow -- inside a grid they'd knock the rows out of line */
  :not(.grid-2):not(.grid-3):not(.battle-menu-grid) > button.btn + button.btn { margin-top: calc(8px * var(--s)); }

  .nav-toggle { min-width: 46px; min-height: 46px; font-size: calc(21px * var(--s)); }
  .nav-item { padding: calc(14px * var(--s)) calc(15px * var(--s)); font-size: calc(16px * var(--s)); min-height: 46px; }

  .combo-opt { padding: calc(13px * var(--s)) calc(15px * var(--s)); font-size: calc(16px * var(--s)); min-height: 46px; display: flex; align-items: center; }
  .combo-list { -webkit-overflow-scrolling: touch; max-height: 45vh; }

  table.data-table { font-size: max(12px, calc(12.5px * var(--s))); }
  table.data-table th, table.data-table td { padding: calc(8px * var(--s)) calc(6px * var(--s)); }
  .table-wrap { -webkit-overflow-scrolling: touch; max-height: 55vh; }
  .hide-mobile { display: none; }
  /* These two got noticeably bigger in an earlier "make icons/fields
     bigger" pass, sized for desktop -- fine there, but a 46px sprite plus
     full-size type pills is what was actually forcing Pokédex/Move Dex's
     table wider than a phone screen (Type Chart doesn't use .type-pill or
     row sprites at all, which is why it never had this problem). Pulled
     back down for phone width specifically; desktop is untouched. */
  .dex-row-sprite { width: 26px; height: 26px; }
  .type-pill { font-size: max(12px, calc(11px * var(--s))); padding: calc(2px * var(--s)) calc(7px * var(--s)); margin-right: calc(3px * var(--s)); }

  .kv-table { font-size: max(12px, calc(14px * var(--s))); }
  .kv-table td { padding: calc(9px * var(--s)); }

  .grid-2, .grid-3 { gap: calc(11px * var(--s)); }

  .result-banner { font-size: calc(19px * var(--s)); padding: calc(15px * var(--s)); }

  .moveset-chip { padding: calc(8px * var(--s)) calc(12px * var(--s)); font-size: max(12px, calc(14px * var(--s))); }
  .pill-btn { padding: calc(9px * var(--s)) calc(14px * var(--s)); font-size: max(12px, calc(14px * var(--s))); }
}

/* ---------------- Settings page ---------------- */

/* Tabs that split Settings into small pages; on a narrow phone the row
   scrolls sideways instead of wrapping onto several lines. */
.settings-tabs {
  display: flex; gap: calc(6px * var(--s)); margin: 0 0 calc(18px * var(--s)); padding-bottom: calc(6px * var(--s));
  overflow-x: auto; scrollbar-width: thin; -webkit-overflow-scrolling: touch;
  border-bottom: 1px solid var(--border);
}
.settings-tabs .pill-btn { flex: 0 0 auto; margin: 0; white-space: nowrap; }
.settings-danger { border-color: color-mix(in srgb, var(--bad) 55%, var(--border)); }
.settings-danger h4 { color: var(--bad); }
/* a button beside a labelled field lines up with the input, not the whole label+input block */
.settings-panel .grid-2 > .btn { align-self: end; margin-bottom: calc(13px * var(--s)); }

.settings-page-row {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: calc(8px * var(--s));
  padding: calc(8px * var(--s)) 0; border-bottom: 1px solid var(--border);
}
.settings-page-row > span { flex: 1 1 160px; min-width: 0; overflow-wrap: anywhere; }
.settings-page-row .btn { width: auto; padding: calc(8px * var(--s)) calc(14px * var(--s)); min-height: 40px; font-size: calc(15.5px * var(--s)); }
.settings-page-row:last-child { border-bottom: none; }

.toggle-switch { position: relative; display: inline-block; width: 40px; height: 22px; flex-shrink: 0; }
.toggle-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle-switch .slider {
  position: absolute; inset: 0; background: var(--panel-alt); border: 1px solid var(--border);
  border-radius: 999px; cursor: pointer; transition: background .15s ease, border-color .15s ease;
}
.toggle-switch .slider::before {
  content: ""; position: absolute; width: 16px; height: 16px; left: 2px; top: 2px;
  background: var(--text-dim); border-radius: 50%; transition: transform .15s ease, background .15s ease;
}
.toggle-switch input:checked + .slider { background: var(--accent-dim); border-color: var(--accent); }
.toggle-switch input:checked + .slider::before { transform: translateX(18px); background: var(--accent); }
.toggle-switch input:focus-visible + .slider { outline: 2px solid var(--accent-2); outline-offset: 2px; }

/* ---------------- Account card (js/accountCard.js) ---------------- */
.auth-or { text-align: center; color: var(--text-dim); margin: calc(14px * var(--s)) 0 calc(10px * var(--s)); font-size: max(12px, calc(15px * var(--s))); text-transform: uppercase; letter-spacing: .12em; }
.auth-providers { display: flex; flex-direction: column; align-items: center; gap: calc(10px * var(--s)); }
.auth-providers .btn { width: 100%; max-width: 320px; }
.auth-msg:empty { display: none; }
.auth-msg { margin: calc(12px * var(--s)) 0 0; color: var(--bad); }

/* ---------------- Account chip (title bar, js/accountChip.js) ---------------- */
.account-chip { position: relative; margin-left: auto; flex-shrink: 1; min-width: 0; }
.account-chip:empty { display: none; }
.account-chip-btn {
  display: flex; align-items: center; gap: calc(9px * var(--s)); max-width: 100%;
  background: var(--panel-alt); color: var(--text); border: 1px solid var(--border);
  border-radius: 999px; padding: calc(5px * var(--s)) calc(14px * var(--s)) calc(5px * var(--s)) calc(6px * var(--s)); cursor: pointer; font-size: calc(16px * var(--s)); font-family: var(--font-body);
}
.account-chip-btn:hover, .account-chip-btn[aria-expanded="true"] { border-color: var(--gold); }
.account-chip-avatar {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  background: var(--accent); color: #fff; font-family: var(--font-display); font-weight: 700; font-size: max(12px, calc(15px * var(--s)));
}
.account-chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 240px; }
.account-chip-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 30; min-width: 230px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 10px 28px rgba(0,0,0,.35); padding: calc(6px * var(--s)); display: flex; flex-direction: column;
}
.account-chip-menu[hidden] { display: none; }
.account-chip-who { padding: calc(8px * var(--s)) calc(10px * var(--s)) calc(10px * var(--s)); display: flex; flex-direction: column; gap: calc(2px * var(--s)); font-size: max(12px, calc(14px * var(--s))); color: var(--text-dim); border-bottom: 1px solid var(--border); margin-bottom: calc(4px * var(--s)); }
.account-chip-who strong { color: var(--text); font-size: calc(15.5px * var(--s)); word-break: break-all; }
.account-chip-item {
  text-align: left; background: none; border: none; color: var(--text); padding: calc(10px * var(--s)); border-radius: 6px;
  cursor: pointer; font-family: var(--font-display); font-size: calc(16px * var(--s));
}
.account-chip-item:hover { background: var(--accent-dim); }
@media (max-width: 480px) {
  .account-chip-label { display: none; }
  .account-chip-btn { padding: calc(5px * var(--s)); }
}

/* ======================= Wide-screen layout ======================= */
/* Pages that are stacks of independent cards flow into columns instead of
   one very wide card per row: two columns at 1920x1080, three at 3440x1440,
   one on phones (the min() makes the column no wider than the screen).
   Anything that isn't a card -- titles, headings, notes, tables -- spans the
   full width. data-view is set on <main> by setView() in js/app.js. */
.main[data-view="trainer"], .main[data-view="statcalc"], .main[data-view="damagecalc"],
.main[data-view="tierguide"], .main[data-view="trainersOnline"], .settings-panel, .card-grid {
  display: grid; align-items: start; align-content: start; justify-content: start;
  column-gap: calc(20px * var(--s));
  /* auto-fill + 1fr: the column COUNT comes from the minimum width, and an
     unused column stays empty instead of stretching a lone card across the screen */
  grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--col-min)), 1fr));
}
.main[data-view="trainer"] > :not(.card), .main[data-view="statcalc"] > :not(.card), .main[data-view="damagecalc"] > :not(.card),
.main[data-view="tierguide"] > :not(.card), .main[data-view="trainersOnline"] > :not(.card), .card-grid > :not(.card),
.main[data-view] > .card:has(table), .main[data-view] > .card:has(.table-wrap), .settings-panel > .card:has(table) {
  grid-column: 1 / -1;
}

/* Pages built around one wide element look better capped and centered than
   stretched across a 3440px screen. */
.main[data-view="battleview"] > *, .main[data-view="typechart"] > *, .main[data-view="controlcentre"] > * {
  max-width: 1700px; margin-left: auto; margin-right: auto;
}
.main[data-view="bag"] > .card { max-width: 860px; }

/* ======================= Feel: touch, focus, motion ======================= */
html { -webkit-tap-highlight-color: transparent; }
/* no 300ms double-tap-zoom wait on iPhone: taps register immediately */
a, button, input, select, textarea, label, .nav-item, .pill-btn { touch-action: manipulation; }
:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }

@media (prefers-reduced-motion: no-preference) {
  @keyframes view-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
  @keyframes pop-in { from { opacity: 0; transform: translateY(8px) scale(.97); } to { opacity: 1; transform: none; } }

  /* Page changes and settings tabs: a quick fade-and-rise, lightly staggered.
     Only opacity/transform, ~0.2s, never blocks clicks. */
  .main.view-enter > *, .settings-panel.tab-enter > * { animation: view-in .2s cubic-bezier(.22, .8, .3, 1) both; }
  .main.view-enter > :nth-child(2), .settings-panel.tab-enter > :nth-child(2) { animation-delay: 30ms; }
  .main.view-enter > :nth-child(3), .settings-panel.tab-enter > :nth-child(3) { animation-delay: 55ms; }
  .main.view-enter > :nth-child(4), .settings-panel.tab-enter > :nth-child(4) { animation-delay: 75ms; }
  .main.view-enter > :nth-child(n+5), .settings-panel.tab-enter > :nth-child(n+5) { animation-delay: 90ms; }

  /* Floating panels and the account menu pop in from their button. */
  .quick-console-panel, .dice-widget-panel { animation: pop-in .16s ease-out; transform-origin: bottom right; }
  .account-chip-menu:not([hidden]) { animation: pop-in .14s ease-out; transform-origin: top right; }

  /* Every control reacts instantly and smoothly (specificity 0: any control
     that already declares its own transition keeps it). */
  :where(button, .nav-item, .pill-btn, input, select, .combo-opt) {
    transition: background-color .14s ease, border-color .14s ease, color .14s ease, box-shadow .14s ease, transform .09s ease, opacity .14s ease;
  }
  :where(button:not(:disabled), .nav-item, .pill-btn):active { transform: scale(.97); }
  @media (hover: hover) {
    button.btn:not(:disabled):not(.secondary):hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,.25); }
  }
}

/* Touch screens: the small +/- buttons need a finger-sized target. */
@media (pointer: coarse) {
  .bag-item-mini-btn, .quick-console-mini-btn { min-height: 40px !important; min-width: 40px; }
}

/* My Team card header: identity row, then the action buttons as one row. */
.mon-header { display: flex; flex-direction: column; gap: calc(10px * var(--s)); }
.mon-actions { display: flex; flex-wrap: wrap; gap: calc(8px * var(--s)); }
.mon-actions .btn { width: auto; }
@media (max-width: 480px) { .mon-actions .btn { flex: 1 1 calc(50% - 8px); } } /* two per row on a phone */
.mon-header .detail-header { flex-wrap: nowrap; }
.mon-header .detail-header .name { flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; line-height: 1.15; }
.mon-header .detail-header > * { flex-shrink: 0; }
.mon-header .detail-header > .name { flex-shrink: 1; }
.mon-actions .btn { padding: calc(9px * var(--s)) calc(14px * var(--s)); font-size: max(13px, calc(16px * var(--s))); min-height: 0; }
@media (max-width: 600px) {
  /* narrow screens: let a long name drop below the sprite instead of being squeezed beside it */
  .mon-header .detail-header { flex-wrap: wrap; }
  .mon-header .detail-header .name { flex: 0 1 auto; }
  .mon-actions .btn { min-height: 44px; }
}

/* art credit under the campaign picker */
.art-credit { margin: calc(18px * var(--s)) 0 0; font-size: max(12px, calc(13px * var(--s))); line-height: 1.5; color: var(--text-dim); text-align: center; }

/* My Team on phones: per-Pokémon Show/Hide Info (details start hidden) */
.mon-details-toggle { display: none; }
@media (max-width: 900px) {
  .mon-details-toggle { display: block; width: 100%; margin: calc(8px * var(--s)) 0 0; }
  .mon-card:not(.details-open) .mon-details { display: none; }
}
