:root {
  --bg: #f7f7f9;
  --panel-bg: #ffffff;
  --text: #1a1a1e;
  --muted: #666672;
  --border: #dcdce2;
  --accent: #4a5fd6;
  --accent-text: #ffffff;
  --error: #c53030;
  --warning-bg: #fff6e0;
  --warning-border: #e8c15a;
  --input-bg: #fbfbfd;
  --hover-bg: #eef0fb;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #17171c;
    --panel-bg: #212127;
    --text: #eaeaf0;
    --muted: #9a9aa8;
    --border: #34343d;
    --accent: #7b8cf5;
    --accent-text: #12121a;
    --error: #ff8686;
    --warning-bg: #2c2612;
    --warning-border: #6b5a1f;
    --input-bg: #17171c;
    --hover-bg: #2a2a35;
  }
}

* {
  box-sizing: border-box;
}

a {
  color: var(--accent);
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.45;
}

header {
  padding: 2rem 1.5rem 1rem;
  max-width: 1100px;
  margin: 0 auto;
  position: relative;
}

.header-actions {
  position: absolute;
  top: 2rem;
  right: 1.5rem;
  display: flex;
  gap: 0.5rem;
}

h1 {
  margin: 0 0 0.25rem;
  font-size: 1.6rem;
}

.subtitle {
  color: var(--muted);
  margin: 0;
}

main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 1.5rem;
}

.panel {
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.25rem;
}

.panel h2 {
  margin-top: 0;
  font-size: 1.1rem;
}

.editor {
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
}

.hint {
  color: var(--muted);
  font-size: 0.9rem;
}

.hint.warning {
  background: var(--warning-bg);
  border: 1px solid var(--warning-border);
  border-radius: 8px;
  padding: 0.6rem 0.9rem;
  color: var(--text);
}

.upload-columns {
  display: flex;
  gap: 1.5rem;
  align-items: flex-start;
  margin-bottom: 0.75rem;
}

.upload-column {
  flex: 1;
  min-width: 0;
}

.upload-column h3 {
  margin: 0 0 0.25rem;
  font-size: 0.95rem;
}

@media (max-width: 700px) {
  .upload-columns {
    flex-direction: column;
  }
}

.drop-zone {
  border: 2px dashed var(--border);
  border-radius: 10px;
  padding: 2rem 1rem;
  text-align: center;
  color: var(--muted);
  cursor: pointer;
  margin: 0.75rem 0;
}

.drop-zone:hover,
.drop-zone:focus-visible {
  border-color: var(--accent);
  color: var(--text);
}

.drop-zone.dragover {
  border-color: var(--accent);
  background: var(--hover-bg);
  color: var(--text);
}

/* Once a file is loaded, the zone itself shows it (see .loaded-files below)
   instead of the "drag a file here" placeholder - dropping another file
   still works the same way (still the same element/listeners), it just
   replaces what's shown instead of appending below an unchanged placeholder. */
.drop-zone.has-files {
  padding: 0.75rem;
  text-align: left;
}

.drop-zone.has-files .drop-zone-placeholder {
  display: none;
}

.loaded-files {
  display: none;
  flex-direction: column;
  gap: 0.4rem;
}

.drop-zone.has-files .loaded-files {
  display: flex;
}

.loaded-file {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.7rem;
  font-size: 0.85rem;
}

.loaded-file button {
  padding: 0.2rem 0.6rem;
  font-size: 0.8rem;
}

.file-row {
  display: flex;
  align-items: flex-end;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}

.file-row label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.85rem;
  color: var(--muted);
}

/* Seed finder page */
.slider-field {
  grid-column: 1 / -1;
  max-width: 48rem;
}

.slider-field label {
  font-size: 0.85rem;
  color: var(--muted);
  display: block;
  margin-bottom: 0.4rem;
}

.slider-field input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
}

.search-buttons {
  display: flex;
  gap: 0.75rem;
  margin: 1rem 0;
}

.progress-readout progress {
  width: 100%;
  height: 0.6rem;
  accent-color: var(--accent);
}

.result-seed {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1.2rem;
  color: var(--accent);
}

input[type="text"],
input[type="number"] {
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.6rem;
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9rem;
}

