/* ==========================================================================
   Illustration Pokédex — dark theme
   Card art is the subject here, so the chrome stays quiet: near-black base,
   one violet accent, and full uncropped card images at trading-card ratio.
   ========================================================================== */

:root {
  --line: rgba(255, 255, 255, 0.09);
  --line-strong: rgba(255, 255, 255, 0.16);
  --amber: #fbbf24;
  --green: #34d399;
  --danger: #fb7185;

  /* Real trading-card proportions — 63mm x 88mm. */
  --card-ratio: 63 / 88;
  --radius-lg: 20px;
  --shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.9);
  --topbar-h: 62px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: Outfit, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -0.01em; }

button, input, select, textarea { font: inherit; color: inherit; }

svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

::selection { background: var(--accent-soft); }

/* ── Ambient background ─────────────────────────────────────────────── */
.aurora { position: fixed; inset: 0; z-index: -1; overflow: hidden; }
.aurora span {
  position: absolute;
  border-radius: 50%;
  filter: blur(120px);
}
.aurora span:nth-child(1) { width: 46vw; height: 46vw; top: -14vw; left: -8vw; }
.aurora span:nth-child(2) { width: 36vw; height: 36vw; top: 22vw; right: -10vw; }
.aurora span:nth-child(3) { width: 30vw; height: 30vw; bottom: -12vw; left: 34vw; }

/* ── Top bar ────────────────────────────────────────────────────────── */
.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--topbar-h);
  backdrop-filter: blur(18px) saturate(150%);
  border-bottom: 1px solid var(--line);
}

.topbar-inner {
  max-width: var(--page-max);
  height: 100%;
  margin: 0 auto;
  padding: 0 22px;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: nowrap;
  min-width: 0;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: inherit;
  min-width: 0;
  flex-shrink: 1;
}

/* The mark is an inline SVG — a card with a horizon and a sun in it, which is
   decision 1 (art covering the whole card, depicting a real environment) drawn
   rather than described. Inline so it takes --bg from the palette and repaints
   with the theme; favicon.svg is the same drawing with the colour baked in,
   since a tab icon cannot read CSS variables.

   `stroke: none` matters: the global svg rule sets stroke: currentColor at
   1.9px, which would outline every shape in here. */
.brand-mark {
  width: 34px; height: 34px;
  flex: none;
  stroke: none;
  overflow: visible;
  filter: drop-shadow(0 3px 10px color-mix(in srgb, var(--accent) 32%, transparent));
}

