:root {
  --bg-color: #080b11;
  --panel-bg: rgba(17, 22, 34, 0.65);
  --panel-bg-solid: #111622;
  --border-color: rgba(255, 255, 255, 0.08);
  --text-primary: #f1f5f9;
  --text-secondary: #94a3b8;
  --accent-blue: #0ea5e9;
  --accent-green: #10b981;
  --accent-warning: #f59e0b;
  --accent-danger: #ef4444;
  --accent-purple: #a78bfa;
  --transition-smooth: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: 'Outfit', system-ui, sans-serif;
  background-color: var(--bg-color);
  color: var(--text-primary);
  min-height: 100vh;
  background-image:
    radial-gradient(circle at 10% 20%, rgba(14, 165, 233, 0.08) 0%, transparent 40%),
    radial-gradient(circle at 90% 80%, rgba(167, 139, 250, 0.06) 0%, transparent 40%);
  background-attachment: fixed;
}

.shell { max-width: 1400px; margin: 0 auto; padding: 2rem 1.5rem 4rem; }

.glass-card {
  background: var(--panel-bg);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--border-color);
  border-radius: 16px;
  padding: 1.5rem;
  box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
}

/* Header ---------------------------------------------------------- */
.app-header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap; margin-bottom: 1.25rem;
}
.brand { display: flex; align-items: center; gap: 1rem; }
.logo-accent {
  width: 8px; height: 44px; border-radius: 4px;
  background: linear-gradient(180deg, var(--accent-blue), var(--accent-purple));
  box-shadow: 0 0 18px rgba(14, 165, 233, 0.5);
}
.app-header h1 { font-size: 1.5rem; font-weight: 800; letter-spacing: -0.02em; }
#status-line { color: var(--text-secondary); font-size: 0.85rem; margin-top: 2px; }
.header-actions { display: flex; align-items: flex-end; gap: 0.75rem; flex-wrap: wrap; }