button {
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 6px;
  padding: 0.5rem 1rem;
  font-size: 0.9rem;
  cursor: pointer;
}

button:hover {
  filter: brightness(1.08);
}

button.secondary {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}
button.secondary.danger:hover { background: var(--error); color: #fff; border-color: var(--error); }

.error {
  color: var(--error);
  font-size: 0.85rem;
  min-height: 1.2em;
}

/* Horizontal character tabs */
.char-tabs {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.25rem;
  padding-bottom: 0;
}

.char-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--muted);
  padding: 0.5rem 0.9rem;
  font-size: 0.9rem;
  cursor: pointer;
}

.char-tab.active {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.char-tab.empty {
  font-style: italic;
}

/* Vertical section tabs + content */
.editor-body {
  display: flex;
  gap: 1.5rem;
  align-items: flex-start;
}

.vertical-tabs {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  flex: 0 0 140px;
}

.vtab {
  background: none;
  border: none;
  border-left: 2px solid transparent;
  border-radius: 0;
  text-align: left;
  color: var(--muted);
  padding: 0.5rem 0.8rem;
  font-size: 0.9rem;
  cursor: pointer;
}

.vtab.active {
  color: var(--text);
  border-left-color: var(--accent);
  background: var(--hover-bg);
}

.section-content {
  flex: 1;
  min-width: 0;
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.field label {
  font-size: 0.8rem;
  color: var(--muted);
}

.field select {
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.5rem;
  color: var(--text);
}

fieldset {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 1rem;
}

legend {
  padding: 0 0.4rem;
  font-size: 0.9rem;
  color: var(--muted);
}

table.items {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.82rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

table.items th,
table.items td {
  border-bottom: 1px solid var(--border);
  padding: 0.3rem 0.4rem;
  text-align: left;
  vertical-align: middle;
}

table.items input[type="text"],
table.items input[type="number"] {
  width: 100%;
  padding: 0.2rem 0.4rem;
  font-size: 0.8rem;
}

table.items td.item-details-display {
  color: var(--muted);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 0.8rem;
  white-space: normal;
  min-width: 10em;
}

table.items input[type="checkbox"] {
  transform: scale(1.1);
}

/* Amount inputs (inventory tool stacks, bank item counts): fixed width
   (roughly 5 digits) instead of stretching to fill the column. */
table.items input.amount-input {
  width: 5.5em;
}

.add-item-button {
  margin-top: 0.75rem;
}

/* Item cell (just the item name; edit/delete live in .row-actions) */
.item-search-cell {
  min-width: 12em;
}

.item-name-display {
  display: block;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 0.85rem;
}

/* Edit/delete icon buttons at the start of each inventory/bank row */
.row-actions {
  display: flex;
  gap: 0.3rem;
  white-space: nowrap;
}

.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.25rem;
  cursor: pointer;
}

.icon-button:hover:not(:disabled) {
  color: var(--text);
  border-color: var(--accent);
  background: var(--hover-bg);
}

.icon-button:disabled {
  opacity: 0.4;
  cursor: default;
}

.status {
  font-size: 0.85rem;
  color: var(--muted);
}

/* Item editor sheet (shared by mag/weapon/armor/unit/tool sections) */
dialog.item-dialog {
  background: var(--panel-bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
  max-width: 34rem;
  width: 92vw;
  max-height: 85vh;
  overflow-y: auto;
}

dialog.item-dialog::backdrop {
  background: rgba(0, 0, 0, 0.4);
}

dialog.item-dialog h2 {
  margin-top: 0;
  font-size: 1.1rem;
}

.item-dialog-current {
  font-size: 0.95rem;
  margin: -0.5rem 0 1rem;
}

.dialog-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.8rem;
  color: var(--muted);
}

.dialog-field-checkbox {
  flex-direction: row;
  align-items: center;
  gap: 0.4rem;
}

.mag-level-display {
  display: block;
  font-size: 0.85rem;
  color: var(--muted);
  margin: -0.5rem 0 1rem;
}

.mag-level-display.over-cap {
  color: var(--error);
}

.dialog-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-top: 0.5rem;
}

/* Item picker (inside the item editor dialog) */
.item-picker-search {
  width: 100%;
  margin-bottom: 0.5rem;
}

.item-category-tabs {
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}

.item-category-tab {
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  font-size: 0.78rem;
  cursor: pointer;
}

.item-category-tab.active {
  border-color: var(--accent);
  color: var(--accent);
}

.item-picker-results {
  max-height: 12rem;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.3rem 0.5rem;
}

.item-picker-group-header {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  margin: 0.5rem 0 0.2rem;
}

.item-picker-result {
  padding: 0.3rem 0.4rem;
  font-size: 0.85rem;
  cursor: pointer;
  border-radius: 6px;
}

.item-picker-result:hover {
  background: var(--hover-bg);
}

.item-picker-empty {
  color: var(--muted);
  font-size: 0.85rem;
  padding: 0.4rem;
}

/* ---------------- Episode III card browser ----------------
   Card artwork is optional (extracted from a disc, never shipped), so every
   image rule has to look sane with the picture missing - hence the .missing
   fallback rather than relying on the image to size anything. */

/* This page lays cards out in grids and wants the whole window, unlike the
   form-shaped pages the shared max-width was written for. */
.ep3-page header,
.ep3-page main {
  max-width: none;
  width: 100%;
}
.ep3-page .editor-body { align-items: flex-start; }
.ep3-page .section-content { min-width: 0; }

.filter-bar {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
}
.filter-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.filter-label {
  min-width: 3.2rem;
  font-size: 0.8rem;
  color: var(--muted);
}
.filter-search { flex: 1 1 14rem; min-width: 0; }
.chips { display: flex; flex-wrap: wrap; gap: 0.25rem; }
.chip {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.16rem 0.6rem;
  font-size: 0.88rem;
  cursor: pointer;
}
.chip.on {
  background: var(--accent);
  color: var(--accent-text);
  border-color: var(--accent);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 0.55rem;
  margin-top: 0.6rem;
}
.card-cell {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.35rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
/* Cards the player doesn't hold stay visible but read as absent. */
.card-cell.unowned { opacity: 0.4; }
.card-cell.unowned .card-art-img { filter: grayscale(1); }

.card-tile {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  text-align: center;
  width: 100%;
}
.card-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.card-tile-action {
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--hover-bg);
  color: inherit;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.2rem 0;
  cursor: pointer;
}
.card-tile-action:hover { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }
.card-tile-action.remove:hover { background: var(--error); color: #fff; border-color: var(--error); }
.card-tile-action:disabled { opacity: 0.4; cursor: not-allowed; }
.card-tile-action:disabled:hover { background: var(--hover-bg); color: inherit; border-color: var(--border); }

/* The art, with rank and cost overlaid on it the way the game does. */
.card-art {
  position: relative;
  width: 100%;
  aspect-ratio: 128 / 100;
  background: rgba(0, 0, 0, 0.35);
  border-radius: 5px;
  overflow: hidden;
}
.card-art-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.card-art-img.missing { visibility: hidden; }
.card-rank {
  position: absolute;
  top: 2px;
  right: 2px;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 3px;
  background: rgba(8, 14, 24, 0.85);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.35);
}
.card-slot-badge {
  position: absolute;
  top: 2px;
  left: 2px;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 3px;
  background: var(--accent);
  color: var(--accent-text);
}
.cost-pips {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  justify-content: center;
  gap: 3px;
  padding: 2px 0;
  background: linear-gradient(to top, rgba(6, 10, 18, 0.88), rgba(6, 10, 18, 0));
}
.pip {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #ffd34d;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6);
}
.pip-zero { font-size: 0.6rem; color: var(--muted); line-height: 1; }

.card-tile-name {
  font-size: 0.76rem;
  line-height: 1.15;
  /* Card names run long ("Pofuilly Slime +"); two lines beats an ellipsis. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 1.8em;
}
.card-tile-count { font-size: 0.72rem; color: var(--muted); }

/* HP/AP/TP/MV under the tile, the same four boxes as the detail overlay's
   stat panel at a scale that fits a ~132px grid tile. */
.tile-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
}
.tile-stat {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2px;
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 1px 3px;
  font-size: 1rem;
  line-height: 1.3;
}
.tile-stat-key { color: var(--muted); font-weight: 600; }
.tile-stat-val { font-variant-numeric: tabular-nums; }

.card-cell-controls { display: flex; justify-content: center; align-items: center; gap: 0.35rem; }
.qty-label { font-size: 0.75rem; color: var(--muted); }
.count-input { font-size: 0.8rem; padding: 0.15rem 0.3rem; width: 3.6rem; }

/* Decks: selected deck in the middle, the character's own cards on the right,
   with the page's existing left nav making the third column. */
.deck-columns {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
  gap: 1.25rem;
  align-items: start;
}
.deck-col, .avail-col { min-width: 0; }
.avail-col {
  border-left: 1px solid var(--border);
  padding-left: 1rem;
}
.avail-grid { grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); }
@media (max-width: 1100px) {
  .deck-columns { grid-template-columns: 1fr; }
  .avail-col { border-left: none; padding-left: 0; border-top: 1px solid var(--border); padding-top: 1rem; }
}