.brand-text { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
/* The title is an h1 for structure; it keeps the visual weight it had as
   <strong>, so nothing moves. */
.brand-text h1 { margin: 0; font-size: 16px; font-weight: 700; white-space: nowrap; }
.brand-text small { font-size: 11.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.topbar-actions { display: flex; align-items: center; gap: 8px; flex: none; }

/* ── Collection switcher ────────────────────────────────────────────── */
.collection-switch { position: relative; display: flex; align-items: center; gap: 8px;
  margin-left: auto; margin-right: 12px; min-width: 0; flex-shrink: 1; }
/* The edit button sits beside the switcher, not under it. The menu is absolutely
   positioned, so it is unaffected by the row. */
#editCollection { flex: 0 0 auto; }

.collection-btn {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 40px;
  padding: 0 11px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: var(--surface);
  cursor: pointer;
  transition: background 0.16s, border-color 0.16s;
}
.collection-btn:hover { background: var(--surface-2); border-color: var(--line-strong); }
/* Without these the button refuses to shrink and its text spills over the
   neighbouring controls instead. */
.collection-btn { min-width: 0; overflow: hidden; }
.collection-btn svg { width: 15px; height: 15px; color: var(--faint); }

.collection-icon { font-size: 17px; line-height: 1; }
.collection-label { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.2; min-width: 0; }
.collection-label small { font-size: 9.5px; letter-spacing: 0.09em; text-transform: uppercase; color: var(--faint); }
.collection-label strong {
  font-size: 13.5px; font-weight: 600;
  max-width: 190px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.collection-menu {
  position: absolute;
  top: calc(100% + 7px);
  left: 0;
  z-index: 60;
  min-width: 290px;
  max-width: 360px;
  padding: 6px;
  border-radius: 13px;
  border: 1px solid var(--line-strong);
  background: rgba(18, 18, 26, 0.98);
  backdrop-filter: blur(16px);
  box-shadow: 0 24px 50px -20px rgba(0, 0, 0, 0.95);
}
.collection-menu[hidden] { display: none; }

.collection-row { display: flex; align-items: stretch; gap: 2px; border-radius: 9px; }
.collection-row:hover { background: var(--surface-2); }
.collection-row.is-active { background: var(--accent-soft); }

.collection-pick {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 9px 10px;
  border: 0;
  border-radius: 9px;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.collection-text { display: flex; flex-direction: column; min-width: 0; }
.collection-text strong { font-size: 13.5px; font-weight: 600; }
.collection-text small {
  font-size: 11.5px; color: var(--faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.collection-edit {
  width: 32px;
  border: 0;
  border-radius: 9px;
  background: none;
  color: var(--faint);
  cursor: pointer;
  font-size: 13px;
}
.collection-edit:hover { color: var(--text); background: var(--surface-2); }

.collection-add {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 9px;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0 0 9px 9px;
  background: none;
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.collection-add:hover { background: var(--surface-2); }

/* ── Collection editor ──────────────────────────────────────────────── */
.modal-md { max-width: min(620px, calc(100vw - 32px)); }

.form-row { display: flex; gap: 10px; align-items: flex-end; }
.form-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.form-field > span {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--faint);
}
.form-grow { flex: 1; }
.form-icon input { width: 58px; text-align: center; font-size: 18px; }

.form-field input[type="text"] {
  height: 38px;
  padding: 0 11px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface);
  outline: none;
}
.form-field input[type="text"]:focus { border-color: color-mix(in srgb, var(--accent) 60%, transparent); }

.token-input { position: relative; display: flex; flex-direction: column; gap: 6px; }
.tokens { display: flex; flex-wrap: wrap; gap: 5px; }
.tokens:empty { display: none; }
.token {
  display: inline-flex; align-items: center; gap: 5px;
  height: 26px; padding: 0 5px 0 9px;
  border-radius: 99px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
  font-size: 12px; color: #ddd6fe;
}
.token button { border: 0; background: none; color: inherit; opacity: 0.7; cursor: pointer; font-size: 11px; padding: 2px; }
.token button:hover { opacity: 1; }

.suggest {
  position: absolute;
  top: 100%;
  left: 0; right: 0;
  z-index: 5;
  margin-top: 4px;
  padding: 4px;
  border-radius: 10px;
  border: 1px solid var(--line-strong);
  background: rgba(20, 20, 30, 0.99);
  box-shadow: var(--shadow);
  max-height: 220px;
  overflow-y: auto;
}
.suggest[hidden] { display: none; }
.suggest-item {
  display: block; width: 100%;
  padding: 8px 10px;
  border: 0; border-radius: 7px;
  background: none; color: inherit;
  text-align: left; font-size: 13px; cursor: pointer;
}
.suggest-item:hover { background: var(--accent-soft); }

.switch-inline { height: auto; margin-top: 2px; }

.coll-preview {
  margin: 2px 0 0;
  padding: 10px 12px;
  border-radius: 9px;
  background: var(--surface);
  border: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--muted);
}

/* The switcher is the important control up here, so the wordmark yields first. */
@media (max-width: 1100px) {
  .brand-text small { display: none; }
}
@media (max-width: 980px) {
  /*
   * Hidden to reclaim topbar width, but not with display:none — that also
   * removed the h1 from the accessibility tree, leaving phones with no page
   * heading at all. Clipped instead, so it is still announced.
   */
  .brand-text {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .collection-switch { margin-left: 0; }
}
@media (max-width: 760px) {
  .collection-label small { display: none; }
  .collection-label strong { max-width: 110px; }
  .collection-btn { height: 36px; padding: 0 9px; }
}
/* Very narrow: the switcher becomes an icon. The menu still names everything. */
@media (max-width: 620px) {
  .collection-label { display: none; }
  .collection-btn { padding: 0 8px; gap: 5px; }
}

/* ── Buttons ────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 36px;
  padding: 0 13px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.16s, border-color 0.16s, transform 0.16s;
}
.btn:hover { background: var(--surface-2); border-color: var(--line-strong); }
.btn:active { transform: translateY(1px); }
/* Accent-derived colours use color-mix on --accent rather than a hardcoded
   hex, so a palette change repaints them. The jade redesign missed six
   hardcoded purples this way — four focus borders, a button glow and the
   Insights hero wash — which stayed violet in a mint UI. */
/* A class-level `display` outranks the UA rule for [hidden], so restate it. */
.btn[hidden], .mini-btn[hidden] { display: none; }
.btn svg { width: 16px; height: 16px; }

.btn-primary {
  border-color: transparent;
  font-weight: 600;
}
.btn-primary:hover { filter: brightness(1.12); }

.btn-danger { background: rgba(251, 113, 133, 0.13); border-color: rgba(251, 113, 133, 0.35); color: #fecdd3; }
.btn-danger:hover { background: rgba(251, 113, 133, 0.2); }

.link-btn {
  background: none; border: 0; padding: 0;
  color: var(--accent);
  font-size: 13px; font-weight: 500;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.link-muted { color: var(--faint); text-decoration-style: dotted; }
.link-muted:hover, .link-muted.is-active { color: var(--text); }
.link-muted[hidden] { display: none; }

/* Sync spinner */
.sync-icon { transition: transform 0.2s; }
.btn.is-busy { opacity: 0.75; cursor: progress; }
.btn.is-busy .sync-icon { animation: spin 0.9s linear infinite; transform-origin: 50% 50%; }
@keyframes spin { to { transform: rotate(360deg); } }

.pill-badge {
  min-width: 18px; height: 18px;
  display: inline-grid; place-items: center;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--accent-strong);
  color: #fff;
  font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ── Page shell ─────────────────────────────────────────────────────── */
.page {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 22px 22px 70px;
}

/* ── Stats ──────────────────────────────────────────────────────────── */
.stats {
  display: grid;
  grid-template-columns: 1fr 1fr minmax(230px, 0.85fr);
}
.stats[hidden] { display: none; }

.stat {
  min-width: 0;
}

.stat header { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }

.stat-label {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--faint);
}

.stat-value { font-family: "DM Mono", ui-monospace, monospace; white-space: nowrap; }
.stat-value b { font-size: 25px; font-weight: 500; }
.stat-value i { font-style: normal; font-size: 14px; color: var(--faint); margin-left: 3px; }

.meter {
  height: 6px;
  margin: 11px 0 8px;
  border-radius: 99px;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
}
.meter-fill {
  height: 100%;
  width: 0;
  border-radius: 99px;
  transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.meter-cyan { background: linear-gradient(90deg, var(--cyan), #22d3ee); }

.stat footer { font-size: 12.5px; color: var(--muted); }

/* Two columns: this list is what set the height of the whole stats row, pushing
   the card grid past the fold on a laptop. Seven categories read fine paired. */
.cat-list {
  list-style: none; margin: 10px 0 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 18px;
}
@media (max-width: 900px) { .cat-list { grid-template-columns: 1fr; } }
.cat-list li {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px;
}
.cat-list .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.cat-list .cat-name { color: var(--muted); }
.cat-list .cat-num {
  margin-left: auto;
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: 12px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* ── Controls ───────────────────────────────────────────────────────── */
.controls {
  position: sticky;
  top: var(--topbar-h);
  z-index: 40;
  margin: 0 -22px 20px;
  padding: 12px 22px;
  backdrop-filter: blur(18px) saturate(150%);
  border-bottom: 1px solid var(--line);
}

.controls-row { display: flex; align-items: center; flex-wrap: wrap; }

.search {
  position: relative;
  flex: 1 1 260px;
  min-width: 200px;
  display: flex;
  align-items: center;
}
.search svg { position: absolute; left: 12px; width: 17px; height: 17px; color: var(--faint); pointer-events: none; }
.search input {
  width: 100%;
  height: 38px;
  padding: 0 36px 0 37px;
  border-radius: 10px;
  border: 1px solid var(--line);
  outline: none;
  transition: border-color 0.16s, background 0.16s;
}
.search input::placeholder { color: var(--faint); }
.search input:focus { border-color: color-mix(in srgb, var(--accent) 60%, transparent); background: var(--surface-2); }
.search input::-webkit-search-cancel-button { display: none; }
.search-clear {
  position: absolute; right: 8px;
  width: 22px; height: 22px;
  display: grid; place-items: center;
  border: 0; border-radius: 6px;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 11px;
  cursor: pointer;
}
.search-clear:hover { color: var(--text); }

.tabs {
  display: flex;
  gap: 2px;
  padding: 3px;
  border-radius: 11px;
  border: 1px solid var(--line);
}
.tab {
  height: 30px;
  padding: 0 13px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.16s, color 0.16s;
}
.tab:hover { color: var(--text); }
.tab.is-active { font-weight: 600; }
.tab-count {
  margin-left: 5px;
  font-family: "DM Mono", monospace;
  font-size: 11px;
  opacity: 0.75;
}

/* ── Filter panel ───────────────────────────────────────────────────── */
.filter-panel {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 20px;
  margin-top: 13px;
  padding: 15px 0 4px;
  border-top: 1px solid var(--line);
}
.filter-panel[hidden] { display: none; }
/* A class-level `display` outranks the UA rule for [hidden], so restate it.
   These come off when a visitor is browsing the catalogue signed out. */
.field[hidden], .quick-status[hidden], .collection-hero[hidden] { display: none; }

.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field-grow { flex: 1 1 300px; }
.field > label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--faint);
}

.seg {
  display: inline-flex;
  padding: 3px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--surface);
}
.seg button {
  height: 28px;
  padding: 0 11px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--muted);
  font-size: 12.5px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.16s, color 0.16s;
}
.seg button:hover { color: var(--text); }
.seg button.is-active { background: var(--surface-2); color: var(--text); font-weight: 600; box-shadow: inset 0 0 0 1px var(--line-strong); }

.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 11px;
  border-radius: 99px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  font-size: 12.5px;
  cursor: pointer;
  transition: background 0.16s, color 0.16s, border-color 0.16s;
}
.chip:hover { color: var(--text); border-color: var(--line-strong); }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.chip .chip-num { font-family: "DM Mono", monospace; font-size: 11px; opacity: 0.7; }
.chip.is-on { color: var(--text); background: var(--surface-2); border-color: var(--line-strong); font-weight: 600; }
.chip.is-on .chip-num { opacity: 0.95; }
/* The opt-in pool is machine-selected, so it looks provisional until enabled. */
.chip-optin { border-style: dashed; }
.chip-optin.is-on { border-style: solid; border-color: rgba(148, 163, 184, 0.5); }

select {
  height: 34px;
  padding: 0 30px 0 11px;
  border-radius: 9px;
  border: 1px solid var(--line);
  background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239b98ad' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 8px center / 15px;
  appearance: none;
  cursor: pointer;
  max-width: 240px;
  outline: none;
}
select:focus { border-color: color-mix(in srgb, var(--accent) 60%, transparent); }
select option { background: #14141d; }

.switch { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); cursor: pointer; height: 34px; }
.switch input {
  appearance: none;
  width: 34px; height: 19px;
  border-radius: 99px;
  background: rgba(255, 255, 255, 0.13);
  position: relative;
  cursor: pointer;
  transition: background 0.18s;
  flex: none;
}
.switch input::after {
  content: "";
  position: absolute;
  top: 2.5px; left: 2.5px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.18s;
}
.switch input:checked { background: var(--accent); }
.switch input:checked::after { transform: translateX(15px); }
.switch:hover { color: var(--text); }

.preset-row { display: flex; align-items: center; gap: 6px; }
.preset-row select { max-width: 190px; }
.field-note { font-size: 11px; color: var(--faint); }

/* ── Results bar ────────────────────────────────────────────────────── */
.results-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 11px;
}
.results-count { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

.active-filters { display: flex; flex-wrap: wrap; gap: 6px; }
.active-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 6px 0 9px;
  border-radius: 99px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 32%, transparent);
  font-size: 11.5px;
  color: #ddd6fe;
}
.active-filter button {
  border: 0; background: none; cursor: pointer;
  color: inherit; opacity: 0.7;
  font-size: 12px; line-height: 1;
  padding: 2px;
}
.active-filter button:hover { opacity: 1; }

/* ── Grid ───────────────────────────────────────────────────────────── */
.grid {
  display: grid;
}
/* A class-level `display` beats the UA rule for [hidden], so restate it. */
.grid[hidden] { display: none; }

/* One Pokédex slot, or one card in the flat views. */
.tile {
  position: relative;
  border: 0;
  padding: 0;
  border-radius: var(--radius);
  background: none;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.tile:hover { transform: translateY(-4px); }
.tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: var(--radius); }

/*
 * One visible focus ring for everything that takes focus.
 *
 * Only .tile had one, so 114 of the 115 focusable controls gave a keyboard user
 * nothing to follow — the tab position was simply invisible (WCAG 2.4.7).
 * :focus-visible rather than :focus so a mouse click does not leave a ring
 * behind, and a hard-coded light colour rather than the accent for the two
 * accent-filled buttons, where purple on purple would vanish.
 */
:where(button, a[href], input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 8px;
}
.btn-primary:focus-visible,
.tab.is-active:focus-visible,
.chip.is-on:focus-visible {
  outline-color: #e9d5ff;
}
/* The search field already tints its border on focus; the ring would double up
   on an element that is 100% of the row. */
.search input:focus-visible { outline-offset: -2px; }

.tile-art {
  position: relative;
  aspect-ratio: var(--card-ratio);
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0.02));
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.07) inset, var(--shadow);
  /* A slow sheen while the art is in flight, so an empty frame reads as loading
     rather than as a card with nothing on it. Stops as soon as one lands. */
  background-size: 200% 100%;
  animation: art-wait 2.4s ease-in-out infinite;
  transition: box-shadow 0.2s;
}
.tile-art:has(img.is-loaded) {
  animation: none;
}
@keyframes art-wait {
  0%, 100% { background-position: 0% 0%; }
  50% { background-position: 100% 0%; }
}