/* Fields ---------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: 0.4rem; }
.field.grow { flex: 1 1 240px; }
.field > span { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-secondary); }
.field > span b { color: var(--accent-blue); font-variant-numeric: tabular-nums; }
.field.checkbox { flex-direction: row; align-items: center; gap: 0.5rem; padding-bottom: 0.5rem; }
.field.checkbox span { text-transform: none; letter-spacing: 0; font-size: 0.85rem; }

input[type="text"], input:not([type]), select, input[list] {
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--border-color);
  border-radius: 10px; padding: 0.6rem 0.8rem;
  color: var(--text-primary); font-family: inherit; font-size: 0.95rem;
  transition: var(--transition-smooth); min-width: 180px;
}
input:focus, select:focus { outline: none; border-color: var(--accent-blue); box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.15); }
input[type="range"] { accent-color: var(--accent-blue); min-width: 150px; }
input[type="checkbox"] { accent-color: var(--accent-blue); width: 16px; height: 16px; }

button { font-family: inherit; cursor: pointer; border-radius: 10px; transition: var(--transition-smooth); }
.btn-primary {
  background: linear-gradient(135deg, var(--accent-blue), #0284c7);
  border: none; color: #fff; font-weight: 600; font-size: 0.95rem;
  padding: 0.65rem 1.4rem;
}
.btn-primary:hover { filter: brightness(1.12); transform: translateY(-1px); }
.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.btn-ghost {
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--border-color);
  color: var(--text-primary); padding: 0.6rem 1.1rem; font-size: 0.9rem;
}
.btn-ghost:hover { background: rgba(255, 255, 255, 0.1); }
.btn-ghost:disabled { opacity: 0.5; cursor: not-allowed; }

/* Tabs ------------------------------------------------------------ */
.tabs { display: flex; gap: 0.5rem; margin-bottom: 1.25rem; flex-wrap: wrap; }
.tab {
  background: transparent; border: 1px solid var(--border-color);
  color: var(--text-secondary); padding: 0.55rem 1.2rem; font-size: 0.9rem; font-weight: 500;
}
.tab:hover { color: var(--text-primary); border-color: rgba(255, 255, 255, 0.18); }
.tab.is-active { background: rgba(14, 165, 233, 0.15); border-color: var(--accent-blue); color: #fff; }
.tab-panel { display: none; }
.tab-panel.is-active { display: block; }
.tab-panel > .glass-card { margin-bottom: 1.25rem; }

/* Sub-tabs, for a tab holding two views that share only a data source (Items:
   what you own vs. what a craft costs). Underlined rather than boxed like the
   main tabs, so one glance separates "which section" from "which view of it". */
.subtabs {
  display: flex; gap: 0.25rem; flex-wrap: wrap;
  margin-bottom: 1.25rem; border-bottom: 1px solid var(--border-color);
}
.subtab {
  background: transparent; border: none; border-bottom: 2px solid transparent;
  border-radius: 0; margin-bottom: -1px;
  color: var(--text-secondary); padding: 0.5rem 1rem;
  font-size: 0.88rem; font-weight: 600;
}
.subtab:hover { color: var(--text-primary); }
.subtab.is-active { color: #fff; border-bottom-color: var(--accent-blue); }
.subtab-panel { display: none; }
.subtab-panel.is-active { display: block; }
/* The cards are no longer direct children of .tab-panel, so they need the gap
   between them restated here or every card in a sub-tab collapses onto the next. */
.subtab-panel > .glass-card { margin-bottom: 1.25rem; }

.planner-controls { display: flex; gap: 1.25rem; align-items: flex-end; flex-wrap: wrap; }
.hint { margin-top: 1rem; color: var(--text-secondary); font-size: 0.85rem; line-height: 1.5; }

/* Stat row -------------------------------------------------------- */
.stat-row { display: flex; gap: 1.5rem; flex-wrap: wrap; margin-top: 1.25rem; }
.stat { display: flex; flex-direction: column; gap: 0.15rem; }
.stat b { font-size: 1.5rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.stat span { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-secondary); }

/* Plan steps ------------------------------------------------------ */
.plan-head { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.25rem; }
.plan-head h2 { font-size: 1.25rem; font-weight: 700; }
.plan-head .badges { display: flex; gap: 0.5rem; flex-wrap: wrap; }

.badge {
  font-size: 0.75rem; font-weight: 600; padding: 0.25rem 0.6rem; border-radius: 999px;
  border: 1px solid transparent; white-space: nowrap;
}
.badge.blue { background: rgba(14, 165, 233, 0.15); border-color: rgba(14, 165, 233, 0.4); color: #7dd3fc; }
.badge.green { background: rgba(16, 185, 129, 0.15); border-color: rgba(16, 185, 129, 0.4); color: #6ee7b7; }
.badge.warn { background: rgba(245, 158, 11, 0.15); border-color: rgba(245, 158, 11, 0.4); color: #fcd34d; }
.badge.grey { background: rgba(148, 163, 184, 0.12); border-color: rgba(148, 163, 184, 0.3); color: var(--text-secondary); }
.badge.purple { background: rgba(167, 139, 250, 0.15); border-color: rgba(167, 139, 250, 0.4); color: #c4b5fd; }

.step {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 1rem 1.25rem; border-radius: 14px;
  background: rgba(0, 0, 0, 0.25); border: 1px solid var(--border-color);
  margin-bottom: 0.75rem;
}
.step-gen {
  flex: 0 0 auto; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em;
  color: var(--text-secondary); text-transform: uppercase;
  min-width: 42px;
}
.pal-chip {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.85rem 0.45rem 0.5rem; border-radius: 10px;
  font-weight: 600; font-size: 0.95rem;
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--border-color);
}

/* Pal icons -------------------------------------------------------
   Transparent 100x100 PNGs. The tinted disc behind them keeps light-coloured
   pals legible on the dark panels and makes a missing icon look deliberate
   rather than broken. `.is-missing` is set from JS when a file fails to load. */
.pal-icon {
  width: 32px; height: 32px; flex: 0 0 auto;
  object-fit: contain; border-radius: 50%;
  background: rgba(255, 255, 255, 0.07);
  image-rendering: -webkit-optimize-contrast;
  /* position + transform (not width) so growing on hover cannot reflow the row. */
  position: relative;
  transition: transform 0.18s cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}
.pal-icon.is-missing { visibility: hidden; }
.pal-icon.lg { width: 44px; height: 44px; }
.pal-icon.md { width: 40px; height: 40px; }
.pal-icon.sm { width: 22px; height: 22px; }

/* Zoom on hover so a 100x100 artwork can actually be made out. Factors are tuned
   per size and kept deliberately modest: the icon grows into the gap that already
   separates it from its own label, so it does not cover the name it belongs to.
   A larger scale looked impressive and read as broken. */
.pal-icon:hover {
  transform: scale(1.45);
  z-index: 30;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
  background: rgba(12, 17, 26, 0.92);
}
.pal-icon.md:hover { transform: scale(1.4); }
.pal-icon.lg:hover { transform: scale(1.3); }
.pal-icon.xl:hover { transform: scale(1.15); }
/* Row-level chips need a stacking context of their own, or a later sibling
   paints over the enlarged icon. */
.pal-chip:hover, .mini-chip:hover, .species-card:hover, .hero-ident:hover { z-index: 20; }
.pal-chip, .mini-chip, .species-card { position: relative; }

@media (prefers-reduced-motion: reduce) {
  .pal-icon { transition: none; }
}

.plan-head .pal-icon { vertical-align: -0.6rem; margin-right: 0.5rem; }

/* A datalist cannot render images, so the resolved target is previewed beside
   the input instead. The slot keeps its width whether or not an icon is shown,
   so the field does not jump as you type. */
.input-with-icon { position: relative; display: flex; align-items: center; gap: 0.5rem; }
/* Matches the lg icon it holds, so the icon does not overflow its own slot. */
.target-preview { width: 44px; height: 44px; flex: 0 0 auto; }
.input-with-icon input { flex: 1 1 auto; min-width: 0; }
.pal-chip.owned { border-color: rgba(16, 185, 129, 0.45); background: rgba(16, 185, 129, 0.1); }
.pal-chip.bred { border-color: rgba(167, 139, 250, 0.45); background: rgba(167, 139, 250, 0.1); }
.pal-chip.child { border-color: rgba(14, 165, 233, 0.5); background: rgba(14, 165, 233, 0.12); }
/* The carrier is the lineage that actually holds the passives being moved, so it
   is the one chip in a transfer step that must stand out. */
.pal-chip.carrier { border-color: rgba(245, 158, 11, 0.55); background: rgba(245, 158, 11, 0.12); }
.pal-chip small { font-weight: 500; font-size: 0.7rem; color: var(--text-secondary); }
.op { color: var(--text-secondary); font-weight: 600; }
.arrow { color: var(--accent-blue); font-size: 1.15rem; font-weight: 700; }
.step-note { flex-basis: 100%; font-size: 0.8rem; color: var(--accent-warning); }

/* Tables / grids -------------------------------------------------- */
.species-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 0.75rem;
}
.species-card {
  padding: 0.9rem 1rem; border-radius: 12px;
  background: rgba(0, 0, 0, 0.25); border: 1px solid var(--border-color);
  transition: var(--transition-smooth);
}
.species-card:hover { border-color: rgba(255, 255, 255, 0.18); transform: translateY(-2px); }
.species-card.pairable { border-left: 3px solid var(--accent-green); }
.species-card .row1 { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
.species-card .row1 .ident { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.species-card .name { font-weight: 700; font-size: 1rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.species-card .count { font-variant-numeric: tabular-nums; font-weight: 800; color: var(--accent-blue); }
.species-card .row2 { display: flex; gap: 0.6rem; margin-top: 0.5rem; flex-wrap: wrap; font-size: 0.78rem; color: var(--text-secondary); }
/* Outfit has no ♂/♀ glyphs, so these fall through to a system font. The explicit
   symbol-capable stack keeps them from landing on a font that lacks them too. */
.gender-m, .gender-f {
  font-weight: 600;
  font-family: 'Outfit', 'Segoe UI Symbol', 'Noto Sans Symbols 2', 'DejaVu Sans', sans-serif;
}
.gender-m { color: #60a5fa; }
.gender-f { color: #f472b6; }

.section-title { font-size: 1.05rem; font-weight: 700; margin: 0 0 0.9rem; }
.shopping-list { display: flex; flex-direction: column; gap: 0.5rem; }
.shopping-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  padding: 0.7rem 1rem; border-radius: 10px;
  background: rgba(0, 0, 0, 0.25); border: 1px solid var(--border-color);
}
.shopping-row .ident { display: flex; align-items: center; gap: 0.75rem; }
.shopping-row .used-for { font-size: 0.78rem; color: var(--text-secondary); }

/* IVs ------------------------------------------------------------
   Three individual values, 0-100 each. The tier colour is the fast signal when
   scanning a list; the number stays visible because 88 vs 92 matters when
   picking a breeding parent. */
.iv-row { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
.iv {
  display: flex; align-items: center; gap: 0.35rem;
  font-size: 0.78rem; font-variant-numeric: tabular-nums;
}
.iv-label { color: var(--text-secondary); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; }
.iv-bar {
  width: 46px; height: 6px; border-radius: 3px; overflow: hidden;
  background: rgba(255, 255, 255, 0.09); flex: 0 0 auto;
}
.iv-bar > i { display: block; height: 100%; border-radius: 3px; }
.iv-value { font-weight: 700; min-width: 1.9em; text-align: right; }

.tier-best   > i { background: linear-gradient(90deg, #10b981, #34d399); }
.tier-good   > i { background: linear-gradient(90deg, #0ea5e9, #38bdf8); }
.tier-ok     > i { background: linear-gradient(90deg, #f59e0b, #fbbf24); }
.tier-weak   > i { background: linear-gradient(90deg, #64748b, #94a3b8); }
.tier-best   + .iv-value, .iv-value.tier-best { color: #6ee7b7; }
.tier-good   + .iv-value, .iv-value.tier-good { color: #7dd3fc; }
.tier-ok     + .iv-value, .iv-value.tier-ok   { color: #fcd34d; }
.tier-weak   + .iv-value, .iv-value.tier-weak { color: var(--text-secondary); }

.iv-total {
  font-weight: 800; font-variant-numeric: tabular-nums;
  padding: 0.2rem 0.55rem; border-radius: 999px; font-size: 0.8rem;
  border: 1px solid transparent;
}
.iv-total.tier-best { background: rgba(16, 185, 129, 0.15); border-color: rgba(16, 185, 129, 0.4); color: #6ee7b7; }
.iv-total.tier-good { background: rgba(14, 165, 233, 0.15); border-color: rgba(14, 165, 233, 0.4); color: #7dd3fc; }
.iv-total.tier-ok   { background: rgba(245, 158, 11, 0.15); border-color: rgba(245, 158, 11, 0.4); color: #fcd34d; }
.iv-total.tier-weak { background: rgba(148, 163, 184, 0.12); border-color: rgba(148, 163, 184, 0.3); color: var(--text-secondary); }

.hide { display: none !important; }

/* Species page ---------------------------------------------------- */
.species-card { cursor: pointer; }
.species-card .iv-row { margin-top: 0.55rem; }

.species-hero #species-back { margin-bottom: 1.25rem; }
.hero-ident { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; }
.hero-ident h2 { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.02em; }
.hero-code {
  color: var(--text-secondary); font-size: 0.8rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.hero-ident .badges { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.pal-icon.xl { width: 68px; height: 68px; }

.hero-groups {
  display: flex; gap: 2rem; flex-wrap: wrap; margin-top: 1.5rem;
  padding-top: 1.25rem; border-top: 1px solid var(--border-color);
}
.hero-groups > div { min-width: 0; }
.group-label {
  display: block; margin-bottom: 0.5rem;
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-secondary);
}
.hero-groups .mini-chip { display: inline-flex; align-items: center; gap: 0.4rem; }
.species-hero #species-plan { margin-top: 1.5rem; }

/* Paldex: partner skill, base work, tier grades, capture area ------ */

/* Element type, coloured by the game's own element palette. */
.element-row { display: flex; gap: 0.35rem; flex-wrap: wrap; margin-top: 0.4rem; }
.element-badge {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.03em;
  padding: 0.16rem 0.55rem; border-radius: 999px;
  border: 1px solid currentColor; color: #cbd5e1;
  background: rgba(255, 255, 255, 0.04);
}
.elem-fire { color: #fb923c; }
.elem-water { color: #38bdf8; }
.elem-leaf { color: #4ade80; }
.elem-electricity { color: #facc15; }
.elem-earth { color: #d6a26a; }
.elem-ice { color: #7dd3fc; }
.elem-dark { color: #c084fc; }
.elem-dragon { color: #818cf8; }
.elem-normal { color: #cbd5e1; }

/* The grades written onto the pal itself, next to the icon. */
.hero-tiers { margin-top: 1.1rem; }
.hero-tier-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.hero-tier {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.3rem 0.5rem 0.3rem 0.7rem; border-radius: 10px;
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--border-color);
}
.hero-tier-label {
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--text-secondary);
}
.tier-grade {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.6rem; height: 1.6rem; padding: 0 0.3rem;
  border-radius: 8px; font-weight: 800; font-size: 0.95rem; line-height: 1;
  color: #0b1017;
}
/* The grade shown on a species entry in a sorted list — inventory cards and the
   reachable chips. Reads as one unit with the icon+name, not a separate badge. */
.grade-chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-secondary);
}
.grade-chip-label { white-space: nowrap; }
.grade-chip .tier-grade {
  min-width: 1.3rem; height: 1.3rem; font-size: 0.8rem; border-radius: 6px;
}
.grade-chip.is-none {
  font-size: 0.7rem; text-transform: none; letter-spacing: 0;
  opacity: 0.65;
}
/* Holds the work-level chip and/or the grade chip, either of which may be absent
   depending on the active filter and sort. */
.row-grade {
  margin-top: 0.5rem;
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
}
.row-grade:empty { display: none; }
/* On a reachable chip the grade sits after the name, inside the pill. */
.mini-chip.with-icon .grade-chip { margin-left: 0.15rem; }

.grade-S { background: linear-gradient(135deg, #fbbf24, #f97316); }
.grade-A { background: linear-gradient(135deg, #4ade80, #16a34a); }
.grade-B { background: linear-gradient(135deg, #38bdf8, #0284c7); }
.grade-C { background: rgba(255, 255, 255, 0.16); color: var(--text-primary); }
.grade-D { background: rgba(255, 255, 255, 0.08); color: var(--text-secondary); }

/* Folded-away explanation of how the grades are derived. */
.tier-details { margin-top: 0.85rem; }
.tier-details > summary {
  cursor: pointer; width: fit-content;
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-secondary);
}
.tier-details > summary:hover { color: var(--text-primary); }
.tier-details .hint { margin-top: 0.5rem; max-width: 62ch; font-size: 0.78rem; }

/* Three columns: the partner skill and the map each need twice the width of a
   chip list, and pairing them with one narrow panel fills both rows exactly. */
.paldex-card {
  margin-top: 1.25rem;
  display: grid; gap: 1.75rem 2rem;
  grid-template-columns: 2fr 2fr 1.5fr;
}
.paldex-panel { min-width: 0; }
.paldex-panel .hint { margin-top: 0.6rem; font-size: 0.78rem; }
.partner-panel { grid-column: span 2; }
.map-panel { grid-column: span 2; }
@media (max-width: 1000px) {
  .paldex-card { grid-template-columns: 1fr 1fr; }
  .partner-panel, .map-panel { grid-column: span 2; }
}
@media (max-width: 720px) {
  .paldex-card { grid-template-columns: 1fr; }
  .partner-panel, .map-panel { grid-column: auto; }
}

.partner-name {
  font-size: 1.05rem; font-weight: 700; color: var(--accent-blue);
  margin-bottom: 0.35rem;
}
.partner-desc { font-size: 0.9rem; line-height: 1.55; color: var(--text-primary); }

/* Work suitability: name plus the level the game gates tasks on. */
.work-wrap { gap: 0.4rem; }
.work-chip {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.28rem 0.4rem 0.28rem 0.7rem; border-radius: 999px;
  font-size: 0.82rem;
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--border-color);
}
.work-chip.is-best {
  border-color: var(--accent-green);
  background: rgba(16, 185, 129, 0.12);
}
.work-level {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.25rem; height: 1.25rem; border-radius: 6px;
  background: rgba(255, 255, 255, 0.12);
  font-weight: 700; font-size: 0.78rem; font-variant-numeric: tabular-nums;
}
.work-chip.is-best .work-level { background: var(--accent-green); color: #06281d; }

/* Two columns of label/value. Uppercase tracking made the longer labels
   ("Sprint (geritten)") collide with the neighbouring cell, so these read as
   sentence case and each cell owns a whole row of its column. */
.stat-cells {
  display: grid; gap: 0.45rem 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.stat-cell {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.6rem; min-width: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05); padding-bottom: 0.3rem;
}
.stat-cell b { font-size: 1rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.stat-cell span {
  font-size: 0.78rem; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Capture-area map: the world texture with an SVG dot overlay on top. The
   overlay's viewBox is the same lattice the points are quantised onto, so it
   scales with the image without any coordinate maths in the client. */
.mini-chip.is-nocturnal { border-color: rgba(167, 139, 250, 0.45); color: #c4b5fd; }
.mini-chip.is-nospawn { opacity: 0.55; }

/* Missing-pals list ----------------------------------------------- */

/* The route is the point of this list — it says whether the pal is a breeding
   job or a hunting trip — so it is colour-coded and sits directly under the name.
   The left border repeats it, so the four groups are separable while scrolling. */
.missing-card { border-left-width: 3px; }
.missing-card.route-breedable { border-left-color: var(--accent-green); }
.missing-card.route-deeper { border-left-color: var(--accent-blue); }
.missing-card.route-catch_only { border-left-color: var(--accent-warning); }
.missing-card.route-unreachable { border-left-color: rgba(255, 255, 255, 0.14); }
.missing-card .dex {
  font-size: 0.85rem; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.route-badge {
  font-size: 0.75rem; font-weight: 600;
  padding: 0.2rem 0.6rem; border-radius: 999px;
  border: 1px solid currentColor;
}
.route-badge.is-breedable { color: #6ee7b7; }
.route-badge.is-deeper { color: #7dd3fc; }
.route-badge.is-catch { color: #fcd34d; }
.route-badge.is-unreachable { color: var(--text-secondary); opacity: 0.8; }

/* Items -------------------------------------------------------------- */
/* Item icons, unlike pal icons, are square artwork on a transparent ground and
   are not clickable — there is no larger version to open, and no overlay. Hence
   a rounded square rather than a disc, and no hover zoom. */
.item-icon {
  width: 24px; height: 24px; flex: 0 0 auto;
  object-fit: contain; border-radius: 6px;
  background: rgba(255, 255, 255, 0.06);
  vertical-align: middle;
}
.item-icon.sm { width: 20px; height: 20px; }
.item-icon.md { width: 28px; height: 28px; }
.item-icon.lg { width: 36px; height: 36px; }
/* `display: none`, not `visibility: hidden` as pal icons use: 13 items have no
   texture in the game data at all, and reserving a blank square for each would
   read as a failed download rather than as "this one has no picture". */
.item-icon.is-missing { display: none; }
.mini-chip .item-icon { margin-right: 0.3rem; }

.item-row {
  padding: 0.5rem 0; border-bottom: 1px solid var(--border-color);
}
.item-row:last-child { border-bottom: none; }
.item-head { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.item-total {
  margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums;
}
.item-split { font-size: 0.8rem; color: var(--text-secondary); margin: 0.15rem 0 0.3rem; }

.plan-tree { display: flex; flex-direction: column; gap: 0.2rem; }
/* Depth is a CSS variable so the tree indents without a wrapper per level. */
.plan-node {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  margin-left: calc(var(--depth) * 1.3rem);
  padding: 0.3rem 0.55rem; border-radius: 8px;
  border-left: 3px solid var(--border-color);
  background: rgba(255, 255, 255, 0.03);
}
.plan-node.is-craft { border-left-color: #7dd3fc; }
.plan-node.is-raw { border-left-color: #fcd34d; }
.plan-node.is-have { border-left-color: #6ee7b7; }
/* The chain stops here, so it reads as a wall rather than another step. */
.plan-node.is-locked { border-left-color: #f87171; background: rgba(248, 113, 113, 0.08); }
.plan-toolbar {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
  margin-bottom: 0.6rem;
}
.plan-toolbar .mini-chip { margin-left: auto; }
.seg { display: inline-flex; border: 1px solid var(--border-color); border-radius: 8px; overflow: hidden; }
.seg-btn {
  background: none; border: none; color: var(--text-secondary);
  font: inherit; font-size: 0.85rem; padding: 0.3rem 0.85rem; cursor: pointer;
}
.seg-btn + .seg-btn { border-left: 1px solid var(--border-color); }
.seg-btn.is-active { background: rgba(125, 211, 252, 0.16); color: var(--text-primary); }

/* Top-down chart. A family-tree layout: the target on top, what it is made of
   on the row below, connected by lines.

   The connectors are pure CSS. Each <li> draws half a horizontal bar on either
   side of itself (::before to the left, ::after to the right) plus the vertical
   drop; the first and last child suppress their outer half so the bar spans only
   between siblings. Each child <ul> draws its own stem up to the parent. This is
   why the chart needs no layout maths and reflows with the text. */
/* `margin: auto` on the chart, not `justify-content: center` on the scroller:
   a centred flex container clips its overflow on the *left* and scrollLeft
   cannot reach it, so wide charts lose their first branches for good. With auto
   margins the chart still centres while it fits and stays fully scrollable once
   it does not. */
.chart-scroll { overflow-x: auto; padding-bottom: 0.5rem; display: flex; }
.plan-chart { margin: 0 auto; }
.plan-chart, .plan-chart ul {
  list-style: none; padding: 0;
  display: flex; justify-content: center;
}
.plan-chart ul { margin: 0; }
.plan-chart ul { padding-top: 1.1rem; position: relative; }
/* Stem from the parent box down to the sibling bar. */
.plan-chart ul::before {
  content: ''; position: absolute; top: 0; left: 50%; height: 1.1rem;
  border-left: 1px solid var(--border-color);
}
.plan-chart li {
  position: relative; padding: 1.1rem 0.4rem 0; text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
.plan-chart > li { padding-top: 0; }
.plan-chart li::before, .plan-chart li::after {
  content: ''; position: absolute; top: 0; width: 50%; height: 1.1rem;
  border-top: 1px solid var(--border-color);
}
.plan-chart li::before { right: 50%; }
.plan-chart li::after { left: 50%; border-left: 1px solid var(--border-color); }
/* An only child needs just the stem, not a bar. */
.plan-chart li:only-child::before, .plan-chart li:only-child::after { border-top: none; }
.plan-chart li:only-child::before { border: none; }
/* The bar must stop at the outermost siblings instead of overhanging. */
.plan-chart li:first-child::before { border: none; }
.plan-chart li:last-child::after { border-top: none; }
.plan-chart > li::before, .plan-chart > li::after { display: none; }
/* Folded: the whole subtree goes, including the stem it would draw. */
.plan-chart li.is-folded > ul { display: none; }

.chart-node {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: 0.1rem;
  min-width: 8.5rem; max-width: 13rem;
  position: relative;
  padding: 0.4rem 0.6rem; border-radius: 8px;
  border: 1px solid var(--border-color); border-top: 3px solid var(--border-color);
  background: var(--card-bg, rgba(255, 255, 255, 0.04));
  font: inherit; color: inherit; text-align: left;
}
button.chart-node { cursor: pointer; }
button.chart-node:hover { border-color: var(--accent, #7dd3fc); }
.chart-node.is-craft { border-top-color: #7dd3fc; }
.chart-node.is-raw { border-top-color: #fcd34d; }
.chart-node.is-have { border-top-color: #6ee7b7; }
.chart-node.is-locked { border-top-color: #f87171; background: rgba(248, 113, 113, 0.1); }
.chart-node .plan-qty { min-width: 0; }
.chart-node .plan-name { white-space: normal; }
.chart-node .plan-note { margin-left: 0; font-size: 0.72rem; }
/* The box is a text column, so the icon is lifted out of the flow into the top
   right corner instead of taking a line of its own between count and name. The
   reserved padding is unconditional, so a node without an icon lines up with the
   ones beside it. */
.chart-node { padding-right: 2.6rem; }
.chart-node .item-icon { position: absolute; top: 0.4rem; right: 0.5rem; }
/* Only meaningful while the branch is folded; it names what is hidden. */
.chart-more { display: none; font-size: 0.72rem; color: var(--text-secondary); }
.is-folded > .chart-node .chart-more { display: inline; }
.chart-node.has-children .plan-qty::after {
  content: '▾'; margin-left: 0.35rem; color: var(--text-secondary);
}
.is-folded > .chart-node.has-children .plan-qty::after { content: '▸'; }

.plan-qty { font-variant-numeric: tabular-nums; font-weight: 700; min-width: 4ch; }
.plan-name { font-weight: 600; }
.plan-note { margin-left: auto; font-size: 0.78rem; color: var(--text-secondary); }

/* Breeding calculator ----------------------------------------------- */
.panel-title { margin: 0 0 0.7rem; font-size: 1rem; }
.calc-parents {
  display: flex; align-items: center; justify-content: center;
  gap: 1rem; flex-wrap: wrap;
}
.calc-parent { display: flex; flex-direction: column; align-items: center; gap: 0.35rem; }
.calc-times, .calc-arrow {
  font-size: 1.4rem; color: var(--text-secondary); text-align: center;
}
.calc-arrow { margin: 0.5rem 0; }
.calc-outcomes {
  display: flex; justify-content: center; gap: 1.5rem; flex-wrap: wrap;
}
.calc-outcome { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; }
/* Names which parent the gender applies to, for the one gendered pairing. */
.calc-branch { font-size: 0.82rem; color: var(--text-secondary); }
.pal-chip.is-link {
  background: none; border: 1px solid var(--border-color); cursor: pointer;
  font: inherit; color: inherit;
}
.pal-chip.is-link:hover { border-color: var(--accent, #7dd3fc); }
.mini-chip.is-muted { color: var(--text-secondary); opacity: 0.8; }

.pair-list { display: flex; flex-direction: column; gap: 0.3rem; margin-top: 0.6rem; }
.pair-row {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  padding: 0.3rem 0.5rem; border-radius: 8px;
  border: 1px solid transparent;
}
/* A pair you could breed right now is the actionable case, so it is marked. */
.pair-row.is-owned { border-color: rgba(110, 231, 183, 0.35); }
.pair-side { display: inline-flex; align-items: center; gap: 0.35rem; }
.pair-times { color: var(--text-secondary); }
.own-dot {
  width: 7px; height: 7px; border-radius: 50%;
  border: 1px solid var(--text-secondary); flex: none;
}
.own-dot.is-owned { background: #6ee7b7; border-color: #6ee7b7; }

/* Expeditions ------------------------------------------------------- */
.exp-card { margin-bottom: 0.9rem; }
/* A left edge carries the state, so running/back/idle is readable at a glance
   without hunting for the badge. */
.exp-card.is-running { border-left: 3px solid #7dd3fc; }
.exp-card.is-back { border-left: 3px solid #6ee7b7; }
.exp-card.is-idle { border-left: 3px solid var(--border-color); opacity: 0.75; }
.exp-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.6rem; flex-wrap: wrap;
}
.exp-head h3 { margin: 0; font-size: 1rem; }
.exp-state {
  font-size: 0.8rem; font-weight: 600;
  padding: 0.2rem 0.6rem; border-radius: 999px;
  border: 1px solid currentColor;
  font-variant-numeric: tabular-nums;
}
.exp-state.is-running { color: #7dd3fc; }
.exp-state.is-back { color: #6ee7b7; }
.exp-state.is-idle { color: var(--text-secondary); }
.exp-mission {
  display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap;
  margin: 0.55rem 0 0.35rem;
}
.exp-mission b { font-size: 0.95rem; }
.exp-times {
  display: flex; gap: 1rem; flex-wrap: wrap;
  font-size: 0.82rem; color: var(--text-secondary);
}
.exp-team { margin-top: 0.55rem; font-size: 0.85rem; font-weight: 600; }
.exp-members {
  display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.45rem;
}
.exp-member {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.78rem; padding: 0.2rem 0.5rem; border-radius: 999px;
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--border-color);
}
.exp-member b { font-variant-numeric: tabular-nums; }
.exp-member i { font-style: normal; color: var(--text-secondary); font-size: 0.72rem; }

.map-head {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  margin-bottom: 0.6rem;
}
.map-toggle { display: inline-flex; gap: 0.3rem; }
.map-toggle button { padding: 0.3rem 0.7rem; font-size: 0.8rem; }
.map-toggle button.is-on {
  background: rgba(14, 165, 233, 0.18); border-color: var(--accent-blue); color: #fff;
}
.spawn-map {
  position: relative; width: 100%; max-width: 560px;
  aspect-ratio: 1 / 1; border-radius: 12px; overflow: hidden;
  border: 1px solid var(--border-color); background: #0a1420;
}
.spawn-map img { width: 100%; height: 100%; display: block; object-fit: cover; }
.spawn-dots {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none;
}
.spawn-dots circle {
  fill: #f43f5e;
  /* The dots sit on a busy, mostly dark texture, so they carry their own halo
     rather than relying on contrast with whatever biome is underneath. */
  stroke: rgba(255, 255, 255, 0.85);
  stroke-width: 0.5;
  paint-order: stroke;
}
/* Wide-ranging pals: no halo and partly transparent, so a few hundred
   overlapping cells read as a shaded region rather than a solid slab. */
.spawn-dots.is-dense circle { stroke: none; fill: rgba(244, 63, 94, 0.5); }

.carried { margin-top: 1.1rem; }
.carried .chip-wrap { margin-top: 0.15rem; }
.row-action {
  padding: 0.3rem 0.6rem; font-size: 0.95rem; line-height: 1;
  justify-self: end; align-self: center;
}

.owner-cell {
  font-size: 0.85rem; font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
/* Guild- and world-owned pals are not any member's, so they read as secondary. */
.owner-cell.is-sentinel { font-weight: 500; color: var(--text-secondary); font-style: italic; }

.detail-head {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  margin-bottom: 1.25rem;
}
.detail-head h3 { font-size: 1.15rem; font-weight: 700; }
.detail-head .spacer { flex: 1 1 auto; }

/* Every row must share one set of column widths, otherwise the level, location
   and IV columns drift horizontally from row to row and the list is unreadable.
   Each .pal-row is its own grid by default; where subgrid is available the rows
   inherit the list's columns instead, which aligns them. Without subgrid the
   per-row definition still produces a sane (if unaligned) layout. */
.pal-row {
  display: grid;
  grid-template-columns: 44px minmax(120px, 1fr) 4.5rem minmax(6rem, auto) 6.5rem max-content minmax(0, 1fr) auto;
  align-items: center; gap: 0.9rem;
  padding: 0.6rem 0.9rem; border-radius: 10px;
  background: rgba(0, 0, 0, 0.25); border: 1px solid var(--border-color);
  margin-bottom: 0.5rem;
}

@supports (grid-template-columns: subgrid) {
  .pal-list {
    display: grid;
    grid-template-columns: 44px minmax(120px, 1fr) 4.5rem minmax(6rem, auto) 6.5rem max-content minmax(0, 1fr) auto;
  }
  .pal-row { grid-template-columns: subgrid; grid-column: 1 / -1; }
}
.pal-row:hover { border-color: rgba(255, 255, 255, 0.16); }
.pal-row .who { min-width: 0; }
/* The IV block is one atomic unit — letting it wrap puts the total on its own
   line and makes every row taller than it needs to be. */
.pal-row .iv-row { flex-wrap: nowrap; }
.pal-row .passives { min-width: 0; }
.pal-row .who b { display: block; font-size: 0.95rem; }
.pal-row .who small { color: var(--text-secondary); font-size: 0.75rem; }
.pal-row .lvl { font-size: 0.8rem; color: var(--text-secondary); white-space: nowrap; }
.pal-row .passives { display: flex; flex-wrap: wrap; gap: 0.3rem; justify-content: flex-end; }
.pal-row .passives .mini-chip { font-size: 0.72rem; padding: 0.2rem 0.5rem; }

@media (max-width: 900px) {
  /* Drop back to per-row grids on narrow screens: the IV block and passives get
     their own full-width lines, so shared columns would fight the wrapping. */
  .pal-list { display: block; }
  .pal-row {
    grid-template-columns: 40px 1fr auto; row-gap: 0.6rem; grid-column: auto;
  }
  .pal-row .iv-row, .pal-row .passives { grid-column: 1 / -1; justify-content: flex-start; }
}

/* Passive skills ---------------------------------------------------
   Rank is the game's own grading: negative passives are harmful, so they read
   red rather than as just another chip. */
.passive { position: relative; cursor: help; }
.passive.rank-bad     { border-color: rgba(239, 68, 68, 0.45); color: #fca5a5; }
.passive.rank-great   { border-color: rgba(245, 158, 11, 0.5); color: #fcd34d; }
.passive.rank-good    { border-color: rgba(14, 165, 233, 0.45); color: #7dd3fc; }
.passive.rank-neutral { color: var(--text-secondary); }

/* Hover card. Anchored to the chip's right edge so it grows leftwards and cannot
   run off the viewport — these chips sit in a right-aligned column.
   Opens *downwards* on purpose: opening upwards clipped the card off the top of
   the window for rows near the top of the page, which the user cannot scroll to
   recover, whereas anything below the fold is reachable.
   Descriptions are multi-line, hence pre-line rather than CSS content. */
.passive .tip {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 40;
  min-width: 190px; max-width: 300px; width: max-content;
  padding: 0.6rem 0.75rem; border-radius: 10px;
  background: #0b1017; border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.6);
  text-align: left; white-space: pre-line; line-height: 1.45;
  font-size: 0.8rem; font-weight: 400; color: var(--text-primary);
  opacity: 0; visibility: hidden; transform: translateY(4px);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
  pointer-events: none;
}
.passive:hover .tip, .passive:focus-visible .tip {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.passive .tip b {
  display: block; margin-bottom: 0.3rem; font-size: 0.85rem; font-weight: 700;
}
.passive .tip .tip-rank {
  display: block; margin-top: 0.4rem; padding-top: 0.4rem;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.72rem; color: var(--text-secondary);
}
/* Rows later in the list would otherwise stack above earlier tooltips. */
.pal-row:hover { z-index: 5; }
.pal-row { position: relative; }

.notice {
  padding: 1.1rem 1.35rem; border-radius: 14px; line-height: 1.55;
  border: 1px solid var(--border-color); background: rgba(0, 0, 0, 0.25);
}
.notice.warn { border-color: rgba(245, 158, 11, 0.4); background: rgba(245, 158, 11, 0.08); }
.notice.info { border-color: rgba(14, 165, 233, 0.35); background: rgba(14, 165, 233, 0.08); }
.notice.error { border-color: rgba(239, 68, 68, 0.4); background: rgba(239, 68, 68, 0.08); }
.notice h3 { font-size: 1.05rem; margin-bottom: 0.4rem; }
.notice p { color: var(--text-secondary); font-size: 0.9rem; }

.chip-wrap { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.mini-chip {
  font-size: 0.8rem; padding: 0.3rem 0.65rem; border-radius: 999px;
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--border-color);
}
/* Species buttons in the reachable list carry an icon, so they need to align. */
/* The "what can I breed?" list is a browse-and-pick view, so its species chips
   carry a full-size icon rather than a thumbnail. */
.mini-chip.with-icon {
  display: inline-flex; align-items: center; gap: 0.55rem;
  padding: 0.35rem 0.9rem 0.35rem 0.35rem; border-radius: 999px;
  font-size: 0.88rem; font-weight: 600;
  color: var(--text-primary); cursor: pointer;
}
.mini-chip.with-icon:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.2); }
.mini-chip b { color: var(--accent-blue); font-variant-numeric: tabular-nums; }

/* Sign-in ---------------------------------------------------------- */

.whoami { display: flex; align-items: center; gap: 0.6rem; }
#whoami-name { font-size: 0.9rem; font-weight: 600; }

.login-card {
  max-width: 560px; margin: 3rem auto 0; text-align: center;
}
.login-card h2 { font-size: 1.5rem; font-weight: 800; margin-bottom: 0.6rem; }
.login-lead {
  color: var(--text-secondary); line-height: 1.6; margin-bottom: 1.5rem;
}
.login-card .notice { text-align: left; margin-bottom: 1.25rem; }
.login-card .hint { max-width: 46ch; margin: 1.25rem auto 0; }

/* Steam's own brand blue, so the button reads as the third-party sign-in it is. */
.steam-btn {
  display: inline-flex; align-items: center; gap: 0.7rem;
  padding: 0.8rem 1.5rem; border-radius: 12px;
  background: linear-gradient(135deg, #1b2838, #2a475e);
  border: 1px solid #66c0f4;
  color: #fff; font-weight: 700; font-size: 1rem; text-decoration: none;
  transition: var(--transition-smooth);
}
.steam-btn:hover { background: linear-gradient(135deg, #2a475e, #3d6c8d); }
/* Drawn in CSS rather than fetched: the UI must not depend on an outside host. */
.steam-mark {
  width: 20px; height: 20px; border-radius: 50%; flex: 0 0 auto;
  background: #66c0f4;
  box-shadow: inset -4px -4px 0 0 rgba(27, 40, 56, 0.65);
}

/* World map: bases and player positions --------------------------- */

.world-layout {
  display: flex; gap: 1.75rem; flex-wrap: wrap; align-items: flex-start;
}
.world-map { max-width: 620px; flex: 1 1 380px; }
.world-list { flex: 1 1 220px; min-width: 200px; display: flex; flex-direction: column; gap: 0.4rem; }
.world-row {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 0.6rem; padding: 0.45rem 0.7rem; border-radius: 8px;
  background: rgba(0, 0, 0, 0.22); border: 1px solid var(--border-color);
  font-size: 0.85rem;
}
.world-row span:last-child { color: var(--text-secondary); font-size: 0.78rem; }

/* Legend swatches, reused inline in the list so the two always agree. */
.wm-key {
  width: 10px; height: 10px; border-radius: 50%; display: inline-block;
  flex: 0 0 auto;
}
.wm-key-player { background: #38bdf8; box-shadow: 0 0 0 2px rgba(56, 189, 248, 0.25); }
.wm-key-base { background: var(--accent-warning); box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.25); }
.mini-chip .wm-key { margin-right: 0.4rem; vertical-align: -1px; }

/* Its own overlay class rather than reusing the spawn map's: `.spawn-dots circle`
   sets a fill, and being a descendant selector it outranks a plain marker class,
   which silently painted both players and bases spawn-red. */
.world-dots {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none;
}
.world-dots .wm-base { fill: var(--accent-warning); stroke: rgba(0, 0, 0, 0.6); stroke-width: 0.4; }
.world-dots .wm-player {
  fill: #38bdf8; stroke: #fff; stroke-width: 0.5; paint-order: stroke;
}
.wm-label {
  font-size: 4px; font-weight: 700; text-anchor: middle;
  fill: #fff; paint-order: stroke;
  stroke: rgba(0, 0, 0, 0.85); stroke-width: 1.1;
}
.wm-player-label { fill: #e0f2fe; }

/* Enlarged pal image ---------------------------------------------- */

body.overlay-open { overflow: hidden; }

#img-overlay {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 2rem;
  background: rgba(4, 7, 12, 0.82);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  animation: overlay-in 0.16s ease-out;
}
@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }

.img-overlay-inner {
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  gap: 0.5rem;
  padding: 3.75rem 2.5rem 1.75rem;
  border-radius: 20px;
  background: var(--panel-bg-solid);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.65);
  max-width: min(92vw, 560px);
}

/* The pal's own icon, top-left corner of the panel. */
.img-overlay-icon {
  position: absolute; top: 1rem; left: 1rem;
  width: 64px; height: 64px;
  object-fit: contain; border-radius: 50%;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.14);
}

.img-overlay-close {
  position: absolute; top: 0.85rem; right: 0.85rem;
  width: 2.2rem; height: 2.2rem; line-height: 1;
  font-size: 1.5rem; font-family: inherit;
  color: var(--text-secondary);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--border-color); border-radius: 10px;
}
.img-overlay-close:hover { color: var(--text-primary); background: rgba(255, 255, 255, 0.12); }

/* The pal, large and centred. Capped at 2.6x its 128px source: these are the
   game's own textures and there is no higher-resolution pal image to be had, so
   scaling further only magnifies the softness. */
.img-overlay-main {
  width: min(68vw, 46vh, 332px); height: auto;
  aspect-ratio: 1 / 1; object-fit: contain;
  image-rendering: auto;
  filter: drop-shadow(0 10px 26px rgba(0, 0, 0, 0.5));
}

.img-overlay-caption { text-align: center; }
.img-overlay-caption h3 { font-size: 1.25rem; font-weight: 800; }
.img-overlay-caption .hero-code { margin-top: 0.1rem; }

@media (max-width: 520px) {
  #img-overlay { padding: 1rem; }
  .img-overlay-inner { padding: 3.25rem 1.25rem 1.25rem; }
  .img-overlay-icon { width: 48px; height: 48px; }
}
@media (prefers-reduced-motion: reduce) {
  #img-overlay { animation: none; }
}

/* Every pal image is now a control, so it has to look like one. */
.pal-icon { cursor: zoom-in; }

.spinner {
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.2); border-top-color: var(--accent-blue);
  animation: spin 0.7s linear infinite; display: inline-block; vertical-align: -3px;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (max-width: 640px) {
  .shell { padding: 1rem 0.85rem 3rem; }
  .planner-controls { flex-direction: column; align-items: stretch; }
  .field.grow { flex: 1 1 auto; }
  input, select { min-width: 0; width: 100%; }
}