.deck-chooser { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
/* .deck-chooser .secondary { margin-left: auto; } */
.deck-head h3 { margin-bottom: 0.15rem; }
.deck-head-title-row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.vtab-action { margin-top: 0.75rem; width: 100%; }

.new-deck-form { display: flex; flex-direction: column; gap: 0.75rem; min-width: 16rem; }
.dialog-actions { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 0.25rem; }

/* Deck composition: a type bar with a sub-type bar fused directly beneath
   it, plus a cost bar in the same style, read from the deck's own 30 non-SC
   cards. */
.deck-stats {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.6rem 0 1rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--hover-bg);
}
.deck-stats-label { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); margin: 0.5rem 0 0; }
.deck-stats-label:first-child { margin-top: 0; }

.comp-bar {
  display: flex;
  height: 1.6rem;
  overflow: hidden;
  background: var(--border);
}
/* Two bars with no gap between them read as one connected shape: rounded
   only on the outside edges, with a hairline seam where they meet. */
.comp-bars { 
  display: flex; 
  flex-direction: column; 
}
.comp-bars, .cost-bar {
  border-radius: 6px;
  border: 1px solid black;
  background: black;
}
.comp-bar-type { border-radius: 6px 6px 0 0; }
.comp-bar-class { border-radius: 0 0 6px 6px; }
.cost-bar { border-radius: 6px; }
.comp-seg {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
/* A hard line between e.g. weapon and action - the colours already tell
   them apart, but a boundary reads faster than a colour change alone. On
   the sub-type bar this only belongs at a type boundary (Mag | Attack),
   not between every sub-type (Sword | Mag are both still Weapon) - JS
   marks the last sub-type segment of each type with .comp-seg-type-end. */
.comp-bar-type .comp-seg:not(:last-child),
.comp-bar-class .comp-seg.comp-seg-type-end:not(:last-child) { border-right: 1px solid #000; }
.comp-seg-label {
  padding: 0 4px;
  font-size: 0.7rem;
  font-weight: 600;
  color: #000;
  text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.55);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;
}

.cost-block { display: flex; flex-direction: column; gap: 0.4rem; }

/* Deck body cards (not the fixed SC slot) are drag-reorderable. */
.deck-grid .card-cell[draggable="true"] { cursor: grab; }
.deck-grid .card-cell.dragging { opacity: 0.4; }
/* Marks where the dragged card will land if dropped now - an empty slot
   rather than a highlighted existing card, so it reads as "a gap opens
   here" instead of "this card is the target". */
.drag-placeholder {
  border: 2px dashed var(--accent);
  border-radius: 8px;
  background: var(--hover-bg);
}

/* ---------------- dialogs ---------------- */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.72);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  z-index: 50;
}
.modal {
  position: relative;
  background: var(--panel, #12161c);
  border: 1px solid var(--border);
  border-radius: 10px;
  max-width: 900px;
  width: 100%;
  max-height: 88vh;
  /* The frame stays put and .modal-body scrolls inside it, so the close
     button keeps its corner instead of sliding away over the content. */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal-header {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.7rem 0.7rem 0.7rem 1.25rem;
  border-bottom: 1px solid var(--border);
}
.modal-heading { display: flex; align-items: baseline; gap: 0.6rem; min-width: 0; flex-wrap: wrap; }
.modal-subtitle { font-size: 0.8rem; color: var(--muted); }
.modal-title {
  margin: 0;
  font-size: 1.05rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.modal-body {
  padding: 1.25rem;
  overflow: auto;
  min-height: 0;
}
.modal-image { max-width: min(92vw, 780px); }
.modal-image .modal-body { text-align: center; }
.modal-close {
  flex: none;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 2rem;
  height: 2rem;
  padding: 0;
  font-size: 1.1rem;
  cursor: pointer;
  /* The theme letter-spaces every button, which offsets a single glyph inside
     a fixed-size box; centring explicitly keeps the x in the middle. */
  letter-spacing: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* Card detail: art down the left column, everything else on the right. */
.card-detail-top {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
}
.card-detail-figure { display: flex; flex-direction: column; gap: 0.4rem; align-items: flex-start; }
.card-detail-img {
  width: 100%;
  border-radius: 8px;
  cursor: zoom-in;
  display: block;
}
.card-detail-img.missing { display: none; }
.card-detail-right { min-width: 0; }
/* "View full size" has to mean exactly that: the art at its own resolution,
   with the dialog scrolling when the window is too small to show all of it.
   Capping the height to a fraction of the viewport silently rendered a
   512x400 card at 414x323 on a short window - smaller than the source. */
.card-full { display: block; margin: 0 auto; max-width: none; max-height: none; }
.card-full.missing { display: none; }
.card-facts { display: grid; grid-template-columns: auto 1fr; gap: 0.2rem 0.75rem; margin: 0; font-size: 0.85rem; }
.card-facts dt { color: var(--muted); }
.card-facts dd { margin: 0; }
.card-flavour {
  font-size: 0.88rem;
  margin: 1em 0;
}

.rank-box { margin-top: 0.9rem; }
.rank-row { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.rank-pill {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.1rem 0.6rem;
  font-size: 0.8rem;
}
.rank-pill.changed { border-color: var(--accent); color: var(--accent); }

.ability-list { display: flex; flex-direction: column; gap: 0.6rem; }
.ability-item { border-left: 2px solid var(--border); padding-left: 0.6rem; }
.ability-name { font-weight: 600; }
.ability-desc, .glossary-desc { margin: 0.15rem 0 0; font-size: 0.85rem; color: var(--muted); }
.tag-restriction {
  font-size: 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 0.4rem;
  margin-left: 0.4rem;
  color: var(--muted);
}
.tag-varies {
  font-size: 0.7rem;
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 0 0.4rem;
  margin-left: 0.4rem;
  color: var(--accent);
}
/* Each card's own wording for a varying ability, shown under its tile in the
   "which cards have this" overlay so the actual per-card number is visible
   rather than only the glossary's single representative text. */
.ability-card-cell { display: flex; flex-direction: column; gap: 0.3rem; }
.ability-card-own-text { margin: 0; font-size: 0.75rem; color: var(--muted); }
.linklike {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  cursor: pointer;
  font: inherit;
  text-decoration: underline;
}
.glossary-list { display: flex; flex-direction: column; gap: 0.7rem; margin-top: 0.6rem; }
.glossary-item { border-left: 2px solid var(--border); padding-left: 0.6rem; }
.glossary-item.focused { border-left-color: var(--accent); }
.glossary-name { font-weight: 600; }

/* ---------------- card detail: the game-style card panel ---------------- */

/* The card drawn the way the game draws it: name bar, cost pips, art framed
   by its connection colours, HP/AP/TP/MV panel across the bottom. */

/* The nine connection colours, named as the card table names them. */
.game-card {
  --cardcolor-blue: #2f6ed8;
  --cardcolor-red: #cf3030;
  --cardcolor-yellow: #e0c22a;
  --cardcolor-orange: #e08a1e;
  --cardcolor-purple: #8a4fd0;
  --cardcolor-green: #3fa845;
  --cardcolor-brown: #8a5a34;
  --cardcolor-gray: #8a8f96;
  --cardcolor-white: #e6e9ee;

  width: 100%;
  background: linear-gradient(#2c3a33, #1b241f);
  border: 2px solid #4d6b57;
  border-radius: 6px;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.game-card-head {
  display: flex;
  align-items: center;
  gap: 6px;
  background: linear-gradient(#6f9a72, #3f6147);
  border: 1px solid #7fae83;
  border-radius: 3px;
  padding: 2px 4px;
}
.game-card-rank {
  flex: none;
  min-width: 1.7rem;
  text-align: center;
  background: #16201a;
  border: 1px solid #7fae83;
  border-radius: 2px;
  font-size: 0.7rem;
  font-weight: 700;
  color: #d8ecd9;
  padding: 1px 3px;
}
.game-card-name {
  font-weight: 700;
  font-size: 0.95rem;
  color: #f2f7f2;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.game-card-cost { display: flex; justify-content: flex-end; gap: 4px; padding: 0 2px; }
.gc-pip {
  width: 0.8rem;
  height: 0.8rem;
  border-radius: 50%;
  background: #16201a;
  border: 1px solid #4d6b57;
}
.gc-pip.lit { background: var(--cardcolor-yellow); border-color: #f6e08a; }

.game-card-body { display: flex; gap: 3px; align-items: stretch; }
.game-card-art {
  flex: 1;
  min-width: 0;
  background: #0d1310;
  border: 1px solid #4d6b57;
  border-radius: 2px;
  display: flex;
}
.game-card-img { width: 100%; height: auto; display: block; cursor: zoom-in; }
.game-card-img.missing { display: none; }
/* Edge strips keep their width even when a card has no colours on that side,
   so the art stays centred and cards line up with each other. */
.game-card-edge {
  flex: none;
  width: 0.62rem;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.edge-chip {
  flex: 1;
  min-height: 0.62rem;
  border: 1px solid rgba(0, 0, 0, 0.55);
  border-radius: 2px;
  padding: 0;
}
button.edge-chip { cursor: pointer; }
button.edge-chip:hover, button.edge-chip:focus-visible {
  outline: 2px solid #f2f7f2;
  outline-offset: 1px;
}
.game-card-art { flex-direction: column; gap: 2px; padding: 2px; position: relative; }
/* The range grid reads as part of the card, sitting over the art the way the
   cost pips do rather than as a separate diagram below it. */
.range-overlay {
  position: absolute;
  right: 5px;
  bottom: 5px;
  background: rgba(6, 10, 8, 0.72);
  border: 1px solid rgba(127, 174, 131, 0.6);
  border-radius: 3px;
  padding: 3px;
}
.range-overlay .range-grid {
  /* Same footprint as before, tighter gap traded for bigger cells so a solid
     block of hits reads as solid instead of a row of separated dots. */
  --range-cell: 0.56rem;
  --range-gap: 1px;
}
.range-overlay .range-cell {
  border-color: rgba(159, 191, 164, 0.45);
}
.game-card-top { display: flex; gap: 3px; }
.game-card-top .edge-chip { flex: 1; height: 0.4rem; }

.game-card-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3px;
}
.gc-stat {
  display: flex;
  align-items: stretch;
  border: 1px solid #4d6b57;
  border-radius: 2px;
  overflow: hidden;
  min-height: 1.9rem;
}
.gc-stat-key {
  flex: none;
  padding: 1px 5px;
  background: #16201a;
  color: #9fbfa4;
  font-size: 0.72rem;
  font-weight: 700;
  display: flex;
  align-items: center;
}
.gc-stat-val {
  flex: 1;
  padding: 1px 6px;
  background: #24322a;
  color: #f2f7f2;
  font-size: 1.25rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

/* Cell size and gap are one CSS variable each, shared by the grid's own
   track width and by every cell's box size, so they can't drift apart the way
   they did when the two were set independently: a cell smaller than its track
   left dead space at the end of every row, which is what read as gaps in a
   supposedly solid block. */
.range-grid {
  --range-cell: 0.9rem;
  --range-gap: 2px;
  display: grid;
  grid-template-columns: repeat(var(--range-cols, 5), var(--range-cell));
  gap: var(--range-gap);
}
.range-cell {
  width: var(--range-cell);
  height: var(--range-cell);
  border: 1px solid var(--border);
  border-radius: 2px;
}
.range-cell.hit { background: var(--accent); border-color: var(--accent); }
.range-cell.origin { background: var(--text); border-color: var(--text); }
.card-caps { margin: 0; font-size: 0.75rem; color: var(--muted); }

/* Heading with an action sitting beside it, e.g. Abilities + glossary. */
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.9rem;
}
h4 {
  margin: 1em 0;
}
.section-head h4 { margin: 0; }
.btn-small { font-size: 0.75rem; padding: 0.2rem 0.5rem; }

/* Boss/unused cards, kept out of the main collection grid. */
.boss-section {
  margin-top: 1.5rem;
  border-top: 1px solid var(--border);
  padding-top: 0.75rem;
}
.boss-section > summary {
  cursor: pointer;
  font-weight: 600;
  margin-bottom: 0.35rem;
}

/* Colour swatch used on the "chains on" filter chips and the chain dialog. */
.chip-swatch {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 2px;
  border: 1px solid rgba(0, 0, 0, 0.5);
  margin-right: 0.3rem;
  vertical-align: -1px;
}
.chip-swatch.big { width: 0.85rem; height: 0.85rem; vertical-align: -2px; }

/* The connection colours again, at document scope, so the filter chips and
   the chain dialog can use them outside a .game-card. */
:root {
  --cardcolor-blue: #2f6ed8;
  --cardcolor-red: #cf3030;
  --cardcolor-yellow: #e0c22a;
  --cardcolor-orange: #e08a1e;
  --cardcolor-purple: #8a4fd0;
  --cardcolor-green: #3fa845;
  --cardcolor-brown: #8a5a34;
  --cardcolor-gray: #8a8f96;
  --cardcolor-white: #e6e9ee;
}

/* The game deletes decks that fail its own validation, so a collection edit
   that breaks one has to be visible before the save is downloaded. */
.deck-warning {
  border: 1px solid var(--accent);
  border-left-width: 3px;
  border-radius: 6px;
  padding: 0.6rem 0.8rem;
  margin: 0.6rem 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: flex-start;
}
.deck-warning[hidden] { display: none; }
.deck-warning-head { margin: 0; font-weight: 600; color: var(--accent); }
.deck-warning-list { margin: 0; padding-left: 1.1rem; font-size: 0.85rem; }
.deck-warning-list li { margin: 0.1rem 0; }

.glossary-name { display: flex; align-items: baseline; gap: 0.45rem; flex-wrap: wrap; }
.glossary-count { font-size: 0.72rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* "Give [n] of each shown" reads as one instruction, so the quantity sits
   inside the control rather than beside it. */
.bulk-give {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  user-select: none;
  /* Matches button.secondary: a <select> can't sit inside a <button>, so the
     group borrows the styling rather than inheriting it. */
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.5rem 1rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9rem;
  line-height: 1;
}
.bulk-give:hover { filter: brightness(1.08); }
.bulk-give:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bulk-give select {
  cursor: pointer;
  font-size: 0.85rem;
  padding: 0 0.2rem;
  line-height: 1.1;
}


/* ---------------- ep3-ranges.html: the range reference page ---------------- */

.range-group {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  margin-top: 0.8rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
.range-group-head { display: flex; align-items: flex-start; gap: 1.1rem; flex-wrap: wrap; }
.ranges-page-grid { --range-cell: 1.15rem; --range-gap: 3px; flex: none; }
.range-grid-none {
  flex: none;
  width: calc(5 * 1.15rem + 4 * 3px);
  height: calc(6 * 1.15rem + 5 * 3px);
  border: 1px dashed var(--border);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 0.75rem;
  text-align: center;
  padding: 0.3rem;
}
.range-group-info { min-width: 0; flex: 1 1 16rem; }
.range-group-count { margin: 0 0 0.15rem; font-weight: 600; }

.range-examples { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.range-example {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  width: 6.5rem;
  text-align: center;
}
.range-example-img { width: 100%; border-radius: 6px; }
.range-example-name { font-size: 0.78rem; }
.range-example-hits { font-size: 0.68rem; color: var(--muted); }

#download-button {
  margin-top: 2em;
}