:root {
  color-scheme: light dark;
  --bg: #0f1216;
  --card-bg: #1a1f27;
  --fg: #e6e9ef;
  --muted: #9aa4b2;
  --accent: #4f8cff;
  --danger: #e5484d;
  --warn: #f0a30a;
  --up: #2ecc71;
  --down: #888;
  --border: #2a3038;
  --row-alt: rgba(255, 255, 255, 0.022);
  --row-hover: rgba(79, 140, 255, 0.09);
}
@media (prefers-color-scheme: light) {
  :root {
    --bg: #f4f6f9;
    --card-bg: #ffffff;
    --fg: #171a1f;
    --muted: #5b6470;
    --warn: #9a6700;
    --border: #dde2e8;
    --row-alt: rgba(0, 0, 0, 0.018);
    --row-hover: rgba(79, 140, 255, 0.08);
  }
}
* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--fg);
}
header {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0.75rem 1.5rem;
  background: var(--card-bg);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.brand { font-weight: 700; }
nav { display: flex; gap: 0.25rem; flex-wrap: wrap; }
nav a {
  color: var(--muted);
  text-decoration: none;
  padding: 0.4rem 0.7rem;
  border-radius: 6px;
  font-size: 0.9rem;
}
nav a:hover { background: var(--border); color: var(--fg); }
nav a.active { background: var(--accent); color: white; }
.userbox { margin-left: auto; display: flex; align-items: center; gap: 1rem; }
.user { color: var(--muted); }
.logout { color: var(--muted); text-decoration: none; }
/* 960px was a reading-column width, which is wrong for this app: almost every
   page is a wide table of content. Cap generously instead, and let the content
   breathe on a 16:9 display rather than leaving half the screen empty. */
main { width: min(1560px, 100% - 3rem); margin: 1.5rem auto; padding: 0 0 3rem; }
/* Pages that really are prose stay narrow -- a 1500px line of text is unreadable. */
main.narrow { width: min(820px, 100% - 3rem); }
h1 { margin-top: 0; font-size: 1.5rem; }
h2 { font-size: 1.1rem; }
h3 { font-size: 0.95rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem;
  margin-bottom: 1.25rem;
}
/* A wide table must be able to scroll inside its card rather than forcing the
   whole page sideways -- otherwise one long car id breaks every other page. */
.table-wrap { overflow-x: auto; margin: 0 -0.25rem; }
table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
table th {
  text-align: left;
  padding: 0.45rem 0.6rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}
table td {
  text-align: left;
  padding: 0.45rem 0.6rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
/* Zebra + hover: with seven columns of mixed content, a row you can follow
   across the table matters more than it does on a three-column one. */
table tr:nth-child(even) td { background: var(--row-alt); }
table tr:not(:has(th)):hover td { background: var(--row-hover); }
table tr:last-child td { border-bottom: none; }
/* Shrink-to-fit columns: "width:1%" plus nowrap makes a column exactly as wide
   as its content, handing the leftover space to the name column where it helps. */
.col-tight { width: 1%; white-space: nowrap; }
.col-thumb { width: 4.5rem; }
.col-id { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85rem; }
table.kv th { width: 12rem; color: var(--muted); font-weight: 500; text-transform: none;
              letter-spacing: 0; font-size: 0.9rem; }

form { display: flex; flex-direction: column; gap: 0.75rem; }
form.inline { display: inline-flex; flex-direction: row; align-items: center; gap: 0.4rem; margin: 0; }
/* Settings pages are lists of short fields. Stacking them in one column leaves a
   1500px-wide page with a 1500px-wide text box on it; flow them into columns
   that stay a sane width instead. */
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
             gap: 0.9rem 1.5rem; align-items: start; }
.form-grid > h2, .form-grid > h3, .form-grid > .span-all { grid-column: 1 / -1; }
.field { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.help { color: var(--muted); font-size: 0.78rem; line-height: 1.45; }
label { display: flex; flex-direction: column; gap: 0.25rem; font-size: 0.9rem; color: var(--muted); }
label input, label select, textarea {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.4rem 0.5rem;
  max-width: 100%;
}
label input:focus, label select:focus, textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}
label:has(input[type=checkbox]) { flex-direction: row; align-items: center; }
label input[type=checkbox] { width: auto; }
textarea { width: 100%; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.85rem; }
fieldset {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 0.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: end;
}
legend { padding: 0 0.4rem; color: var(--muted); font-size: 0.85rem; }
.row-status { font-size: 0.8rem; font-style: italic; }
button {
  font: inherit;
  cursor: pointer;
  background: var(--accent);
  color: white;
  border: none;
  border-radius: 6px;
  padding: 0.5rem 1rem;
  align-self: flex-start;
}
button:disabled { opacity: 0.5; cursor: not-allowed; }
button.danger { background: var(--danger); }
button.small { padding: 0.3rem 0.6rem; font-size: 0.85rem; }
/* Row-level buttons are quiet by default. A solid red Delete on every one of
   751 rows makes the most destructive action the loudest thing on the page;
   outlined until hovered puts it back in proportion without hiding it. */
button.ghost { background: transparent; color: var(--muted); border: 1px solid var(--border); }
button.ghost:hover { color: var(--fg); border-color: var(--accent); }
button.ghost.danger:hover { color: var(--danger); border-color: var(--danger); background: transparent; }
button.ghost.danger { background: transparent; }

/* One compact control per row, with the rarely-used external-URL form folded
   away behind it -- three side-by-side controls on every row was most of what
   made this table unreadable. */
.row-actions { display: flex; gap: 0.35rem; align-items: center; justify-content: flex-end; }
details.drop > summary {
  list-style: none; cursor: pointer; font-size: 0.85rem; color: var(--muted);
  padding: 0.3rem 0.6rem; border: 1px solid var(--border); border-radius: 6px;
  user-select: none; white-space: nowrap;
}
details.drop > summary::-webkit-details-marker { display: none; }
details.drop > summary:hover { color: var(--fg); border-color: var(--accent); }
details.drop[open] > summary { color: var(--fg); border-color: var(--accent); }
details.drop > form { margin-top: 0.4rem; justify-content: flex-end; }
.status-line { display: flex; align-items: center; gap: 0.4rem; white-space: nowrap; }
.status-sub { font-size: 0.78rem; }
.muted { color: var(--muted); }
.save-fab {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 100;
  padding: 0.85rem 1.75rem;
  font-size: 1rem;
  font-weight: 600;
  border-radius: 999px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
}
.save-fab:active { transform: translateY(1px); }
.badge { display: inline-block; padding: 0.15rem 0.5rem; border-radius: 999px;
         font-size: 0.72rem; font-weight: 600; white-space: nowrap; }
.badge-up { background: var(--up); color: #06280f; }
.badge-down { background: var(--border); color: var(--muted); }
/* visibility, not display: a thumbnail that fails to load must still hold its
   space, or rows with artwork end up taller than rows without and the whole
   table loses its rhythm. */
.thumb { height: 2.5rem; width: 4rem; object-fit: cover; border-radius: 6px;
         background: var(--border); vertical-align: middle; display: block; }
.thumb-large { height: 6rem; width: auto; max-width: 100%; display: block; margin-bottom: 0.5rem; }
.tabs { display: flex; gap: 0.25rem; margin: 0 0 -1px; }
.tab-btn {
  background: var(--card-bg);
  color: var(--muted);
  border: 1px solid var(--border);
  border-bottom: none;
  border-radius: 8px 8px 0 0;
  padding: 0.5rem 1.25rem;
  cursor: pointer;
}
.tab-btn.active { color: var(--fg); font-weight: 600; }
.tab-panel { border-top-left-radius: 0; }
.table-filter { width: 100%; margin-bottom: 0.75rem; }
.pager { display: flex; align-items: center; gap: 0.75rem; margin-top: 0.75rem; }
.pager-info { color: var(--muted); font-size: 0.85rem; }
.log {
  background: #05070a;
  color: #c8f0c8;
  padding: 1rem;
  border-radius: 8px;
  max-height: 420px;
  overflow-y: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.8rem;
  white-space: pre-wrap;
}
.center-box {
  max-width: 360px;
  margin: 4rem auto;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 2rem;
}
.flash { padding: 0.6rem 1rem; border-radius: 8px; margin-bottom: 1rem; }
.flash-error { background: #4a1416; color: #ffb3b6; }
.flash-ok { background: #133a1f; color: #b6f0c1; }
code { background: var(--border); padding: 0.1rem 0.3rem; border-radius: 4px; }

/* Other Settings: key and value split the available width evenly, with the
   buttons pulled out into their own column so the value input can own its full
   cell instead of sharing it with a Save button. The ops column is sized by its
   buttons -- a min-width keeps Save and Delete side by side rather than wrapping
   onto two lines on a narrow window. */
.col-key, .col-value { width: 50%; }
.col-ops { width: 1%; min-width: 11rem; white-space: nowrap; }
.col-value select, .col-value input { width: 100%; }
.cell-form { display: block; margin: 0; }
.col-key code { font-size: 0.85rem; }
.col-key .help { margin-top: 0.15rem; }

/* Content toolbar: search, filters and bulk actions on one line above the
   table. Wraps rather than overflowing -- it carries six controls. */
.table-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  margin-bottom: 0.75rem;
}
.table-toolbar .table-filter { flex: 1 1 16rem; min-width: 12rem; margin-bottom: 0; }
.table-toolbar .page-size { flex: 0 0 auto; }
.table-toolbar .sel-count { font-size: 0.85rem; min-width: 5.5rem; }
.table-toolbar button { align-self: auto; }
.inline-check {
  flex-direction: row; align-items: center; gap: 0.35rem;
  white-space: nowrap; font-size: 0.85rem;
}
.row-check, .check-all { width: auto; cursor: pointer; }
/* A disabled bulk button should read as "nothing selected yet", not as an
   error -- keep it quiet rather than greying it into illegibility. */
.bulk-btn:disabled { opacity: 0.45; }

/* Quick Race footer: Run is the primary action, Save as preset the quiet one
   beside it. Not a floating button like the preset page's Save -- running a
   race is a bigger commitment than saving a form, so it stays at the end of
   the page where you arrive at it deliberately. */
.quick-actions {
  display: flex; align-items: center; gap: 0.75rem;
  margin: 0 0 1.25rem; flex-wrap: wrap;
}
.save-fab-inline {
  padding: 0.7rem 1.75rem; font-size: 1rem; font-weight: 600; border-radius: 999px;
}

/* Content availability notes. Two levels, because the two problems are not the
   same: a mod with no download package is a hard block (nobody can get it),
   while paid DLC is only a block for players who happen not to own that pack. */
.content-note {
  font-size: 0.85rem;
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
}
.content-note.blocked { color: var(--danger); }
.content-note.dlc { color: var(--warn); }
legend .content-note { font-size: 0.8rem; }
p.content-note { display: flex; margin: 0.4rem 0; }

/* Entry list grouped by car. The collapsed header is the normal view: car,
   availability, how many. Everything per-slot hides behind the toggle. */
.car-group {
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 0.5rem;
  background: var(--row-alt);
}
.car-group-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0.75rem;
  cursor: pointer;
}
.car-group-head:hover { background: var(--row-hover); border-radius: 8px; }
.car-group.open > .car-group-head { border-bottom: 1px solid var(--border); border-radius: 8px 8px 0 0; }
.group-toggle {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 0.9rem;
  padding: 0 0.2rem;
  cursor: pointer;
  transition: transform 0.12s ease;
}
.car-group.open .group-toggle { transform: rotate(90deg); color: var(--fg); }
.thumb-tiny { height: 1.9rem; width: 3rem; }
/* The name takes the slack so the quantity box stays pinned right, lining up
   down the list however long the car names are. */
.car-group-name { flex: 1 1 auto; min-width: 0; }
.car-group-name code { color: var(--muted); font-size: 0.85rem; margin-left: 0.4rem; }
.car-group-skins { color: var(--muted); font-size: 0.8rem; white-space: nowrap; }
.car-qty {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  color: var(--muted);
  font-size: 0.85rem;
  cursor: auto;
}
.car-qty input { width: 4.5rem; }
.qty-status { font-size: 0.8rem; min-width: 5rem; }
.car-group-slots { padding: 0.75rem; }
.car-group-slots[hidden] { display: none; }
@media (max-width: 720px) {
  .car-group-head { flex-wrap: wrap; }
  .car-group-name { flex-basis: 100%; }
  .car-group-skins { display: none; }
}

/* A car with no data.acd. It looks completely normal otherwise -- artwork,
   skins, a working download -- so the row itself has to carry the warning. */
tr.row-broken > td { background: color-mix(in srgb, var(--danger) 12%, transparent); }
tr.row-broken:hover > td { background: color-mix(in srgb, var(--danger) 18%, transparent); }
tr.row-broken .col-id { color: var(--danger); }

.inline-check.disabled { opacity: 0.45; cursor: not-allowed; }

/* --- server picker (header) + servers page ------------------------------ */
.server-picker {
  display: inline-flex; align-items: center; gap: .4rem; margin: 0 .75rem 0 0;
}
.server-picker select {
  padding: .25rem 1.6rem .25rem .5rem; font-size: .85rem; max-width: 14rem;
  background: var(--panel); color: var(--fg);
  border: 1px solid var(--border); border-radius: 5px;
}
/* Shown only when JavaScript hasn't taken over the change event. */
.server-picker-go { padding: .25rem .6rem; font-size: .8rem; }
.server-picker.js-ready .server-picker-go { display: none; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.dot { width: .55rem; height: .55rem; border-radius: 50%; flex: none; display: inline-block; }
.dot-up { background: var(--ok, #2ea043); }
.dot-down { background: var(--muted); }
.dot-pending { background: var(--warn); }
.dot-dead { background: var(--danger); }

.server-card {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 6px; padding: 1rem; margin-bottom: 1rem;
}
.server-card-head { display: flex; align-items: center; gap: .75rem; }
.server-card-head h3 { margin: 0; }
.pill {
  font-size: .75rem; padding: .15rem .55rem; border-radius: 999px;
  background: color-mix(in srgb, var(--fg) 12%, transparent); color: var(--muted);
}
.pill-good { background: color-mix(in srgb, var(--ok, #2ea043) 22%, transparent); color: var(--fg); }
.pill-warn { background: color-mix(in srgb, var(--warn) 25%, transparent); color: var(--fg); }
.pill-bad { background: color-mix(in srgb, var(--danger) 22%, transparent); color: var(--fg); }
.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: .75rem; }
.grid-2 small { display: block; color: var(--muted); font-size: .75rem; margin-top: .2rem; }

/* Results > Drivers: the column currently sorted on. */
table.sortable th[aria-sort="ascending"]::after { content: " \25B2"; font-size: 0.7em; }
table.sortable th[aria-sort="descending"]::after { content: " \25BC"; font-size: 0.7em; }
