/* Mobile first; the badge list turns into a grid as the width allows. No external fonts:
   the four game-style fonts are self-hosted (fonts/, licences beside them). */

/* Game-style text (CONTRACT section 11a): free look-alikes of the game's badge font, used
   only for a badge's name, level and number. <html data-font="..."> picks one (section 11b
   tests which reads best); missing or unknown -> Lilita One. Unused faces never download. */
@font-face { font-family: "Lilita One"; src: url("fonts/lilita-one.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Titan One"; src: url("fonts/titan-one.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Bowlby One"; src: url("fonts/bowlby-one.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Luckiest Guy"; src: url("fonts/luckiest-guy.woff2") format("woff2"); font-display: swap; }
:root {
  --game-fallback: "Arial Black", "Segoe UI Black", Impact, system-ui, sans-serif;
  --game-font: "Lilita One", var(--game-fallback);
}
/* The other three run wider than Lilita One (average real badge name: Titan 1.25x, Bowlby
   1.42x, Luckiest 1.15x), so each is set a little smaller - about the square root of that -
   to keep names to two lines without shrinking any font to unreadable. */
html[data-font="titan"] { --game-font: "Titan One", var(--game-fallback); --game-scale: 0.9; }
html[data-font="bowlby"] { --game-font: "Bowlby One", var(--game-fallback); --game-scale: 0.84; }
html[data-font="luckiest"] { --game-font: "Luckiest Guy", var(--game-fallback); --game-scale: 0.93; }

:root {
  /* One dark theme. Text sits directly on the moving background (the owner's choice), so
     every letter carries a two-layer glow: a tight dark halo right behind it keeps it
     legible over the particles, and a soft blue outer glow ties it to the wave. Headings
     glow more; small text gets a lighter outer glow so it stays crisp. */
  --bg: #000000;
  --text: #e8e8ee;
  --muted: #b9bfcc;
  --input-border: #6fa8d8;
  --note: #f2b766;
  --error-text: #ffc9c9;
  --error-line: rgba(255, 140, 140, 0.75);
  --focus: #f59e0b;
  /* Too little data (section 12): the gold of the "!" coin (~13:1 on black). */
  --warn: #ffc94d;
  /* Game-style controls (owner, 2026-10-27: "like Clash Royale"): a dark ink outline, navy
     panels and bubbles with a lighter rim, chunky buttons with a lit top and a dark lip. */
  --ink: #0d1830;
  --bubble: #1f3460;
  --bubble-rim: #3b5a96;
  --gold: linear-gradient(#ffe066 0%, #ffc21a 55%, #f0a10a 100%);
  --btn-blue: linear-gradient(#6cc4ff 0%, #3a8ff0 55%, #2668cc 100%);
  --btn-slate: linear-gradient(#56657f 0%, #3b4860 60%, #2f3a4f 100%);
  --btn-lip: inset 0 -4px 0 rgba(0, 0, 0, 0.25), inset 0 3px 0 rgba(255, 255, 255, 0.3), 0 3px 0 var(--ink);
  --halo: 0 0 2px #000, 0 0 6px rgba(0, 0, 0, 0.9), 0 0 12px rgba(0, 0, 0, 0.7);
  --glow-head: var(--halo), 0 0 12px rgba(63, 169, 216, 0.55), 0 0 28px rgba(0, 119, 182, 0.35);
  --glow-body: var(--halo), 0 0 10px rgba(63, 169, 216, 0.28);
  --glow-box: 0 0 10px rgba(63, 169, 216, 0.45);
  /* Clash rarity colours for the number under a badge (tierFor in lib/view.js). Contrast on
     black: common 9.8:1, rare 9.9:1, epic 6.9:1, legendary 9.0-15.2:1, champion 15.2:1. */
  --tier-common: #9fb3c8;
  --tier-rare: #ff9a2e;
  --tier-epic: #c46bff;
  --tier-legendary: linear-gradient(90deg, #3fe0c8, #ff7ad9, #ffd84d);
  --tier-champion: #ffd84d;
  /* Game-style text (section 11a): fills on a dark outline; each fill reaches AA on the
     outline colour too (test/webView.test.js). */
  --outline: #14102a;
  --game-name: #ffffff;
  --game-level: #dce6f2;
  --game-glow: rgba(63, 169, 216, 0.55);
  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 17px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  overflow-wrap: anywhere;
  text-shadow: var(--glow-body);
  text-align: center; /* everything centered; long paragraphs keep a readable line length */
}
h1, h2, .highlight-count { text-shadow: var(--glow-head); }

p, h1, h2, h3, ol { margin: 0; }

/* Wide screens get wider content, not a narrow column: only the gutters grow. */
.wrap {
  width: 100%;
  max-width: 1600px;
  margin: 0 auto;
  padding-inline: clamp(16px, 4vw, 48px);
}

:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* --- header + form --- */
/* No boxes anywhere: text sits on the background with its glow; spacing groups things. */
.top { padding-block: clamp(24px, 5vw, 48px) 0; }
.top h1 { font-size: clamp(1.5rem, 1.1rem + 2vw, 2.4rem); line-height: 1.2; }
/* Who we compare with - always visible (owner, 2026-10-27). */
.top .sub { margin-top: 6px; color: var(--muted); font-size: 0.95rem; }
/* The two pages: small, quiet links above the title; the current one is plain bright text. */
.nav { display: flex; justify-content: center; align-items: baseline; gap: 10px; margin-bottom: 14px; font-size: 0.95rem; }
.nav a { color: var(--muted); text-decoration: none; padding: 6px 4px; border-bottom: 2px solid transparent; }
.nav a:hover { color: var(--text); border-bottom-color: rgba(111, 168, 216, 0.6); }
.nav a[aria-current="page"] { color: var(--text); font-weight: 600; border-bottom-color: var(--input-border); }
.nav-dot { color: var(--muted); }
.panel.intro { margin-top: 12px; max-width: 100%; }

.lookup { margin: 20px auto 0; max-width: 40rem; }
.lookup label { display: block; font-weight: 600; margin-bottom: 6px; }
.row { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.lookup input::placeholder { color: #9aa1b1; }
/* The controls keep visible edges (3:1 or more): a glowing border on a see-through field,
   and a solid button. */
.lookup input {
  flex: 1 1 12rem;
  min-width: 0;
  font: inherit;
  font-size: 1.1rem;
  padding: 10px 12px;
  border: 2px solid var(--input-border);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.45);
  color: var(--text);
  box-shadow: var(--glow-box);
}
.lookup button {
  flex: 0 0 auto;
  font: inherit;
  font-weight: 600;
  padding: 10px 18px;
  border: 0;
  border-radius: 8px;
  background: #7aa5ff;
  color: #0b1020;
  text-shadow: none;
  box-shadow: var(--glow-box);
  cursor: pointer;
}
.lookup button:disabled { opacity: 0.6; cursor: progress; }

/* --- status + results --- */
main { padding-block: 24px; }
.status:empty { display: none; }
.status { margin: 0 auto 16px; color: var(--muted); max-width: 48rem; }
/* Errors: glowing text in a thin glowing outline - no filled box. */
.status.error {
  color: var(--error-text);
  padding: 10px 14px;
  border: 1px solid var(--error-line);
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(255, 110, 110, 0.35), inset 0 0 10px rgba(255, 110, 110, 0.15);
  text-shadow: var(--halo), 0 0 10px rgba(255, 110, 110, 0.4);
}

.player { margin-bottom: 20px; }
.player-name { font-size: 1.6rem; line-height: 1.25; }
.player-tag { color: var(--muted); font-variant-numeric: tabular-nums; }
/* The one headline after a lookup: a little bigger than body text, readable line length. */
.player-rarest { margin: 8px auto 0; max-width: 40rem; font-size: 1.1rem; font-weight: 600; text-wrap: balance; }

.highlights {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: 16px 24px;
  margin-bottom: 32px;
}
.highlight-count { font-size: 1.5rem; font-weight: 700; }
.highlight-line { color: var(--muted); }

/* The badge list: as many columns as the width allows, rows centered (so a part-filled last
   row sits in the middle), each badge centered - picture above its label and numbers. */
.badges {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 24px;
}
/* The owner's badge design: name, a big picture, the level, one glowing number - no tile
   (section 11a order; the full name is in the tooltip). */
.badge {
  flex: 0 0 auto;
  /* Wider than the picture so a game-style name fits in two lines (two columns at 320px). */
  width: clamp(128px, 40vw, 160px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px 2px;
  --pic: clamp(96px, 22vw, 136px);
}
/* Exactly the owner's image - no frame, no added glow (the glow is in the picture itself). */
.pic {
  width: var(--pic);
  height: var(--pic);
  object-fit: contain;
}
/* No picture yet: just a quiet line in the picture's place. */
.pic-empty {
  display: grid;
  place-items: center;
  padding: 12px;
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.3;
  text-align: center;
}
/* Game-style text (section 11a), like the game's "Achievement Badge / ??? / Level 1": a
   white fill on a thick dark outline with a soft drop shadow. The text is drawn twice: the
   ::before copy (from data-t, hidden from screen readers) carries the outline, the shadow
   and the site's glow - on pure black a dark outline alone disappears, so a soft glow
   behind it makes it pop the way the game's blue backdrop does - and the inner .fill paints
   the colour on top. Only the badge name, level and number use it. */
.g {
  position: relative;
  display: block;
  isolation: isolate;
  padding: 0.1em 0.14em;
  font-family: var(--game-font);
  font-size: calc(var(--game-scale, 1) * 1em);
  font-weight: 700;
  font-synthesis: none; /* the game fonts have one weight: never a smeared fake bold */
  letter-spacing: 0.02em;
  line-height: 1.15;
  color: var(--game-fill, var(--game-name));
  text-shadow: none;
  overflow-wrap: normal;
  word-break: normal;
}
.g::before {
  content: attr(data-t);
  content: attr(data-t) / "";
  position: absolute;
  inset: 0;
  z-index: -1;
  padding: inherit;
  color: var(--outline);
  -webkit-text-stroke: 0.22em var(--outline);
  filter: drop-shadow(0 0.09em 0 rgba(0, 0, 0, 0.85)) drop-shadow(0 0.12em 0.18em rgba(0, 0, 0, 0.6))
    drop-shadow(0 0 0.45em var(--game-glow));
}
/* Name above the picture: at most two centred lines; a longer one ends in "…" (the full
   name is in the tooltip). Long names (nameSize in lib/view.js) start a size smaller. */
/* It always takes two lines' height, bottom-aligned, so the pictures in a row line up. */
.badge-name {
  font-size: 0.97rem;
  max-width: 100%;
  min-height: 2.5rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.badge-name.long { font-size: 0.82rem; }
.badge-name.longer { font-size: 0.7rem; }
.badge-name.long .g { letter-spacing: 0.01em; }
.badge-name.longer .g { letter-spacing: 0; }
.badge-name .fill, .badge-name .g::before {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
/* Room inside the clip for tall glyphs (Bowlby One's run past its line box); the outline
   copy gets the same offset so the two layers stay on top of each other. */
.badge-name .fill { padding-block: 0.1em; }
.badge-name .g::before { padding-block: 0.2em; }
.badge-level { font-size: 0.8125rem; --game-fill: var(--game-level); margin-top: -2px; }
.badge-share {
  font-size: 1.1875rem;
  font-variant-numeric: tabular-nums;
  --game-fill: var(--tier-color, var(--game-name));
}
/* Colour is the tier (on the fill); the glow behind the outline takes its hue. */
.tier-common { --tier-color: var(--tier-common); }
.tier-rare { --tier-color: var(--tier-rare); }
.tier-epic { --tier-color: var(--tier-epic); }
.tier-champion { --tier-color: var(--tier-champion); }
.tier-rare, .tier-epic, .tier-champion { --game-glow: color-mix(in srgb, var(--tier-color) 55%, transparent); }
.tier-legendary { --game-glow: rgba(255, 122, 217, 0.5); }
/* Gradient text on the fill only; the outline copy behind it stays dark. */
.tier-legendary .fill {
  background: var(--tier-legendary);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Any level (CONTRACT 13a): one small line under a leveled badge's number, in the plain
   font and dimmer than the number - no tier colour, no ⚠. */
.badge-any { margin: 0; line-height: 1.3; font-size: 0.75rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Too little data (section 12): right after the number (the share line
   becomes a row): a round gold "!" coin and, on hover / focus / tap, one short note under
   it in a game-style navy bubble with a little arrow. page.js shifts the bubble sideways
   (--shift) so it stays on screen; the arrow shifts back so it still points at the coin. */
.badge-share { position: relative; display: flex; align-items: center; justify-content: center; gap: 5px; }
.warn-tip {
  width: 24px;
  height: 24px;
  padding: 0;
  border: 2px solid var(--ink);
  border-radius: 50%;
  background: linear-gradient(#ffe066, #f0a10a);
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.45), 0 2px 0 var(--ink);
  color: var(--ink);
  font: 900 0.85rem/1 system-ui, sans-serif;
  text-shadow: none;
  cursor: help;
}
.warn-tip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.warn-note {
  position: absolute;
  top: calc(100% + 12px);
  left: 50%;
  z-index: 3;
  width: max-content;
  max-width: min(15rem, calc(100vw - 16px));
  padding: 8px 12px;
  border: 3px solid var(--ink);
  border-radius: 12px;
  background: var(--bubble);
  box-shadow: inset 0 0 0 2px var(--bubble-rim), 0 4px 0 rgba(0, 0, 0, 0.6);
  color: var(--text);
  font: 600 0.85rem/1.3 system-ui, sans-serif;
  letter-spacing: normal;
  text-align: center;
  text-shadow: none;
  transform: translateX(calc(-50% + var(--shift, 0px)));
  transform-origin: 50% 0;
  pointer-events: none;
  opacity: 0;
  /* Out of the layout while closed: an invisible note still widened a 320px page. */
  display: none;
}
.warn-note::before {
  content: "";
  position: absolute;
  top: -9px;
  left: calc(50% - var(--shift, 0px));
  width: 14px;
  height: 14px;
  border-left: 3px solid var(--ink);
  border-top: 3px solid var(--ink);
  background: var(--bubble);
  transform: translateX(-50%) rotate(45deg);
}
.tip-on .warn-note { display: block; opacity: 1; }
/* A small game-style pop: in from a little smaller, a slight overshoot, settle. */
@media (prefers-reduced-motion: no-preference) {
  .warn-note { transition: opacity 140ms ease-out, scale 220ms cubic-bezier(0.34, 1.56, 0.64, 1), display 220ms allow-discrete; }
  @starting-style { .tip-on .warn-note { opacity: 0; scale: 0.85; } }
}
/* The open badge sits above its neighbours; on All badges its note isn't clipped. */
.badge.tip-on { position: relative; z-index: 4; }
.catalog .badge.tip-on { content-visibility: visible; }

/* --- All badges page --- */
.count:empty { display: none; }
.count { margin: 0 auto 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
/* One item per badge level (CONTRACT section 10); two columns on a 320px phone. */
.catalog { gap: 8px 12px; }
.catalog .badge {
  width: clamp(136px, 40vw, 160px);
  /* ~1,100 items: the browser skips laying out and painting the ones off screen, with a
     placeholder height of about one item (name, picture, level, number) until it has the real one. */
  content-visibility: auto;
  contain-intrinsic-size: auto clamp(136px, 40vw, 160px) auto calc(var(--pic) + 100px);
}
#search { max-width: 34rem; }
#search input { flex-basis: 10rem; }
.badges .badge[hidden] { display: none; }
/* My badges (CONTRACT 15): the same search + Filter block after emotes/banners, then the
   count line and the player's list. */
.results .badge-tools { margin-bottom: 20px; }
.results .badge-tools .lookup { margin-top: 0; }

/* --- the filter window (CONTRACT 13d), game-style (owner, 2026-10-27, from a mock-up: "omg
   I love it"): a gold Filter button with a red number bubble; a navy window with a blue
   title strip and a close button; chunky options - the chosen one blue, the rest slate;
   colours filled with their tier, an off colour dark. Labels in the game font with a dark
   outline. Every control is at least 24 x 24 px (most 40). --- */
.filter-label, .filters-title, .filter-h, .opt, .filter-close {
  font-family: var(--game-font);
  font-weight: 400;
  color: #fff;
  -webkit-text-stroke: 3px var(--ink);
  paint-order: stroke fill;
  text-shadow: 0 2px 0 var(--ink);
  letter-spacing: 0.02em;
}
.lookup .filter-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 6px 16px;
  font: inherit;
  font-size: 1.05rem;
  background: var(--gold);
  border: 3px solid var(--ink);
  border-radius: 12px;
  box-shadow: var(--btn-lip);
  cursor: pointer;
}
.lookup .filter-toggle[aria-expanded="true"] { filter: brightness(1.1); }
/* Pressed: the button sinks onto its lip, like the game's buttons. */
.lookup .filter-toggle:active, .opt:active, .filter-close:active {
  translate: 0 2px;
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.25), inset 0 2px 0 rgba(255, 255, 255, 0.3), 0 1px 0 var(--ink);
}
.filter-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 4px;
  border: 2px solid var(--ink);
  border-radius: 50%;
  background: linear-gradient(#ff6a5c, #d92617);
  color: #fff;
  font: 700 0.8rem/1 system-ui, sans-serif;
  font-variant-numeric: tabular-nums;
}
.filter-n[hidden] { display: none; }
.filters {
  margin: 16px auto 0;
  max-width: 44rem;
  text-align: left;
  border: 3px solid var(--ink);
  border-radius: 18px;
  background: linear-gradient(#1f3460, #152547);
  box-shadow: inset 0 0 0 2px var(--bubble-rim), 0 6px 0 rgba(0, 0, 0, 0.6);
  transform-origin: 50% 0;
}
.filters[hidden] { display: none; }
.filters-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 10px 8px 14px;
  border-bottom: 3px solid var(--ink);
  border-radius: 15px 15px 0 0;
  background: linear-gradient(#4aa3ff, #2d6fd6);
}
.filters-title { margin: 0; font-size: 1.3rem; line-height: 1.2; }
.filter-close {
  width: 36px;
  height: 36px;
  padding: 0;
  border: 3px solid var(--ink);
  border-radius: 10px;
  background: var(--btn-slate);
  box-shadow: var(--btn-lip);
  font-size: 1rem;
  cursor: pointer;
}
.filters-body { display: grid; gap: 14px; padding: 12px 14px 16px; }
.filter-group { margin: 0; padding: 0; border: 0; min-width: 0; }
.filter-h { margin: 0 0 6px; padding: 0; font-size: 1rem; }
.seg { display: flex; flex-wrap: wrap; gap: 8px; }
/* One option: a chunky button; the chosen one is blue. Radios stay real (and focusable)
   but invisible, so arrow keys work as usual. */
.opt {
  position: relative;
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 4px 14px;
  border: 3px solid var(--ink);
  border-radius: 12px;
  background: var(--btn-slate);
  box-shadow: var(--btn-lip);
  color: #c7d0de;
  font-size: 1rem;
  cursor: pointer;
}
.opt input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.opt:has(input:checked) { background: var(--btn-blue); color: #fff; }
.opt:has(input:focus-visible) { outline: 3px solid var(--focus); outline-offset: 2px; }
/* Colours: each button filled with its tier; off = dark and dim. */
.tier-chip.tier-champion { --chip-fill: linear-gradient(#ffe680, #ffc21a 60%, #e09a00); }
.tier-chip.tier-legendary { --chip-fill: linear-gradient(90deg, #3fe0c8, #ff7ad9, #ffd84d); }
.tier-chip.tier-epic { --chip-fill: linear-gradient(#e1a2ff, #b25df0 60%, #8a3cc8); }
.tier-chip.tier-rare { --chip-fill: linear-gradient(#ffc27a, #ff9a2e 60%, #d9730e); }
.tier-chip.tier-common { --chip-fill: linear-gradient(#b5e6ff, #7cc8f5 60%, #4d9fd6); } /* clearly light blue (owner, 2026-10-27) */
.tier-chip .fill { background: none; color: inherit; -webkit-text-fill-color: currentColor; }
/* Word on the first line, its percent range smaller on the second (CONTRACT 4). */
.tier-chip { flex-direction: column; line-height: 1.1; padding-block: 4px; }
.tier-chip .tier-range { margin-top: 1px; font-size: 0.82rem; letter-spacing: 0.04em; -webkit-text-stroke-width: 2px; text-shadow: 0 1px 0 var(--ink); }
.tier-chip[aria-pressed="true"] { background: var(--chip-fill); color: #fff; }
.tier-chip[aria-pressed="false"] {
  background: linear-gradient(#3a4458, #2a3244);
  color: #8b95a8;
  box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.35), 0 3px 0 var(--ink);
}
@media (prefers-reduced-motion: no-preference) {
  .filters { transition: opacity 160ms ease-out, scale 260ms cubic-bezier(0.34, 1.56, 0.64, 1), display 260ms allow-discrete; }
  .filters[hidden] { opacity: 0; scale: 0.96; }
  @starting-style { .filters:not([hidden]) { opacity: 0; scale: 0.94; } }
  .lookup .filter-toggle, .opt, .filter-close { transition: translate 80ms ease-out, box-shadow 80ms ease-out; }
}

/* Badges together: input + suggestion list, picked chips, one number. The input is a
   sunken dark well inside the filter window. */
.combo-pick { position: relative; }
.combo-pick input {
  width: 100%;
  min-height: 42px;
  font: inherit;
  padding: 8px 12px;
  border: 3px solid var(--ink);
  border-radius: 12px;
  background: #0b1424;
  color: var(--text);
  box-shadow: inset 0 3px 0 rgba(0, 0, 0, 0.45);
}
.combo-out { text-align: center; }
.combo-pick input::placeholder { color: #9aa1b1; }
.combo-pick input:disabled { opacity: 0.6; }
.combo-list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  z-index: 5;
  margin: 0;
  padding: 4px;
  list-style: none;
  text-align: left;
  border: 1px solid rgba(63, 169, 216, 0.45);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.92);
  box-shadow: 0 0 18px rgba(0, 119, 182, 0.35);
  max-height: min(22rem, 60vh);
  overflow-y: auto;
}
.combo-list[hidden] { display: none; }
.suggest { display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 4px 8px; border-radius: 6px; cursor: pointer; }
.suggest[aria-selected="true"], .suggest:hover { background: rgba(63, 169, 216, 0.25); color: #fff; }
.chip-pic { width: 32px; height: 32px; object-fit: contain; flex: 0 0 auto; }
.combo-chips { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.combo-chips:empty { display: none; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  min-height: 40px;
  padding: 3px 4px 3px 8px;
  border: 1px solid rgba(111, 168, 216, 0.45);
  border-radius: 999px;
  font-size: 0.9rem;
  text-align: left;
}
.chip-name { min-width: 0; line-height: 1.2; }
.chip-level {
  min-height: 28px;
  max-width: 8.5rem;
  font: inherit;
  font-size: 0.85rem;
  color: var(--text);
  background: #0b1020;
  border: 1px solid rgba(111, 168, 216, 0.6);
  border-radius: 6px;
}
.chip-x {
  min-width: 32px;
  min-height: 32px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--muted);
  font: 700 1.2rem/1 system-ui, sans-serif;
  text-shadow: var(--halo);
  cursor: pointer;
}
.chip-x:hover { color: var(--text); background: rgba(63, 169, 216, 0.2); }
.combo-out:empty { display: none; }
.combo-out { margin-top: 10px; }
.combo-out.waiting { opacity: 0.45; }
.combo-out.tip-on { position: relative; z-index: 4; }
.combo-share { font-size: 1.9rem; }
.combo-line { color: var(--muted); font-size: 0.95rem; }
.combo-error { color: var(--muted); }
@media (prefers-reduced-motion: no-preference) {
  .combo-out { transition: opacity 150ms ease-out; }
}

/* The reveal (REVEAL in lib/view.js: 150 ms lead, 350 ms each, done by 1.2 s): player and
   highlights fade in, then the badges fade and rise one by one, rarest first. New nodes on
   every lookup, so it replays. None with reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .results .player, .results .highlights { animation: reveal-fade 350ms ease-out both; }
  .results .badge {
    animation: reveal-rise 350ms ease-out both;
    animation-delay: calc(150ms + var(--i, 0) * 1ms);
  }
  /* A filter change only moves, hides and shows cards: no replayed reveal. */
  .results .settled .badge { animation: none; }
}
@media (prefers-reduced-motion: no-preference) {
  /* All badges: only the first screenful (catalogReveal); none again while searching. */
  .catalog:not(.settled) .badge.reveal {
    animation: reveal-rise 350ms ease-out both;
    animation-delay: calc(150ms + var(--i, 0) * 1ms);
  }
}
@keyframes reveal-fade { from { opacity: 0; } }
@keyframes reveal-rise { from { opacity: 0; transform: translateY(12px); } }

/* --- footer --- */
.foot { padding-block: 8px 32px; color: var(--muted); }
.foot #summary { color: var(--text); font-weight: 500; font-variant-numeric: tabular-nums; }
/* Footer disclosure: the line itself is the toggle; details open beneath it. */
.about summary { list-style: none; cursor: pointer; display: inline; }
.about summary::-webkit-details-marker { display: none; }
.about .info { color: var(--muted); margin-left: 4px; }
.about summary:hover .info, .about[open] .info { color: var(--text); }
/* Opens upward, over the page, so the footer never grows and nothing needs scrolling. */
.about { position: relative; display: inline-block; }
.about-pop {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  width: min(34rem, calc(100vw - 32px));
  padding: 12px 16px;
  border-radius: 12px;
  border: 1px solid rgba(63, 169, 216, .45);
  background: rgba(0, 0, 0, .88);
  box-shadow: 0 0 18px rgba(0, 119, 182, .35);
  z-index: 2;
}
#summary-detail { font-size: 0.85rem; margin: 0; }
.about-pop .small { margin-top: 6px; }
.small { font-size: 0.85rem; margin: 6px auto 0; max-width: 70ch; }

/* --- background particle wave (background.js): behind everything, never in the way --- */
.bg-waves {
  image-rendering: pixelated; /* the 2D fallback paints at 1x: keep the points crisp */
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
}

/* Font test notice in the ⓘ popover (page.js, CONTRACT 11b): a button that reads as a link. */
.linkish {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; text-shadow: inherit; text-decoration: underline;
}

/* Visually hidden but read by screen readers (the tag field's label). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