/* contain, never cover — cropping an illustration card defeats the point */
.tile-art img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  opacity: 0;
  transition: opacity 0.35s, filter 0.25s;
}
.tile-art img.is-loaded { opacity: 1; }

/* Read "not yet mine" at a glance. Deliberately gentle — the artwork is the
   point, so colour stays legible and only the life goes out of it. Hover
   restores the card completely. */
/*
 * The grey over cards you do not own. Kept at its original strength on the
 * user's call: I had made it scale with ownership, on the reasoning that at 4%
 * owned it desaturates almost the whole grid and buries the artwork. They prefer
 * the stronger, constant version — the greying is the point, and hover still
 * restores a card completely.
 *
 * The variables stay so the strength is one place to change, not three.
 */
:root {
  --dim-gray: 0.42;
  --dim-bright: 0.86;
  --dim-sat: 0.9;
}
.dim-unowned .tile.is-missing .tile-art img {
  filter: grayscale(var(--dim-gray)) brightness(var(--dim-bright)) saturate(var(--dim-sat));
}
.dim-unowned .tile.is-missing:hover .tile-art img { filter: none; }

/* Owned cards read as "mine" by contrast: full colour, a touch more presence. */
.dim-unowned .tile.is-owned .tile-art img { filter: saturate(1.04); }

/*
 * Owned is the state worth seeing across a screen of cards, so it gets weight
 * rather than a hairline: a brighter edge, a green cast in the shadow so the card
 * sits above the grid, and a slight lift. Everything else is a target, not a
 * possession.
 */
.tile.is-owned .tile-art {
  transform: translateY(-2px);
}
.tile.is-owned:hover .tile-art {
  box-shadow:
    0 0 0 2px rgba(52, 211, 153, 1),
    0 20px 44px -16px rgba(52, 211, 153, 0.6),
    0 22px 46px -18px rgba(0, 0, 0, 0.95);
  transform: translateY(-3px);
}
.tile .tile-art { transition: box-shadow 0.18s, transform 0.18s, background 0.18s; }

.tile-badges {
  position: absolute;
  top: 7px; left: 7px; right: 7px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
  pointer-events: none;
  z-index: 2;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 21px;
  padding: 0 7px;
  border-radius: 7px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  background: rgba(6, 6, 10, 0.76);
  backdrop-filter: blur(7px);
  border: 1px solid rgba(255, 255, 255, 0.12);
  white-space: nowrap;
}
.badge-dex { font-family: "DM Mono", monospace; font-weight: 500; color: #e9e7f2; }
.badge-cat { color: #fff; }

.tile-own {
  position: absolute;
  bottom: 8px; right: 8px;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(6, 6, 10, 0.72);
  backdrop-filter: blur(7px);
  color: var(--muted);
  cursor: pointer;
  transition: background 0.16s, color 0.16s, transform 0.16s, border-color 0.16s;
}
.tile-own:hover { transform: scale(1.1); color: var(--text); border-color: var(--line-strong); }
.tile-own svg { width: 15px; height: 15px; }
.tile.is-owned .tile-own {
  background: var(--green);
  border-color: transparent;
  color: #04231a;
  box-shadow: 0 0 16px -3px rgba(52, 211, 153, 0.8);
}
.tile-own[hidden] { display: none; }

.tile-prints {
  position: absolute;
  bottom: 8px; left: 8px;
  z-index: 2;
  height: 21px;
  padding: 0 7px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: 7px;
  font-size: 10.5px;
  font-weight: 600;
  background: rgba(6, 6, 10, 0.76);
  backdrop-filter: blur(7px);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #d8d5e6;
  pointer-events: none;
}

.tile-meta { padding: 9px 3px 0; }
.tile-name {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
}
.tile-name > span:last-child { overflow: hidden; text-overflow: ellipsis; }
.tile-dex {
  flex: none;
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: 11px;
  font-weight: 400;
  color: var(--faint);
}
.tile-sub {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 11.5px;
  color: var(--faint);
}
.tile-set { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tile-price { font-family: "DM Mono", monospace; color: var(--muted); white-space: nowrap; }

/* Species with no illustration card yet */
.tile-empty .tile-art {
  /* No loading sheen on a slot that will never have art. */
  animation: none;
  display: grid;
  place-items: center;
}
.tile-empty .tile-art img {
  position: static;
  width: 58%;
  height: auto;
  opacity: 0;
  filter: grayscale(1) brightness(0.42) contrast(1.15);
}
.tile-empty .tile-art img.is-loaded { opacity: 0.5; }
.tile-empty:hover .tile-art img { opacity: 0.72; }
.tile-empty .tile-note {
  position: absolute;
  bottom: 9px; left: 0; right: 0;
  text-align: center;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
}

/* Cards the user pushed out of the dataset */
.tile-hidden { cursor: default; }
.tile-hidden:hover { transform: none; }
.tile-hidden .tile-art img { filter: grayscale(1) brightness(0.45); }
.tile-hidden .tile-art { box-shadow: none; border: 1px dashed var(--line-strong); }
.restore-btn {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  height: 30px;
  padding: 0 13px;
  border-radius: 9px;
  border: 1px solid var(--line-strong);
  background: rgba(10, 10, 16, 0.9);
  backdrop-filter: blur(6px);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}
.restore-btn:hover { background: var(--accent); border-color: transparent; }

/* "Not an illustration card" escape hatch in the detail modal */
.reject-btn {
  display: block;
  width: 100%;
  margin-top: 16px;
  padding: 9px 12px;
  border-radius: 10px;
  border: 1px dashed var(--line-strong);
  background: none;
  color: var(--faint);
  font-size: 12.5px;
  cursor: pointer;
  transition: color 0.16s, border-color 0.16s, background 0.16s;
}
.reject-btn:hover {
  color: #fecdd3;
  border-color: rgba(251, 113, 133, 0.5);
  background: rgba(251, 113, 133, 0.08);
}

/* Verdict pair in the detail modal: keep on the left, reject on the right. */
.verdict-row { display: flex; gap: 8px; margin-top: 16px; }
.verdict-row .reject-btn,
.verdict-row .keep-btn { margin-top: 0; flex: 1 1 0; }
.verdict-row .keep-btn[hidden] { display: none; }

.keep-btn {
  display: block;
  width: 100%;
  padding: 9px 12px;
  border-radius: 10px;
  border: 1px dashed var(--line-strong);
  background: none;
  color: var(--faint);
  font-size: 12.5px;
  cursor: pointer;
  transition: color 0.16s, border-color 0.16s, background 0.16s;
}
.keep-btn:hover {
  color: #bbf7d0;
  border-color: rgba(74, 222, 128, 0.5);
  background: rgba(74, 222, 128, 0.08);
}
/* Already checked: solid, so the verdict reads at a glance. */
.keep-btn.is-on {
  border-style: solid;
  color: #bbf7d0;
  border-color: rgba(74, 222, 128, 0.55);
  background: rgba(74, 222, 128, 0.16);
}

.mini-good:hover:not(:disabled) {
  color: #bbf7d0;
  border-color: rgba(74, 222, 128, 0.5);
  background: rgba(74, 222, 128, 0.12);
}

.field-hint {
  margin: 6px 0 0;
  font-size: 11.5px;
  color: var(--faint);
}

.cat-list li.is-off { opacity: 0.4; }

/* Loading skeletons */
.skeleton .tile-art {
  background: linear-gradient(100deg, rgba(255,255,255,0.03) 30%, rgba(255,255,255,0.07) 50%, rgba(255,255,255,0.03) 70%);
  background-size: 220% 100%;
  animation: shimmer 1.3s linear infinite;
}
.skeleton .tile-meta { opacity: 0.35; }
.skeleton .tile-name, .skeleton .tile-set {
  display: block;
  height: 9px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.09);
}
.skeleton .tile-name { width: 72%; margin-bottom: 6px; }
.skeleton .tile-set { width: 45%; }
@keyframes shimmer { to { background-position: -220% 0; } }

/* ── Insights ───────────────────────────────────────────────────────── */
.insights {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 14px;
  align-items: start;
}
.insights[hidden] { display: none; }

.panel {
  padding: 17px 18px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: linear-gradient(180deg, var(--surface), rgba(255, 255, 255, 0.014));
  min-width: 0;
}
.panel h3 { font-size: 16px; margin-bottom: 3px; }
.panel-note { margin: 4px 0 0; font-size: 12px; color: var(--faint); }
.panel .meter { margin: 12px 0 8px; }

.panel-hero {
  grid-column: span 2;
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  background:
    radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--accent) 18%, transparent), transparent 60%),
    linear-gradient(180deg, var(--surface-2), rgba(255, 255, 255, 0.02));
}
.panel-hero h3 { font-size: 23px; margin-bottom: 5px; }
.panel-hero .btn { margin-top: 13px; }

.panel-kicker {
  display: block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 5px;
}

.hero-line { margin: 0; font-size: 13.5px; color: var(--muted); }
.hero-line b { color: var(--text); font-size: 17px; font-family: "DM Mono", monospace; font-weight: 500; }

.panel-empty {
  margin: 12px 0 0;
  padding: 12px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.025);
  font-size: 13px;
  color: var(--muted);
}
.panel-empty b { color: var(--text); }

.value-line { margin: 9px 0 0; font-size: 13px; color: var(--muted); }
.value-line b { color: var(--amber); font-family: "DM Mono", monospace; font-weight: 500; }

.rows { list-style: none; margin: 11px 0 0; padding: 0; display: grid; gap: 3px; }
.rows li { position: relative; }

.row-link {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 7px 8px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.14s;
}
.row-link:hover { background: var(--surface-2); }

.row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.row-name {
  font-size: 13.5px; font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.row-sub { font-size: 11.5px; color: var(--faint); }

.row-figure {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-family: "DM Mono", ui-monospace, monospace;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}
.row-figure small { font-family: Outfit, sans-serif; font-size: 10px; color: var(--faint); }
.row-price { color: var(--amber); font-size: 13.5px; }

.row-meter {
  display: block;
  height: 2px;
  margin: 0 8px;
  border-radius: 99px;
  background: rgba(255, 255, 255, 0.06);
  overflow: hidden;
}
.row-meter i { display: block; height: 100%; background: var(--accent); opacity: 0.75; }
.rows-plain li .row-meter { display: none; }

@media (max-width: 760px) {
  .panel-hero { grid-column: span 1; }
}

/* ── Empty / load more ──────────────────────────────────────────────── */
.empty { text-align: center; padding: 70px 20px; }
.empty[hidden] { display: none; }
.empty-title { margin: 0 0 6px; font-size: 17px; font-weight: 600; }
.empty-sub { margin: 0 0 18px; color: var(--muted); font-size: 13.5px; }

.load-more { display: flex; justify-content: center; padding: 30px 0 6px; }
.load-more[hidden] { display: none; }

.page-foot { margin-top: 34px; padding-top: 16px; border-top: 1px solid var(--line); }
.page-foot p { margin: 0; font-size: 11.5px; color: var(--faint); }

/* ── Modal ──────────────────────────────────────────────────────────── */
.modal {
  border: 0;
  padding: 0;
  max-width: min(980px, calc(100vw - 32px));
  max-height: calc(100vh - 40px);
  width: 100%;
  background: none;
  color: var(--text);
  overflow: visible;
}
.modal::backdrop { background: rgba(3, 3, 6, 0.78); backdrop-filter: blur(7px); }
.modal-sm { max-width: min(480px, calc(100vw - 32px)); }

.modal-shell {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  gap: 26px;
  padding: 26px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line-strong);
  background: linear-gradient(165deg, #14141e, #0b0b11 60%);
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.95);
  max-height: calc(100vh - 40px);
  overflow-y: auto;
}
/*
 * The card's artwork, extended behind the panel.
 *
 * The art is the reason this app shows cards rather than rows, so opening one
 * should feel like stepping into it rather than reading a spec sheet. Held to a
 * whisper on purpose: heavily blurred so nothing competes with the card itself,
 * and faded out towards the text side, because nine contrast failures were just
 * fixed and a busy backdrop is exactly how they come back.
 */
.modal-wash {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s ease;
}
.modal-wash.is-on { opacity: 1; }
.modal-wash::before {
  content: "";
  position: absolute;
  /* Overscanned so the blur has material at the edges instead of smearing. */
  inset: -18%;
  background-image: var(--wash-src);
  background-size: cover;
  background-position: center 22%;
  filter: blur(40px) saturate(1.35);
  /* 0.4 under the scrim below left almost nothing visible — the effect was
     technically present and perceptually absent. */
  opacity: 0.9;
}
/* Keeps the right-hand column readable whatever the card looks like. */
.modal-wash::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Light over the card, heavy over the text column: the card side can carry
     colour, the right side holds prose and a price and must stay legible. */
  background:
    linear-gradient(100deg, rgba(10, 10, 16, 0.28) 0%, rgba(10, 10, 16, 0.62) 46%, rgba(10, 10, 16, 0.88) 100%),
    radial-gradient(130% 110% at 18% 4%, transparent 30%, rgba(8, 8, 13, 0.55));
}
/* z-index only, no position: grid items honour z-index without it, and setting
   position:relative here overrode .modal-close's absolute, dropping it into the
   grid and stealing a cell — which pushed the card into the wrong column. */
.modal-shell > *:not(.modal-wash) { z-index: 1; }

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

.modal-shell-column { display: flex; flex-direction: column; gap: 13px; }

.modal-close {
  position: absolute;
  top: 12px; right: 12px;
  z-index: 5;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  font-size: 12px;
  cursor: pointer;
}
.modal-close:hover { color: var(--text); background: var(--surface-2); }

/* 3D tilt */
.modal-art { display: flex; flex-direction: column; align-items: center; gap: 11px; }
.tilt {
  position: relative;
  width: 100%;
  aspect-ratio: var(--card-ratio);
  border-radius: 12px;
  transform-style: preserve-3d;
  transition: transform 0.12s ease-out;
  will-change: transform;
}
.tilt-img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
  border-radius: 12px;
  filter: drop-shadow(0 22px 30px rgba(0, 0, 0, 0.75));
}
.tilt-shine {
  position: absolute;
  inset: 0;
  border-radius: 12px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
  background: linear-gradient(105deg,
    transparent 32%,
    rgba(255, 92, 200, 0.28) 42%,
    rgba(120, 220, 255, 0.3) 50%,
    rgba(190, 255, 140, 0.26) 58%,
    transparent 68%);
  mix-blend-mode: color-dodge;
}
.tilt.is-live .tilt-shine { opacity: 1; }
.tilt-hint { margin: 0; font-size: 11.5px; color: var(--faint); }
/* "Move your cursor across the card" means nothing without a cursor, and the
   tilt it describes is mouse-driven, so the whole affordance is absent here. */
@media (hover: none) {
  .tilt-hint { display: none; }
}

.modal-info { min-width: 0; }
.modal-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 9px; }
.tag {
  display: inline-flex; align-items: center; gap: 5px;
  height: 23px; padding: 0 9px;
  border-radius: 7px;
  font-size: 11.5px; font-weight: 600;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.tag-mono { font-family: "DM Mono", monospace; font-weight: 500; }

.modal-info h2 { font-size: 26px; line-height: 1.15; margin-bottom: 3px; }
.modal-sub { margin: 0; color: var(--muted); font-size: 13px; }

.own-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  height: 42px;
  margin: 17px 0;
  border-radius: 11px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.16s, border-color 0.16s;
}
.own-btn:hover { background: var(--surface-2); }
.own-icon {
  width: 18px; height: 18px;
  border-radius: 50%;
  border: 2px solid var(--faint);
  display: grid; place-items: center;
  flex: none;
  transition: background 0.16s, border-color 0.16s;
}
.own-btn.is-owned { background: rgba(52, 211, 153, 0.13); border-color: rgba(52, 211, 153, 0.42); color: #a7f3d0; }
.own-btn.is-owned .own-icon { background: var(--green); border-color: var(--green); }
.own-btn.is-owned .own-icon::after { content: "✓"; font-size: 11px; color: #04231a; font-weight: 800; }

.meta { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; margin: 0; border-radius: 11px; overflow: hidden; border: 1px solid var(--line); background: var(--line); }
.meta > div { padding: 10px 12px; background: rgba(255, 255, 255, 0.022); min-width: 0; }
.meta-full { grid-column: 1 / -1; }
.meta dt {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  /* --muted, not --faint: the modal's shell is lighter than a page panel, so
     --faint measures 4.13:1 in here against the 4.5 it clears elsewhere. These
     labels name the data, so they were the wrong thing to make faintest anyway. */
  color: var(--muted);
  margin-bottom: 3px;
}
.meta dd { margin: 0; font-size: 13.5px; overflow-wrap: anywhere; }
.meta-set { display: flex; align-items: center; gap: 7px; }
.meta-set img { width: 20px; height: 20px; object-fit: contain; flex: none; }
.meta dt { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

.price-refresh {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--muted);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.16s, border-color 0.16s, background 0.16s;
}
.price-refresh svg { width: 11px; height: 11px; }
.price-refresh:hover:not(:disabled) { color: var(--text); border-color: var(--line-strong); background: var(--surface-2); }
.price-refresh:disabled { opacity: 0.6; cursor: progress; }
.price-refresh.is-busy svg { animation: spin 0.9s linear infinite; transform-origin: 50% 50%; }

.meta-price { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.meta-price b { font-family: "DM Mono", monospace; font-size: 19px; font-weight: 500; color: var(--amber); }
.meta-price span { font-size: 11.5px; color: var(--muted); }

.prints { margin-top: 18px; }
.prints[hidden] { display: none; }
.prints h3 { font-size: 12px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); }
.prints-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; }

.mini-btn {
  height: 26px;
  padding: 0 10px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.16s, color 0.16s, border-color 0.16s;
}
.mini-btn:hover:not(:disabled) { color: var(--text); background: var(--surface-2); border-color: var(--line-strong); }
.mini-btn:disabled { opacity: 0.4; cursor: default; }
.mini-btn[aria-pressed="true"] { background: var(--accent-strong); border-color: transparent; color: #fff; font-weight: 600; }
.mini-danger:hover:not(:disabled) {
  color: #fecdd3;
  border-color: rgba(251, 113, 133, 0.5);
  background: rgba(251, 113, 133, 0.12);
}

.bulk-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 10px;
  padding: 9px 11px;
  border-radius: 10px;
  border: 1px solid var(--line-strong);
  background: var(--accent-soft);
}
.bulk-bar[hidden] { display: none; }
.bulk-count { font-size: 12.5px; font-weight: 600; color: #ddd6fe; font-variant-numeric: tabular-nums; }
.bulk-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.prints-row { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 5px; }
.print-thumb {
  flex: none;
  width: 62px;
  aspect-ratio: var(--card-ratio);
  padding: 0;
  border-radius: 7px;
  border: 2px solid transparent;
  background: rgba(255, 255, 255, 0.04);
  overflow: hidden;
  cursor: pointer;
  transition: border-color 0.16s, transform 0.16s;
}
.print-thumb img { width: 100%; height: 100%; object-fit: contain; display: block; }
.print-thumb:hover { transform: translateY(-2px); border-color: var(--line-strong); }
.print-thumb.is-active { border-color: var(--accent); }
.print-thumb.is-owned { box-shadow: inset 0 0 0 2px var(--green); }

/* Multi-select: thumbnails become checkboxes rather than navigation. */
.prints-row.is-selecting .print-thumb { position: relative; }
.prints-row.is-selecting .print-thumb img { opacity: 0.55; transition: opacity 0.16s; }
.prints-row.is-selecting .print-thumb.is-picked img { opacity: 1; }
.prints-row.is-selecting .print-thumb.is-picked { border-color: var(--accent); }

.thumb-tick {
  position: absolute;
  top: 3px; right: 3px;
  width: 15px; height: 15px;
  border-radius: 4px;
  border: 1.5px solid rgba(255, 255, 255, 0.65);
  background: rgba(6, 6, 10, 0.7);
}
.print-thumb.is-picked .thumb-tick {
  background: var(--accent);
  border-color: var(--accent);
}
.print-thumb.is-picked .thumb-tick::after {
  content: "✓";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 10px;
  font-weight: 800;
  color: #fff;
}

/* ── Import ─────────────────────────────────────────────────────────── */
.dropzone {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 9px;
  padding: 26px 18px;
  border-radius: 12px;
  border: 1.5px dashed var(--line-strong);
  background: var(--surface);
  color: var(--muted);
  font-size: 13px;
  cursor: pointer;
  text-align: center;
  transition: border-color 0.16s, background 0.16s;
}
.dropzone:hover, .dropzone.is-over { border-color: var(--accent); background: var(--accent-soft); color: var(--text); }
.dropzone input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.dropzone svg { width: 26px; height: 26px; }

.or { display: flex; align-items: center; gap: 11px; color: var(--faint); font-size: 10.5px; letter-spacing: 0.1em; text-transform: uppercase; }
.or::before, .or::after { content: ""; flex: 1; height: 1px; background: var(--line); }

textarea {
  width: 100%;
  padding: 11px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--surface);
  resize: vertical;
  outline: none;
  font-family: "DM Mono", monospace;
  font-size: 12px;
}
textarea:focus { border-color: color-mix(in srgb, var(--accent) 60%, transparent); }

.import-status { margin: 0; font-size: 12.5px; padding: 9px 11px; border-radius: 9px; background: var(--surface); }
.import-status[hidden] { display: none; }
.import-status.is-error { background: rgba(251, 113, 133, 0.14); color: #fecdd3; }
.import-status.is-ok { background: rgba(52, 211, 153, 0.14); color: #a7f3d0; }

.modal-actions { display: flex; gap: 9px; flex-wrap: wrap; }
.modal-actions .btn { flex: 1 1 auto; justify-content: center; height: 38px; }

/* ── Toast ──────────────────────────────────────────────────────────── */
.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translate(-50%, 14px);
  z-index: 200;
  padding: 11px 18px;
  border-radius: 11px;
  border: 1px solid var(--line-strong);
  background: rgba(20, 20, 30, 0.96);
  backdrop-filter: blur(12px);
  box-shadow: var(--shadow);
  font-size: 13.5px;
  opacity: 0;
  transition: opacity 0.22s, transform 0.22s;
  pointer-events: none;
}
.toast[hidden] { display: none; }
.toast.is-visible { opacity: 1; transform: translate(-50%, 0); }

/* ── Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 1080px) {
  .stats { grid-template-columns: 1fr 1fr; }
  .stats .stat:last-child { grid-column: 1 / -1; }
  .cat-list { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 820px) {
  .modal-shell { grid-template-columns: 1fr; gap: 20px; }
  .modal-art { max-width: 300px; margin: 0 auto; }
  .brand-text small { display: none; }
  .topbar-actions .btn span { display: none; }
  .topbar-actions .btn { padding: 0 10px; }
}

@media (max-width: 620px) {
  .page { padding: 16px 14px 60px; }
  .topbar-inner { padding: 0 14px; }
  .controls { position: static; margin: 0 -14px 16px; padding: 11px 14px; }
  /*
   * Keep the two headline figures side by side and shrink them hard. Stacked at
   * full desktop scale they filled the whole phone viewport, so the first thing
   * you saw in a card app was a screen with no cards on it. Side by side and
   * compact, the header costs about a third of what it did.
   */
  .stats { grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 14px; }
  .stats .stat:last-child { grid-column: 1 / -1; }
  .stat { padding: 11px 12px; }
  .stat-label { font-size: 9.5px; letter-spacing: 0.07em; }
  .stat-value b { font-size: 20px; }
  .stat-value i { font-size: 11px; }
  /* The percentage sentence restates the meter beside it; the meter is enough. */
  .stat footer { display: none; }
  /*
   * Inline chips rather than a two-column table. As rows this reference panel
   * cost ~290px of a phone screen — more than the two figures above it — to say
   * something you glance at, not read.
   */
  .cat-list { display: flex; flex-wrap: wrap; gap: 5px 12px; margin-top: 8px; }
  .cat-list li { font-size: 11.5px; gap: 5px; }
  .cat-list .cat-num { margin-left: 3px; font-size: 11px; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(136px, 1fr)); gap: 12px; }
  .meta { grid-template-columns: 1fr; }
  .tabs { width: 100%; }
  .tab { flex: 1; padding: 0 8px; }

  /*
   * Touch targets. 66 controls measured under the 44px guideline on a phone,
   * the worst being the filter-remove cross at 13x16 and the search clear at
   * 22x22 — both effectively un-tappable. Heights are raised outright; the tiny
   * crosses get a padded hit area instead of growing visually, so the layout is
   * unchanged and only the reachable region grows.
   */
  /* .btn sets an explicit height, which outranks min-height — so set height. */
  .btn, .collection-btn { height: 44px; }
  /* Icon-only up here, so width comes from padding alone. */
  .topbar-actions .btn { min-width: 44px; padding: 0 12px; }
  .tab { height: 40px; min-height: 40px; }
  .search input { min-height: 44px; }
  .search-clear {
    width: 40px; height: 40px;
    display: grid; place-items: center;
  }
  .token button, .active-filters button, .chip-x {
    min-width: 40px; min-height: 40px;
    display: inline-grid; place-items: center;
  }
  .mini-btn { min-height: 38px; }
  /* Added with the collector's-journal redesign, and missed by the sweep above:
     the quick filters measured ~31px and the card-size select 32px. The 420px
     query below trims their horizontal padding, which is fine once min-height
     governs the tappable height. .panel-action is the snapshot button. */
  .quick-status button { min-height: 44px; }
  .panel-action { min-height: 40px; }
  /* .gallery-display select is re-asserted at the end of this file — the
     redesign block overrides it from there. */
  /* Text links in the results bar are tap targets too. */
  .link-btn { min-height: 40px; display: inline-flex; align-items: center; }
  .row-link { min-height: 48px; }

  /*
   * The ownership toggle is the control you press most, and at 30px it was the
   * smallest thing on the screen. Grown to 40px with a transparent ring pushing
   * the hit area to 44, so the dot looks the same weight against the artwork
   * while being comfortably tappable.
   */
  .tile-own {
    width: 40px; height: 40px;
    bottom: 6px; right: 6px;
    outline: 2px solid transparent;
    outline-offset: 0;
  }
  .tile-own svg { width: 18px; height: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
  html { scroll-behavior: auto; }
}

/* Cost-to-complete range bar: shows there are two ends, not one number. */
.range-bar {
  height: 6px;
  margin: 12px 0 8px;
  border-radius: 99px;
  background: linear-gradient(90deg, var(--green), var(--amber) 55%, var(--danger));
  opacity: 0.75;
  position: relative;
}
.range-bar i {
  position: absolute;
  inset: 0;
  border-radius: 99px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}
.panel-hero h3 { font-variant-numeric: tabular-nums; }

/* ── Review mode ──────────────────────────────────────────────────────────
   Deliberately austere: one card, three verdicts, keyboard first. The point is
   to get through hundreds of cards without the eye having to hunt for controls.
*/
.modal-review { max-width: min(980px, calc(100vw - 24px)); width: 100%; }
.review-shell { display: flex; flex-direction: column; gap: 14px; padding: 18px; }

.review-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.review-count { margin: 0 0 6px; font-size: 12.5px; color: var(--faint); font-variant-numeric: tabular-nums; }
.review-scope { color: var(--muted); font-variant-numeric: normal; }
#reviewStart:disabled { opacity: 0.55; cursor: default; }
.review-bar { width: 220px; max-width: 40vw; height: 4px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.review-bar span { display: block; height: 100%; width: 0; background: var(--accent); transition: width 0.2s; }

.review-tally { display: flex; align-items: center; gap: 10px; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.review-tally-keep { color: #86efac; }
.review-tally-hide { color: #fda4af; }
.review-tally .modal-close { position: static; }

.review-body { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 20px; align-items: start; }
.review-img { width: 100%; border-radius: 12px; display: block; background: var(--surface-2); aspect-ratio: 734 / 1024; object-fit: cover; }
.review-meta h2 { margin: 0 0 4px; font-size: 20px; }
.review-bar-hint {
  margin: 14px 0 0; padding: 10px 12px; border-radius: 10px;
  background: var(--surface-2); color: var(--faint); font-size: 12.5px; line-height: 1.5;
}
.review-bar-hint em { color: var(--text); font-style: normal; font-weight: 600; }

.review-actions { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; }
.review-btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 14px; border-radius: 11px; border: 1px solid var(--line-strong);
  background: var(--surface-2); color: var(--text); font-size: 13.5px; font-weight: 500;
  cursor: pointer; transition: background 0.14s, border-color 0.14s, color 0.14s;
}
.review-key {
  display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: 5px; background: rgba(255, 255, 255, 0.09); font-size: 11.5px; color: var(--faint);
}
.review-btn-no:hover  { color: #fecdd3; border-color: rgba(251, 113, 133, 0.55); background: rgba(251, 113, 133, 0.14); }
.review-btn-yes:hover { color: #bbf7d0; border-color: rgba(74, 222, 128, 0.55); background: rgba(74, 222, 128, 0.14); }
.review-btn-skip { background: none; color: var(--faint); }
.review-btn-skip:hover { color: var(--text); background: var(--surface-2); }

.review-done { margin: 0; text-align: center; color: var(--faint); font-size: 13px; }
.review-done[hidden] { display: none; }

.btn-sm { margin-top: 8px; padding: 7px 11px; font-size: 12.5px; }

@media (max-width: 720px) {
  .review-body { grid-template-columns: 1fr; }
  .review-img { max-width: 260px; margin: 0 auto; }
  .review-actions { grid-template-columns: 1fr; }
}

/* Value-over-time: a sparkline and a signed delta. No chart library — one
   polyline reads fine at this size and keeps the page dependency-free. */
.spark { display: block; width: 100%; height: 44px; margin: 10px 0 4px; overflow: visible; }
.hero-line.is-up { color: #86efac; }
.hero-line.is-down { color: #fda4af; }
.hero-line small { display: block; margin-top: 3px; font-size: 12px; color: var(--faint); font-weight: 400; }
.row-figure.is-up { color: #86efac; }
.row-figure.is-down { color: #fda4af; }

/* ── Journal layout and gallery controls ────────────────────────────────
   Theme tokens live in :root above. These layout rules follow the legacy
   breakpoints intentionally; keep their order when changing responsive rules. */
:root {
  --bg: #0b1215;
  --bg-2: #101b20;
  --surface: rgba(192, 219, 218, .045);
  --surface-2: rgba(192, 219, 218, .08);
  --text: #f3f1e9;
  --muted: #a5b8ba;
  --faint: #8ea3a8;
  --accent: #5ed7bb;
  --accent-strong: #226e61;
  --accent-soft: rgba(94, 215, 187, .12);
  --cyan: #89bcca;
  --radius: 12px;
  --page-max: 1480px;
}
.aurora span { opacity: .12; }
.aurora span:nth-child(1) { background: #2a796c; }
.aurora span:nth-child(2) { background: #285b6a; opacity: .12; }
.aurora span:nth-child(3) { background: #665b34; opacity: .08; }
.topbar { background: rgba(11, 18, 21, .94); }
.brand-text small { color: var(--muted); }
.page { padding-top: 30px; }
.collection-hero { display: grid; grid-template-columns: 1.1fr 1fr; gap: 32px; align-items: center; margin-bottom: 28px; }
.eyebrow { color: #a8c7bc; font-size: 10px; letter-spacing: .17em; font-weight: 600; display: inline-flex; align-items: center; gap: 8px; }
.live-dot { width: 6px; height: 6px; background: var(--accent); border-radius: 50%; }
.hero-copy h2 { font-size: clamp(32px, 3.3vw, 47px); line-height: 1.08; letter-spacing: -.04em; font-weight: 500; margin: 14px 0 12px; }
.hero-copy h2 em { font-family: Georgia, serif; font-weight: 400; color: #cbd8bd; }
.hero-copy p { color: var(--muted); font-size: 14px; margin: 0 0 20px; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.hero-actions .btn { min-height: 42px; }
.hero-actions .btn-primary { color: #123d32; border-color: #bde9c9; }
.hero-actions .btn-primary:focus-visible { outline-color: var(--accent); }
.btn:disabled { opacity: .45; cursor: default; }
.hero-discovery { min-width: 0; min-height: 248px; display: flex; align-items: center; gap: 20px; padding: 26px 30px; border: 1px solid rgba(179, 209, 186, .19); border-radius: 20px; background: radial-gradient(ellipse at 95% 20%, rgba(149, 183, 108, .15), transparent 65%), #132024; overflow: hidden; }
.discovery-copy { flex: 1; min-width: 0; }
.discovery-copy h3 { font-family: Georgia, serif; font-size: 28px; font-weight: 400; line-height: 1.12; margin: 14px 0 9px; overflow-wrap: anywhere; }
.discovery-copy p { font-size: 13px; color: #bfcdc6; margin: 0 0 14px; }
.discovery-copy .link-btn { padding: 0; color: #bde9c9; font-size: 13px; text-align: left; }
.discovery-copy small { display: block; font-size: 10px; line-height: 1.6; color: var(--muted); margin-top: 14px; max-width: 290px; }
.chase-art { flex: 0 0 130px; aspect-ratio: 63 / 88; transform: rotate(8deg); border-radius: 8px; background: rgba(255, 255, 255, .03); box-shadow: 0 15px 35px #0008; }
.chase-art img { display: block; width: 100%; height: 100%; object-fit: contain; border-radius: 8px; }
.stats { align-items: stretch; gap: 0; border: 1px solid var(--line); border-radius: 14px; background: var(--surface); margin-bottom: 26px; }
.stat { border: none; background: none; border-radius: 0; padding: 18px 22px; }
.stat + .stat { border-left: 1px solid var(--line); }
.stat-wide { display: flex; flex-direction: column; justify-content: center; }
.meter-fill { background: #65bea5; }
.meter-fill.meter-cyan { background: #8db5cd; }
.controls { border-radius: 14px; }
.controls-row { gap: 14px; }
.search input { background: rgba(2, 10, 14, .35); }
.tabs { background: #101b20; }
.tab.is-active { background: #24473f; color: #d3f1df; box-shadow: none; }
.gallery-tools { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; padding-top: 16px; }
.quick-status { display: flex; gap: 5px; flex-wrap: wrap; }
.quick-status[hidden] { display: none; }
.quick-status button { border: 1px solid transparent; background: transparent; color: var(--muted); border-radius: 7px; padding: 7px 12px; cursor: pointer; font-size: 12px; }
.quick-status button:hover { background: var(--surface-2); color: var(--text); }
.quick-status button.is-active { background: var(--accent-soft); border-color: #427d6b; color: #bde9c9; }
.gallery-display { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.gallery-display label { font-size: 11px; color: var(--muted); }
.gallery-display select { font-size: 12px; padding: 6px 25px 6px 10px; min-height: 32px; }
.shortcut-hint { color: var(--faint); font-size: 11px; margin-right: 14px; }
kbd { border: 1px solid var(--line-strong); border-radius: 4px; padding: 1px 5px; font-family: 'DM Mono', monospace; }
.results-bar { padding-top: 14px; }
.grid { gap: 24px 20px; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); }
body[data-density="compact"] .grid { grid-template-columns: repeat(auto-fill, minmax(136px, 1fr)); gap: 18px 14px; }
body[data-density="large"] .grid { grid-template-columns: repeat(auto-fill, minmax(248px, 1fr)); gap: 28px; }
.tile-meta { padding-top: 11px; }
.tile:hover .tile-art { box-shadow: 0 18px 38px -14px #000c, 0 0 0 1px #5ed7bb77; }
.tile.is-owned .tile-art { box-shadow: 0 0 0 1px #6fc7a77a, var(--shadow); }
.tile-empty .tile-art { background: rgba(255, 255, 255, .015); border: 1px dashed var(--line-strong); box-shadow: none; }
@media (min-width: 1100px) { .cat-list { display: grid; grid-template-columns: 1fr 1fr; column-gap: 20px; } }
@media (max-width: 1000px) {
  .collection-hero { gap: 22px; grid-template-columns: 1fr 1fr; }
  .hero-discovery { padding: 22px; gap: 14px; }
  .chase-art { flex-basis: 100px; }
  .discovery-copy h3 { font-size: 23px; }
  .shortcut-hint { display: none; }
}
@media (max-width: 760px) {
  .collection-hero { grid-template-columns: 1fr; gap: 20px; }
  .hero-copy h2 br { display: none; }
  .hero-copy h2 { font-size: 34px; max-width: 500px; }
  .hero-copy h2 em::before { content: ' '; }
  .hero-discovery { min-height: 190px; }
  .chase-art { flex-basis: 96px; }
  .stat + .stat { border-left: 0; border-top: 1px solid var(--line); }
  .stats { grid-template-columns: 1fr; }
  .stat { padding: 14px 17px; }
  .stats .cat-list { display: grid; grid-template-columns: 1fr 1fr; column-gap: 24px; }
  .gallery-tools { gap: 12px; }
  .gallery-display { margin-left: 0; }
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 12px; }
  body[data-density="compact"] .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px 9px; }
  body[data-density="compact"] .tile-dex { display: none; }
  body[data-density="compact"] .tile-name { font-size: 12px; }
  body[data-density="compact"] .tile-sub { flex-wrap: wrap; }
  body[data-density="large"] .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 12px; }
}
@media (max-width: 420px) {
  body[data-density="large"] .grid { grid-template-columns: minmax(0, 1fr); }
  .hero-discovery { padding: 20px 16px; }
  .chase-art { flex-basis: 88px; }
  .quick-status button { padding: 7px 10px; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; animation-iteration-count: 1 !important; }
}
/* Keep primary actions and sticky chrome in the journal palette. */
.btn-primary { background: #226e61; box-shadow: 0 6px 20px -12px #5ed7bb66; }
.btn-primary:hover { background: #2a7f70; }
.hero-actions .btn-primary { background: #bde9c9; box-shadow: none; }
.hero-actions .btn-primary:hover { background: #d4f3dc; }
.controls { background: rgba(11, 18, 21, .96); }
.link-btn:hover { color: #c9f3e5; }
.search-clear[hidden], .pill-badge[hidden], .link-btn[hidden] { display: none; }

/* ── Snapshot-today, in the Value over time panel ──────────────────────────
   Price history cannot be backfilled, so a missed day is gone for good. The
   panel that shows the history is the one place the user is already thinking
   about it, which makes it the right place to offer the remedy.

   Styled after .price-refresh — the established pattern for a small action
   sitting inside a panel — rather than .btn, whose padding is wrong at this
   size. It carries its own spin rule because the .btn one is scoped to .btn. */
.panel { position: relative; }
.panel-action {
  position: absolute;
  top: 14px;
  right: 14px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  padding: 0 9px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--surface);
  color: var(--muted);
  font: inherit;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: color 0.16s, border-color 0.16s, background 0.16s;
}
.panel-action svg { width: 12px; height: 12px; }
.panel-action:hover:not(:disabled) {
  color: var(--text);
  border-color: var(--line-strong);
  background: var(--surface-2);
}
.panel-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.panel-action:disabled { opacity: 0.6; cursor: progress; }
.panel-action.is-busy svg { animation: spin 0.9s linear infinite; transform-origin: 50% 50%; }

/* The kicker sits to the left of the button, so keep the two from colliding on
   a narrow panel. */
.panel-action + h3, .panel-kicker { padding-right: 116px; }

@media (max-width: 560px) {
  .panel-action { position: static; margin: 8px 0 2px; }
  .panel-action + h3, .panel-kicker { padding-right: 0; }
}

/* ══ One touch target that has to live down here ═══════════════════════════
   The redesign appends its base layer at the end of this file, after the
   @media blocks above. `.gallery-display select { min-height: 32px }` therefore
   beats an equal-specificity rule in the touch-target block, so the card-size
   select stayed 32px on a phone — under the 44px guideline every other control
   follows. Re-asserted here, where it is later than the redesign.

   Nothing else needs re-asserting. The redesign carries its own complete
   responsive layer (1000/760/420px) plus its own prefers-reduced-motion block,
   which deliberately supersede the older breakpoints above — single-column
   .stats, a two-column .grid and a two-column .cat-list on a phone are its
   choices, not accidents. Verified by checking which rule actually wins at
   375px rather than by reading source order. */
@media (max-width: 620px) {
  .gallery-display select { min-height: 44px; }
}

/* Card open and ownership actions are sibling buttons, never nested controls. */
.tile-open { position: absolute; inset: 0; z-index: 1; border: 0; border-radius: var(--radius); padding: 0; background: transparent; cursor: pointer; }
.tile-open:focus-visible { outline-offset: 4px; }
.tile-own { z-index: 3; }
.save-status { color: var(--muted); display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
#retrySave[hidden] { display: none; }

/* ── Inventory editor ────────────────────────────────────────────────── */
.inventory-editor { margin: 18px 0; padding: 14px; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface); }
.inventory-editor summary { cursor: pointer; font-weight: 600; }
.inventory-editor summary span { color: var(--muted); font-size: 12px; margin-left: 8px; }
.inventory-editor p { color: var(--muted); font-size: 12px; line-height: 1.5; }
.inventory-row { display: grid; grid-template-columns: 72px minmax(110px, 1fr) minmax(110px, 1fr) auto; gap: 8px; align-items: end; margin-bottom: 12px; }
.inventory-row label { min-width: 0; color: var(--muted); font-size: 11px; }
.inventory-row input, .inventory-row select { width: 100%; min-height: 40px; border: 1px solid var(--line-strong); border-radius: 6px; background: var(--bg-2); padding: 6px; color: var(--text); }
.inventory-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.inventory-remove { min-height: 40px; }
.tile-count { color: var(--accent); white-space: nowrap; font-family: 'DM Mono', monospace; }
@media (max-width: 620px) {
  .inventory-row { grid-template-columns: 64px minmax(0, 1fr); }
  .inventory-row label:nth-child(3) { grid-column: 1 / -1; }
  .inventory-remove { grid-column: 1 / -1; }
}

/* ── Missing-entry checklist ──────────────────────────────────────────────
   Fallback surface for when a pop-up blocker refuses the checklist tab. The
   page itself lives in the iframe with its own stylesheet, so nothing here
   styles its contents — only the frame around it. */
.checklist-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  background: var(--bg, #0f1714);
}
.checklist-overlay-bar {
  flex: none;
  display: flex;
  justify-content: flex-end;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line, #2a3a33);
}
.checklist-overlay iframe {
  flex: 1 1 auto;
  width: 100%;
  border: 0;
}
/* Cmd+P on the app while the checklist is up should print the checklist. */
@media print {
  body.has-checklist > *:not(.checklist-overlay) { display: none !important; }
  body.has-checklist .checklist-overlay { position: static; }
  body.has-checklist .checklist-overlay-bar { display: none; }
}

/* ── Export menu ──────────────────────────────────────────────────────── */
.export-wrap { position: relative; }
.export-menu { left: auto; right: 0; min-width: 300px; }
.export-option {
  display: block;
  width: 100%;
  padding: 9px 11px;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.export-option:hover, .export-option:focus-visible { background: var(--surface-2); }
.export-option-name { display: block; font-weight: 600; }
.export-option-sub {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--muted);
}

/* ── Collection templates ──────────────────────────────────────────────
   Example shapes to start a collection from. Rules only, so a template can
   ship publicly where a personal hidden list cannot. */
.template-list { display: grid; gap: 8px; }
.template-card {
  display: flex; gap: 12px; align-items: flex-start; width: 100%;
  padding: 10px 12px; text-align: left; cursor: pointer;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); color: inherit; font: inherit;
}
.template-card:hover { border-color: var(--line-strong); background: var(--surface-2); }
.template-card.is-on { border-color: var(--accent); background: var(--accent-soft); }
.template-icon { font-size: 20px; line-height: 1.2; }
.template-text { display: grid; gap: 2px; }
.template-text strong { font-weight: 600; }
.template-text span { color: var(--muted); font-size: 12px; line-height: 1.4; }
.template-note { color: var(--faint); font-size: 11px; }
.template-row { display: flex; gap: 8px; align-items: stretch; }
.template-row .template-card { flex: 1; }
.template-by { color: var(--accent); font-size: 11px; }
.template-vote {
  flex: 0 0 auto; padding: 0 12px; cursor: pointer; font: inherit; font-size: 12px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--muted); white-space: nowrap;
}
.template-vote:hover { border-color: var(--line-strong); color: var(--text); }
.template-vote.is-on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.form-note { color: var(--faint); font-size: 11px; margin: 6px 0 0; }

/* ── Picking cards by hand ─────────────────────────────────────────────
   Not every collection is a query. These are the ones chosen one at a time. */
.pick-results { display: grid; gap: 4px; max-height: 240px; overflow-y: auto; margin: 8px 0; }
.pick-row {
  display: grid; grid-template-columns: 1fr auto; gap: 2px 12px; align-items: center;
  width: 100%; padding: 8px 10px; text-align: left; cursor: pointer; font: inherit;
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px; color: inherit;
}
.pick-row:hover { border-color: var(--line-strong); }
.pick-row.is-on { border-color: var(--accent); background: var(--accent-soft); }
.pick-name { font-weight: 600; }
.pick-meta { grid-column: 1; color: var(--muted); font-size: 12px; }
.pick-mark { grid-row: 1 / span 2; color: var(--accent); font-size: 12px; white-space: nowrap; }
.year-range { display: flex; align-items: center; gap: 6px; }
.year-range input { width: 5.5em; }

/* ── Overflow menu ─────────────────────────────────────────────────────
   Privacy, Contact, Cloud backups and "a card is missing" lived only in the
   footer, which on a 20,759-card grid is eight screens down. They are
   site-wide links; they need to be reachable from the top. */
.more-wrap { position: relative; }
.more-menu { right: 0; left: auto; min-width: 230px; }
.more-menu a, .more-menu button {
  display: block; width: 100%; padding: 9px 11px; text-align: left;
  font: inherit; font-size: 13.5px; color: var(--text); text-decoration: none;
  background: none; border: 0; border-radius: 9px; cursor: pointer;
}
.more-menu a:hover, .more-menu button:hover { background: var(--surface-2); }
.more-menu hr { margin: 6px 4px; border: 0; border-top: 1px solid var(--line); }

/* The one action a signed-out visitor needs. .btn-primary is the same green as
   Sync, so using it put two identical buttons at opposite ends of the bar and
   the account action read as a second sync. The bright accent with dark text
   reads as primary without competing. */
.sign-in {
  background: var(--accent);
  border-color: var(--accent);
  color: #0b1215;
  font-weight: 700;
}
.sign-in:hover { background: #7ee6cd; border-color: #7ee6cd; }
