/*
 * Console styles.
 *
 *   Palette / tokens           css/themes/<skin>.css, loaded after this file
 *   Login page                 Connect
 *   Buttons / shell / tables   later in this file (search the ---------- headings)
 *   Scoreboard / cash          Scores / status, Cash
 */

.hidden,
[hidden] {
  display: none !important;
}

/* ----------------------------------------------------------------------------
 * This file is the console itself: layout, components, typography. It carries
 * no palette of its own — every colour comes from a token, and the tokens come
 * from one skin in css/themes/ (wardogs, qonzer, dark, light, win7, win95,
 * british, german, american).
 * The rules just below are shell, not palette, so they hold for every skin;
 * the :root prefix is only there to outrank the base rules further down.
 * ------------------------------------------------------------------------- */

:root .plus-grid::before,
:root.plus-grid::before {
  background-color: var(--bg);
  background-image: none;
}

:root .mark {
  display: none;
}

:root .brand-icon {
  display: block;
}

:root .brand {
  align-items: center;
  gap: 8px;
}

:root .brand h1 {
  font-size: 18px;
  letter-spacing: 0.04em;
  text-transform: none;
  font-weight: 600;
  line-height: 1.2;
}

:root .btn-gold {
  background: var(--primary);
  color: var(--primary-ink);
  border-color: var(--primary);
}

:root .btn-gold:hover {
  background: color-mix(in srgb, var(--primary) 82%, #ffffff);
  border-color: color-mix(in srgb, var(--primary) 82%, #ffffff);
}

:root .connect-card {
  background: var(--surface);
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  min-height: 100%;
  scroll-padding-top: 72px;
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font);
  line-height: 1.45;
}

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

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

.plus-grid {
  position: relative;
  isolation: isolate;
  min-height: 100vh;
}

.plus-grid::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-color: var(--bg);
  background-image: none;
}

/* ---------- Connect ---------- */

.connect-wrap {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 28px;
  padding: 32px 16px 40px;
}

.connect-card {
  width: min(440px, 100%);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 28px 26px 24px;
  box-shadow: var(--shadow);
  backdrop-filter: blur(10px);
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}

.mark {
  width: 40px;
  height: 40px;
  border: 1px solid var(--primary);
  background: color-mix(in srgb, var(--primary) 12%, var(--surface));
  color: var(--primary);
  display: grid;
  place-items: center;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.brand-icon {
  display: none;
  width: 44px;
  height: 44px;
  object-fit: contain;
  flex-shrink: 0;
}

.brand h1 {
  margin: 0;
  font-size: 18px;
  letter-spacing: 0.04em;
  text-transform: none;
  font-weight: 600;
  line-height: 1.2;
}

.brand-sub {
  margin: 0;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.gold-pill {
  display: inline-block;
  margin: 10px 0 22px;
  background: var(--primary);
  color: var(--primary-ink);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 3px 8px;
}

.field {
  display: grid;
  gap: 6px;
  margin-bottom: 14px;
}

.field-split {
  display: grid;
  grid-template-columns: 1fr 110px;
  gap: 10px;
}

.field label,
.lbl {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

.field input:not([type="checkbox"]):not([type="range"]),
.field select,
.field textarea,
.ctrl {
  width: 100%;
  /* --field is the input well. It is the page colour on the two flat skins and
     a light well on the ones whose --bg is a desktop, not a surface. */
  background: var(--field, var(--bg));
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  outline: none;
}

.field input:not([type="checkbox"]):not([type="range"]):focus,
.field select:focus,
.field textarea:focus,
.ctrl:focus {
  border-color: var(--primary);
}

.row-check {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 4px 0 18px;
  color: var(--muted);
  font-size: 13px;
}

.login-mode {
  margin: 0 0 18px;
}

.pass-row {
  display: flex;
  gap: 6px;
  align-items: stretch;
}

.pass-row .ctrl {
  flex: 1;
  min-width: 0;
}

.pass-row .btn {
  flex-shrink: 0;
}

/* Users: the one-time password link after Add user / New link. */
.invite-out {
  margin-top: 12px;
  padding: 12px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
  border-radius: 8px;
  background: var(--bg);
}

.invite-out .field {
  margin-bottom: 6px;
}

.invite-out .hint {
  margin: 0;
}

.invite-tag {
  margin-left: 6px;
  vertical-align: middle;
}

.server-grant {
  display: grid;
  gap: 6px;
  margin-top: 6px;
  justify-items: stretch;
}

.table-wrap .server-grant {
  margin-top: 0;
}

.server-grant .row-check {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr);
  align-items: center;
  column-gap: 8px;
  margin: 0;
  width: 100%;
  color: var(--fg);
  font-size: 13px;
  white-space: nowrap;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}

.server-grant .row-check .tick,
.server-grant .row-check input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: 0;
  padding: 0;
  max-width: 16px;
  min-width: 16px;
  justify-self: center;
  border-radius: 3px;
}

.server-grant .row-check span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

#user-create .server-grant {
  max-width: 360px;
}

#users-body td:nth-child(4) {
  white-space: normal;
  vertical-align: top;
  min-width: 180px;
}

.user-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  justify-content: flex-end;
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--fg);
  border-radius: 8px;
  padding: 9px 14px;
  cursor: pointer;
  text-decoration: none;
}

.btn:hover {
  border-color: color-mix(in srgb, var(--primary) 50%, var(--line));
}

.btn-gold {
  width: 100%;
  border-color: var(--primary);
  background: transparent;
  color: var(--primary);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  padding: 12px;
}

.btn-gold:hover {
  background: color-mix(in srgb, var(--primary) 14%, transparent);
}

.btn-primary {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-ink);
  font-weight: 700;
}

.btn-danger {
  border-color: var(--accent);
  color: var(--accent);
}

.btn-ghost {
  background: transparent;
}

.btn-sm {
  padding: 6px 10px;
  font-size: 12px;
}

.icon-btn {
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 6px;
}

/* ---------- App shell ---------- */

.app {
  height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr;
  overflow: hidden;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  z-index: 20;
  flex-shrink: 0;
  flex-wrap: wrap;
}

.topbar .brand {
  margin: 0;
}

.topbar .brand h1 {
  font-size: 18px;
}

.topbar .brand-icon {
  width: 30px;
  height: 30px;
}

.topbar .brand h1 {
  font-size: 15px;
  letter-spacing: 0.02em;
  text-transform: none;
}

.server-tabs {
  display: flex;
  gap: 6px;
  flex: 1;
  min-width: 0;
  overflow: auto;
  align-items: center;
}

.server-tab {
  display: flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--fg);
  border-radius: 6px;
  padding: 5px 10px;
  font-size: 13px;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  max-width: 7.5rem;
}

.server-tab > span:not(.status-dot) {
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.server-tab .status-dot {
  width: 8px;
  height: 8px;
  box-shadow: none;
  background: var(--idle);
}

.server-tab .status-dot.up {
  background: var(--good);
  box-shadow: 0 0 6px var(--good);
}

.server-tab .status-dot.down {
  background: var(--bad);
  box-shadow: 0 0 6px var(--bad);
}

.server-tab .icon-btn {
  width: 16px;
  height: 16px;
  font-size: 12px;
  line-height: 1;
}

.server-tab.active {
  border-color: var(--primary);
  background: color-mix(in srgb, var(--primary) 12%, var(--surface));
}

#add-server {
  margin-left: 4px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 12px;
  flex-shrink: 0;
}

.perm-acc {
  border-bottom: 1px solid var(--line);
}

.perm-acc:last-child {
  border-bottom: 0;
}

.perm-acc-head {
  display: flex;
  align-items: center;
  gap: 10px;
}

.perm-acc-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: none;
  border: 0;
  color: var(--fg);
  font: inherit;
  font-size: 13px;
  padding: 9px 0;
  cursor: pointer;
  text-align: left;
}

.perm-acc-btn::before {
  content: "▸";
  color: var(--muted);
  font-size: 11px;
  margin-right: 6px;
}

.perm-acc.open .perm-acc-btn::before {
  content: "▾";
  color: var(--primary);
}

.perm-count {
  color: var(--muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.perm-acc-head > label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
  flex-shrink: 0;
}

.perm-list {
  display: none;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 16px;
  padding: 0 0 10px 18px;
}

.perm-acc.open .perm-list {
  display: grid;
}

.perm-list label {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 5px 0;
  font-size: 13px;
  cursor: pointer;
}

.role-card {
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  margin-top: 10px;
}

.role-card-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  padding: 12px 14px;
  cursor: pointer;
}

.role-card-head b {
  display: inline;
}

.role-card-body {
  display: none;
  padding: 0 14px 10px;
  border-top: 1px solid var(--line);
}

.role-card.open .role-card-body {
  display: block;
}

@media (max-width: 640px) {
  .perm-list {
    grid-template-columns: 1fr;
  }
}

.tick,
.switch input[type="checkbox"],
.row-check input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  margin: 0;
  flex-shrink: 0;
  border: 1px solid var(--line);
  background: var(--surface-2);
  border-radius: 3px;
  cursor: pointer;
  position: relative;
}

.tick:checked,
.switch input[type="checkbox"]:checked,
.row-check input[type="checkbox"]:checked {
  background: var(--primary);
  border-color: var(--primary);
}

.tick:checked::after,
.switch input[type="checkbox"]:checked::after,
.row-check input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 4px;
  top: 1px;
  width: 5px;
  height: 9px;
  border: solid var(--primary-ink);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.tick:disabled,
.switch input[type="checkbox"]:disabled {
  opacity: 0.5;
  cursor: default;
}

.tick:focus-visible,
.switch input[type="checkbox"]:focus-visible,
.row-check input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

.rot-edit {
  min-width: 118px;
  width: auto;
}

.rot-order {
  display: flex;
  align-items: center;
  gap: 4px;
}

.rot-handle {
  cursor: grab;
  border: 1px solid var(--primary);
  background: color-mix(in srgb, var(--primary) 14%, var(--surface));
  color: var(--primary);
  border-radius: 6px;
  padding: 4px 8px;
  font: inherit;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.rot-handle:active {
  cursor: grabbing;
}

.rot-arrow {
  min-width: 28px;
  padding-left: 6px;
  padding-right: 6px;
}

.rot-row-ghost {
  opacity: 0.3;
}

.rot-head-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.rot-live {
  margin: 4px 0 14px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.5;
}

.rot-live .hint {
  margin: 0;
}

.rot-live-warn {
  color: var(--bad);
}

.rot-row-now {
  background: color-mix(in srgb, var(--primary) 12%, transparent);
}

.rot-row-next:not(.rot-row-now) {
  background: color-mix(in srgb, var(--primary) 6%, transparent);
}

.route-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.route-tag {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 4px;
  border: 1px solid var(--line);
  white-space: nowrap;
}

.route-tag.route-new {
  border-color: var(--primary);
  color: var(--primary);
}

.route-tag.route-missing {
  border-color: var(--bad);
  color: var(--bad);
}

.rot-row-denied td { opacity: .72; }

.rot-slot-denied {
  background: var(--bad-soft);
  color: var(--bad);
}

.rot-slot {
  display: inline-block;
  margin-left: 6px;
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--primary);
  font-weight: 600;
}

body.rot-dragging,
body.rot-dragging * {
  cursor: grabbing !important;
  user-select: none;
}

.wd-toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  z-index: 90;
  max-width: min(520px, calc(100vw - 32px));
  padding: 10px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--fg);
  box-shadow: var(--shadow);
  font-size: 13px;
  line-height: 1.4;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, 10px);
  transition: opacity .16s ease, transform .16s ease;
}

.wd-toast.show {
  opacity: 1;
  pointer-events: auto;
  cursor: pointer;
  transform: translate(-50%, 0);
}

.rot-float {
  position: fixed;
  z-index: 80;
  pointer-events: none;
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 220px;
  padding: 10px 14px 10px 10px;
  border-radius: 10px;
  border: 1px solid var(--primary);
  background: color-mix(in srgb, var(--surface) 96%, transparent);
  box-shadow: var(--shadow);
  transform: translate(-10px, -72%) rotate(-2deg);
}

.rot-float b {
  display: block;
}

.rot-float span {
  color: var(--muted);
  font-size: 12px;
}

.map-cell {
  display: flex;
  align-items: center;
  gap: 10px;
}

.map-thumb {
  width: 52px;
  height: 66px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  flex-shrink: 0;
}

.rot-add {
  display: grid;
  grid-template-columns: minmax(200px, 280px) 1fr;
  gap: 16px;
  align-items: start;
  margin-top: 8px;
}

.map-preview {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--surface-2);
}

@media (max-width: 800px) {
  .rot-add {
    grid-template-columns: 1fr;
  }
}

.settings-block {
  border-top: 1px solid var(--line);
  padding-top: 16px;
}

.settings-row {
  display: grid;
  grid-template-columns: 1fr minmax(220px, 280px);
  gap: 16px;
  align-items: start;
}

.settings-row .hint {
  margin-top: 6px;
}

.settings-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}

@media (max-width: 980px) {
  .settings-row {
    grid-template-columns: 1fr;
  }
}

.probe-table td:last-child {
  white-space: normal;
  min-width: 220px;
  max-width: 460px;
}

.probe-code {
  font-family: var(--mono);
  font-weight: 700;
}

.probe-fail {
  color: var(--accent);
  font-weight: 700;
}

.probe-wait {
  color: var(--muted);
}

.probe-table pre {
  margin: 0;
  font-family: var(--mono);
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 160px;
  overflow: auto;
}

.probe-table details summary {
  cursor: pointer;
  color: var(--muted);
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--manticore);
  box-shadow: 0 0 8px var(--manticore);
}

.live-chip {
  margin-left: auto;
  color: var(--muted);
  font-size: 12px;
  white-space: nowrap;
}

.live-chip.down {
  color: var(--accent);
}

.nav-toggle {
  display: none;
}

/* The side nav's width; the fixed .gs-stage bar starts after it too. */
body {
  --nav-w: 230px;
}

.shell {
  display: grid;
  grid-template-columns: var(--nav-w) 1fr;
  min-height: 0;
  overflow: hidden;
}

.nav {
  border-right: 1px solid var(--line);
  padding: 14px 10px 20px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: color-mix(in srgb, var(--surface) 55%, transparent);
  overflow: auto;
}

.icon-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* Stroke icons from the sprite at the top of app.html; they take the item's text colour. */
.nav-ico {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.nav-collapse {
  align-self: flex-start;
  margin-bottom: 6px;
  color: var(--muted);
}

.nav-collapse .nav-ico {
  transition: transform 0.15s ease;
}

/* Folded to an icon bar by the arrow at the top (body.nav-collapsed, remembered per browser).
   Desktop only: at 980px and under the nav is the Menu dropdown and keeps its labels. */
@media (min-width: 981px) {
  body.nav-collapsed { --nav-w: 58px; }
  body.nav-collapsed .nav { padding-inline: 9px; }
  body.nav-collapsed .nav-collapse { align-self: center; }
  body.nav-collapsed .nav-collapse .nav-ico { transform: rotate(180deg); }

  body.nav-collapsed .nav a,
  body.nav-collapsed .nav-foot .btn {
    position: relative;
    justify-content: center;
    padding-inline: 0;
  }

  /* Out of sight only, so screen readers still announce each item. */
  body.nav-collapsed .nav-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* Folded rail: the wide badge art has no readable form at 58px, so it gives
     way to the donate icon and the link takes the same box as the other items. */
  body.nav-collapsed .nav-kofi img { display: none; }

  body.nav-collapsed .nav-kofi {
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: normal;
    border: 1px solid var(--line);
    background: var(--surface-2);
    color: var(--fg);
    padding: 9px 0;
  }

  body.nav-collapsed .nav-kofi .nav-ico { display: block; }

  /* Counts sit on the icon's corner instead of after the hidden label. */
  body.nav-collapsed .nav .nav-count {
    position: absolute;
    top: 1px;
    right: 1px;
    margin: 0;
    min-width: 0;
    padding: 0 4px;
    font-size: 10px;
    line-height: 14px;
  }
}

@media (max-width: 980px) {
  .nav-collapse { display: none; }
}

.nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  text-decoration: none;
  padding: 9px 12px;
  border-radius: 8px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 12px;
}

.nav a:hover,
.nav a.active {
  color: var(--primary-ink);
  background: var(--primary);
}

.nav-count {
  display: inline-block;
  min-width: 1.25em;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  letter-spacing: 0;
  text-transform: none;
  font-weight: 700;
  text-align: center;
}

.nav-foot {
  margin-top: auto;
  display: grid;
  gap: 10px;
}

.nav-foot .btn {
  width: 100%;
}

/* Ko-fi badge above Feedback: the badge art brings its own blue, so the button
   is exactly the image - no box around it that could be clicked but not seen. */
.nav-kofi {
  display: block;
  line-height: 0;
  overflow: hidden;
  border-radius: var(--radius, 8px);
}

/* Expanded, the badge art carries the wording; icon and label are for the folded rail only. */
.nav-kofi .nav-ico,
.nav-kofi .nav-label {
  display: none;
}

.nav-kofi img {
  display: block;
  width: 100%;
  height: auto;
  border: 0;
}

.nav-foot .nav-count {
  margin-left: 8px;
  vertical-align: middle;
}

/* Group headings of the side nav (Moderation, Logs & stats, Server setup, Workspace).
   Server setup names the server its pages work on underneath. Folded, a heading is a rule. */
.nav-group {
  display: grid;
  gap: 2px;
  margin: 12px 0 2px;
  padding: 0 12px;
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0.85;
}

.nav-group-server {
  overflow: hidden;
  color: var(--fg);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0;
  text-overflow: ellipsis;
  text-transform: none;
  white-space: nowrap;
}

.nav-group-server:empty {
  display: none;
}

@media (min-width: 981px) {
  body.nav-collapsed .nav-group {
    height: 0;
    margin: 8px 6px;
    padding: 0;
    border-top: 1px solid var(--line);
  }
}

.nav-theme {
  display: grid;
  gap: 6px;
}

.nav-theme span {
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.nav-theme .ctrl {
  width: 100%;
}

.main {
  padding: 20px 22px 40px;
  min-width: 0;
  min-height: 0;
  overflow: auto;
}

.view {
  display: none;
}

.view.active {
  display: block;
}

.view-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.view-head h2 {
  margin: 0 0 4px;
  font-size: 26px;
}

.view-head p {
  margin: 0;
  color: var(--muted);
}

.view-head > .btn {
  flex-shrink: 0;
  white-space: nowrap;
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.stack {
  display: grid;
  gap: 14px;
}

.card {
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
}

.card h3 {
  margin: 0 0 12px;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}

.card-head h3 {
  margin: 0;
}

.board-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.board-tools .ctrl {
  width: 220px;
}

#view-feed .board-tools .ctrl[type="search"],
#view-audit .board-tools .ctrl[type="search"] {
  width: min(420px, 100%);
}

/* Keeps related toolbar controls on the same row when .board-tools wraps. */
.tool-group {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* ---------- Scores / status ---------- */

.scores {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.score {
  border: 1px solid var(--line);
  background: var(--bg);
  border-radius: 8px;
  padding: 12px;
}

.score .name {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.score .n {
  font-size: 36px;
  font-weight: 700;
  line-height: 1.1;
}

.score.valkyra .n { color: var(--valkyra); }
.score.lonestar .n { color: var(--lonestar); }
.score.manticore .n { color: var(--manticore); }

/* ==========================================================================
 * PLAYER DATABASE: staff notes
 * ========================================================================== */
.db-head-tools {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.db-notes-only {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}

.db-notes-only input { cursor: pointer; }
.db-notes-only:hover { color: var(--fg); }

/* Unstyled button so a saved note reads as text but is still clickable. */
.btn-plain {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.db-note {
  display: grid;
  gap: 1px;
  max-width: 100%;
}

.db-note-text {
  display: block;
  color: var(--fg);
  line-height: 1.35;
  overflow-wrap: anywhere;
}

button.db-note:hover .db-note-text { text-decoration: underline; }

.db-note-meta {
  font-size: 11px;
  color: var(--muted);
}

/* Quiet until hovered: an empty cell should not shout on every row. */
.db-note-add {
  opacity: 0.45;
  transition: opacity 0.12s ease;
}

tr:hover .db-note-add,
.db-note-add:focus-visible { opacity: 1; }

/* ==========================================================================
 * PLAYER PROFILE (dossier opened from Database / Players)
 * ========================================================================== */
.player-link {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  max-width: 100%;
}

.player-link:hover,
.player-link:focus-visible {
  text-decoration: underline;
  color: var(--primary);
}

.player-view-head {
  align-items: flex-start;
}

.player-view-title {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  min-width: 0;
}

.player-view-title #player-back {
  margin-top: 6px;
  flex-shrink: 0;
}

.player-view-title h2 {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.player-view-title #player-sub {
  font-family: var(--mono);
  font-size: 12px;
  word-break: break-all;
}

#player-head-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

/* Warn / Kick / Kill while the player is not on the selected server. */
#player-head-actions .btn:disabled {
  opacity: 0.45;
  cursor: default;
}

/* Name dropdown in the profile header: shown only when the player has more than one
   known name. The button inherits the h2 type so the header reads unchanged. */
.player-name {
  position: relative;
  display: inline-block;
}

.player-name-toggle {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.player-name-caret {
  font-size: 0.6em;
  color: var(--muted);
  transition: transform 0.12s ease;
}

.player-name-toggle:hover .player-name-caret,
.player-name-toggle[aria-expanded="true"] .player-name-caret {
  color: var(--fg);
}

.player-name-toggle[aria-expanded="true"] .player-name-caret {
  transform: rotate(180deg);
}

/* Also a .menu, so the surface follows each theme. This only places it under the name
   and beats .menu's position: fixed. */
.player-name .player-alias-list {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 45;
  min-width: 220px;
  max-width: min(28em, 90vw);
  max-height: 22em;
  overflow-y: auto;
  /* Reset the h2 type the header passes down. */
  font-size: 13px;
  font-weight: normal;
  letter-spacing: normal;
  text-transform: none;
  color: var(--fg);
}

.player-alias-head {
  padding: 6px 10px 4px;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.player-alias-list ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.player-alias {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5em;
  padding: 7px 10px;
  border-radius: 6px;
  white-space: nowrap;
}

.player-alias.is-current .player-alias-name {
  font-weight: 600;
}

.player-alias-when {
  color: var(--muted);
  font-size: 12px;
}

/* "now used by 7656…": another player carries this name now. Under the name so the row stays narrow. */
.player-alias-copied {
  display: block;
  margin-top: 2px;
  color: var(--accent);
  font-size: 11px;
  font-weight: normal;
}

/* Beats the menu's own button padding. */
.player-alias-list .player-alias-copied .player-link {
  display: inline;
  width: auto;
  padding: 0;
  margin: 0 0 0 4px;
  font-family: var(--mono);
  font-size: 11px;
}

/* .chip comes later in this file, hence the doubled class. */
.chip.player-copied {
  vertical-align: middle;
  margin-left: 8px;
  border-color: var(--accent);
  color: var(--accent);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: none;
}

.player-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.player-status::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
}

.player-status.is-online {
  color: var(--good);
}

.player-status.is-online::before {
  background: var(--good);
}

.player-profile {
  display: grid;
  gap: 14px;
}

.player-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px 20px;
  margin: 0;
}

.player-meta div {
  min-width: 0;
}

.player-meta dt {
  margin: 0 0 2px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}

.player-meta dd {
  margin: 0;
  color: var(--fg);
  overflow-wrap: anywhere;
}

.player-watch-banner {
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent, var(--primary));
  border-radius: 8px;
  padding: 10px 12px;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
}

.player-watch-banner strong {
  display: block;
  margin-bottom: 2px;
}

.player-profile-grid {
  display: grid;
  gap: 14px;
}

@media (min-width: 960px) {
  .player-profile-grid {
    grid-template-columns: minmax(200px, 0.85fr) minmax(0, 1.4fr);
    align-items: start;
  }
}

.player-penalty-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  margin: 0;
  border-top: 1px solid var(--line);
  background-image: linear-gradient(var(--line), var(--line));
  background-size: 1px 100%;
  background-position: center;
  background-repeat: no-repeat;
}

.player-penalty {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
  min-height: 40px;
  box-sizing: border-box;
}

.player-penalty:nth-child(odd) {
  padding-right: 14px;
}

.player-penalty:nth-child(even) {
  padding-left: 14px;
}

.player-penalty.is-empty {
  pointer-events: none;
}

/* Last row only: drop the bottom rule (works for even cell counts). */
.player-penalty:nth-last-child(-n+2) {
  border-bottom: 0;
}

@media (max-width: 520px) {
  .player-penalty-grid {
    grid-template-columns: 1fr;
    background-image: none;
  }

  .player-penalty:nth-child(odd),
  .player-penalty:nth-child(even) {
    padding-left: 0;
    padding-right: 0;
  }

  .player-penalty:nth-last-child(-n+2) {
    border-bottom: 1px solid var(--line);
  }

  .player-penalty.is-empty {
    display: none;
  }

  .player-penalty:last-child {
    border-bottom: 0;
  }
}

.player-penalty .k {
  font-size: 13px;
  color: var(--muted);
}

.player-penalty .n {
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.player-actions-table {
  margin: 0;
}

.player-actions-table td {
  vertical-align: top;
}

.player-actions-empty {
  margin: 0;
  padding: 4px 0 0;
}

.player-notes-card .note-thread {
  max-height: 28vh;
}

.player-notes-card .note-box {
  min-height: 56px;
  margin-bottom: 10px;
}

.note-box {
  width: 100%;
  min-height: 74px;
  resize: vertical;
  margin: 0 0 12px;
  font: inherit;
  line-height: 1.4;
}

.note-modal {
  width: min(560px, 92vw);
}

/* The thread can grow; keep the add box and buttons reachable. */
.note-thread {
  display: grid;
  gap: 8px;
  max-height: 46vh;
  overflow-y: auto;
  margin: 0 0 12px;
  padding-right: 2px;
}

.note-item {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 10px;
}

.note-item-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 4px;
}

.note-who {
  font-weight: 600;
  font-size: 12px;
}

.note-when {
  font-size: 11px;
  color: var(--muted);
}

.note-del {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
}

.note-del:hover { color: var(--valkyra); }

.note-body {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ==========================================================================
 * STATISTICS (main workspace): tiles, search, one card per workspace
 * ========================================================================== */

/* One strip rather than five boxes. Each cell paints its own hairline into the
   1px gap, so a wrapped row still divides cleanly and the leftover cell at the
   end of a short row reads as empty strip rather than as a missing tile. */
.stat-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 14px;
}

.stat-tile {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 12px 16px;
  background: var(--surface);
  box-shadow: -1px 0 0 var(--line), 0 -1px 0 var(--line);
}

/* Workspaces is the number this page exists to answer. The rule bar is drawn
   as a gradient, not a shadow, because the shadow is the cell divider. */
.stat-tile.is-key {
  background:
    linear-gradient(90deg, var(--primary) 0 2px, transparent 2px),
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--primary) 12%, var(--surface)),
      var(--surface));
}

.stat-tile-n {
  font-size: 22px;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.stat-tile.is-key .stat-tile-n { color: var(--primary); }
.stat-tile-admin { color: var(--lonestar, var(--primary)); }
.stat-tile-host { color: var(--manticore, var(--primary)); }

.stat-tile-label {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.stats-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 4px;
}

.stats-search {
  flex: 1 1 260px;
  min-width: 0;
}

.stats-filter { margin: 0; flex: 0 0 auto; }

/* Pushed to the far end so the count reads as a result line, not a caption. */
.stats-status {
  flex: 0 0 auto;
  margin: 0 0 0 auto;
  font-variant-numeric: tabular-nums;
}

/* Columns, not a row grid: workspaces run from 2 to 20 people, and rows would
   leave a hole under every short card. */
.ws-grid {
  columns: 320px 5;
  column-gap: 12px;
  margin-top: 12px;
}

.ws-card {
  break-inside: avoid;
  margin: 0 0 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 14px;
}

.ws-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

/* Initials tint the card so a wall of them is scannable. The tint is picked
   from the skin's own tokens, never from a colour written here. */
.ws-avatar {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  background: var(--surface-2);
  color: var(--muted);
}

.ws-avatar.is-c1 { color: var(--lonestar, var(--primary)); background: color-mix(in srgb, var(--lonestar, var(--primary)) 18%, var(--surface-2)); }
.ws-avatar.is-c2 { color: var(--manticore, var(--primary)); background: color-mix(in srgb, var(--manticore, var(--primary)) 18%, var(--surface-2)); }
.ws-avatar.is-c3 { color: var(--accent); background: color-mix(in srgb, var(--accent) 18%, var(--surface-2)); }
.ws-avatar.is-c4 { color: var(--watch, var(--accent)); background: color-mix(in srgb, var(--watch, var(--accent)) 18%, var(--surface-2)); }
.ws-avatar.is-c5 { color: var(--info, var(--primary)); background: color-mix(in srgb, var(--info, var(--primary)) 18%, var(--surface-2)); }
.ws-avatar.is-c6 { color: var(--primary); background: color-mix(in srgb, var(--primary) 18%, var(--surface-2)); }

.ws-head-text {
  min-width: 0;
  flex: 1 1 auto;
}

.ws-title {
  font-weight: 700;
  font-size: 14px;
  line-height: 1.25;
  word-break: break-word;
}

.ws-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
  margin-top: 2px;
  font-size: 11px;
  color: var(--muted);
}

.ws-meta-i + .ws-meta-i::before {
  content: "·";
  margin-right: 6px;
}

.ws-meta-i b { font-weight: 700; color: var(--fg); }
.ws-meta-i.is-admin b { color: var(--lonestar, var(--primary)); }
.ws-meta-i.is-host b { color: var(--manticore, var(--primary)); }

.ws-section { margin-top: 10px; }

.ws-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 4px;
}

.ws-section-head span {
  font-variant-numeric: tabular-nums;
  opacity: 0.8;
}

.ws-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
}

/* Long rosters are folded to the first six rows. A row the search matched is
   never folded away, otherwise a hit would land on a card that looks empty. */
.ws-list:not(.is-open) > li:nth-child(n + 7):not(.is-hit) { display: none; }

.ws-person {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 6px;
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.35;
}

.ws-person:hover,
.ws-host:hover { background: var(--surface-2); }

.ws-person.is-hit,
.ws-host.is-hit { background: color-mix(in srgb, var(--primary) 16%, transparent); }

.ws-dot {
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted);
  opacity: 0.45;
}

.ws-dot.is-admin {
  background: var(--lonestar, var(--primary));
  opacity: 1;
}

.ws-person-name {
  min-width: 0;
  flex: 1 1 auto;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ws-role {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

.ws-role.is-admin { color: var(--lonestar, var(--primary)); }

.ws-owner-tag {
  flex: 0 0 auto;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 1px 5px;
  border-radius: 4px;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  white-space: nowrap;
}

/* Host names are long and arbitrary: clamp them and hang the address below,
   so the address column never gets pushed out of the card. */
.ws-host {
  display: block;
  padding: 4px 6px;
  border-radius: 6px;
  font-size: 13px;
}

.ws-host-name {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.3;
  word-break: break-word;
}

.ws-host-addr {
  display: block;
  margin-top: 1px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--muted);
}

.stat-tile-good { color: var(--good); }
.stat-tile-label span { text-transform: none; letter-spacing: 0; }

/* 14 daily bars of distinct players (Communities table). */
.ws-trend { width: 112px; height: 30px; display: block; }
.ws-trend rect { fill: var(--primary); opacity: 0.85; }
.ws-trend rect:last-child { opacity: 1; }
.ws-trend rect.is-zero { fill: var(--muted); opacity: 0.3; }

/* One slim load line per host on a Statistics card. */
.ws-host-load {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.ws-host-load b { color: var(--fg); font-weight: 700; }

.ws-live {
  flex: 0 0 auto;
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--muted);
  opacity: 0.4;
}

.ws-live.is-on {
  background: var(--good);
  opacity: 1;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--good) 22%, transparent);
}

.ws-bar {
  flex: 1 1 auto;
  display: inline-block;
  min-width: 40px;
  height: 5px;
  border-radius: 3px;
  background: var(--surface-2);
  overflow: hidden;
}

.ws-bar i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--primary);
}

.ws-bar.is-full i { background: var(--good); }
.ws-fill { min-width: 4ch; text-align: right; color: var(--fg); }
.ws-fill.is-full { color: var(--good); font-weight: 700; }

.ws-full-tag {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  vertical-align: 2px;
  color: var(--good);
  background: color-mix(in srgb, var(--good) 16%, transparent);
  white-space: nowrap;
}

.ws-meta-i.is-playing b { color: var(--primary); }

.ws-delete {
  flex: 0 0 auto;
  align-self: flex-start;
  width: 28px;
  height: 28px;
  padding: 0;
  display: grid;
  place-items: center;
  color: var(--muted);
  opacity: 0.55;
}

.ws-delete svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.ws-card:hover .ws-delete { opacity: 1; }
.ws-delete:hover { color: var(--bad); }

/* Communities: ranked table, rows expand into a fact grid and a server table. */
.cm-sort { flex: 0 0 auto; width: auto; }

.cm-wrap {
  margin-top: 12px;
  overflow-x: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.cm-table,
.cm-sv {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.cm-table th,
.cm-sv th {
  text-align: left;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

.cm-table td { padding: 8px 12px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.cm-table th.num, .cm-table td.num, .cm-sv th.num, .cm-sv td.num { text-align: right; }

.cm-row { cursor: pointer; }
.cm-row:hover, .cm-row.is-open { background: var(--surface-2); }
.cm-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.cm-row.has-full { box-shadow: inset 3px 0 0 var(--good); }

.cm-rank { width: 60px; color: var(--muted); white-space: nowrap; }
.cm-pick { display: inline-flex; padding: 4px 8px 4px 0; vertical-align: middle; cursor: pointer; }


.cm-name { min-width: 200px; }
.cm-name-in { display: flex; align-items: center; gap: 10px; }
.cm-name b { font-weight: 700; }
.cm-name .hint { display: block; font-size: 11px; margin: 0; }

.cm-fill-cell { min-width: 190px; white-space: nowrap; }
.cm-fill-cell b { color: var(--fg); }
.cm-fill-cell .ws-bar { width: 90px; margin: 0 8px; vertical-align: middle; }
.cm-fill-cell .ws-fill { display: inline-block; }

.cm-now { color: var(--primary); font-weight: 700; }
.cm-new { color: var(--good); }
.cm-trend-col { width: 124px; }
.cm-joined { white-space: nowrap; }
.cm-joined .hint { display: block; font-size: 11px; margin: 0; }

.cm-detail > td { padding: 0; background: color-mix(in srgb, var(--fg) 3%, var(--surface)); }
.cm-detail-in { padding: 14px 16px 16px; display: grid; gap: 14px; }

/* Dividers drawn per cell (as in .stat-tiles), so a short last row leaves plain surface, not grey. */
.cm-facts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.cm-fact {
  min-width: 0;
  padding: 8px 12px;
  background: var(--surface);
  box-shadow: -1px 0 0 var(--line), 0 -1px 0 var(--line);
}

.cm-fact span { display: block; font-size: 10px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.cm-fact b { display: block; font-size: 15px; overflow-wrap: anywhere; }
.cm-fact em { display: block; font-style: normal; font-size: 11px; font-weight: 400; color: var(--muted); }

.cm-sv-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.cm-sv td { padding: 6px 12px; border-top: 1px solid var(--line); white-space: nowrap; }
.cm-sv tr.is-full td { background: color-mix(in srgb, var(--good) 8%, transparent); }
.cm-sv-name { white-space: normal !important; min-width: 220px; }
.cm-sv-name span { display: block; }
.cm-sv-name code { font-family: var(--mono); font-size: 11px; color: var(--muted); }

.cm-detail-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
.cm-detail-foot .hint { margin: 0; }

/* Communities: 30-day Insights summary inside an open row. */
.cm-ins { display: grid; gap: 10px; }
.cm-ins-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
.cm-ins h4 {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.cm-ins-lists {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 10px;
}

.cm-ins-list {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
}

.cm-ins-list h4 { margin-bottom: 6px; }
.cm-ins-list table { width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
.cm-ins-list td { padding: 3px 0; border-top: 1px solid var(--line); }
.cm-ins-list tr:first-child td { border-top: 0; }
.cm-ins-list td.num { text-align: right; padding-left: 8px; white-space: nowrap; }
.cm-ins-list td.hint { margin: 0; font-size: 11px; }
.cm-ins-i { width: 20px; color: var(--muted); }

.ins-ws-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
  padding: 10px 14px;
  border: 1px solid color-mix(in srgb, var(--primary) 40%, var(--line));
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--primary) 10%, var(--surface));
}

.ins-ws-banner b { color: var(--primary); }

/* ==========================================================================
 * DASHBOARD (main workspace): growth, activity and health on one page
 * Search: dash-kpis, dash-growth, dash-funnel, dash-rows, dash-adoption
 * ========================================================================== */

#view-dashboard .view-head-actions { display: flex; align-items: center; gap: 10px; }
.dash-updated { margin: 0; white-space: nowrap; }

/* A reload keeps the last numbers on screen, dimmed, so nothing jumps. */
#view-dashboard .dash-card,
#view-dashboard .dash-kpis { transition: opacity 0.15s; }
#view-dashboard.is-loading .dash-card,
#view-dashboard.is-loading .dash-kpis { opacity: 0.55; }

.dash-kpis .stat-tile { flex-wrap: wrap; row-gap: 2px; }
/* Proportional figures for a standalone value; tabular ones stay for columns. */
.dash-kpis .stat-tile-n { font-variant-numeric: normal; }
.dash-tile-link { color: inherit; text-decoration: none; }
.dash-tile-link:hover { background: var(--surface-2); }

.dash-grid { display: grid; gap: 14px; margin-bottom: 14px; }
.dash-grid-top { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.dash-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.dash-card { min-width: 0; }
#view-dashboard > .dash-card { margin-bottom: 14px; }
.dash-card .card-head .hint { margin: 0; font-size: 11px; text-align: right; }
.dash-total { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dash-chart-wide { height: 250px; }

/* Change against the period before: an arrow and a number, so direction never rests on colour. */
.dash-delta {
  display: block;
  margin-top: 1px;
  font-size: 10px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.dash-delta.is-good { color: var(--good); }
.dash-delta.is-bad { color: var(--bad); }
.stat-tile .dash-delta { display: inline; margin: 0 0 0 2px; font-size: 11px; }
.dash-row-side .dash-delta { display: inline; margin-left: 6px; }

/* Growth: metrics down, windows across. */
.dash-growth-wrap { overflow-x: auto; }
.dash-growth { width: 100%; border-collapse: collapse; font-size: 13px; font-variant-numeric: tabular-nums; }
.dash-growth th,
.dash-growth td { padding: 7px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
.dash-growth thead th {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.dash-growth .num { text-align: right; }
/* Row labels are th for screen readers, not headers to shout: undo the global th look. */
.dash-growth tbody th {
  text-align: left;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--fg);
  background: transparent;
  white-space: nowrap;
}
.dash-growth tr.dash-group th {
  padding: 14px 12px 5px;
  background: transparent;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.dash-growth tbody tr:not(.dash-group):hover { background: var(--surface-2); }
.dash-growth td b { font-weight: 700; }
.dash-ever { color: var(--muted); }
.dash-foot { margin: 10px 0 0; font-size: 11px; }

/* From sign-up to active: one bar per step, share of every workspace. */
.dash-funnel { display: grid; gap: 14px; }
.dash-step-head { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; }
.dash-step-head b { font-variant-numeric: tabular-nums; }
.dash-step-bar {
  display: block;
  height: 10px;
  margin: 5px 0 3px;
  border-radius: 3px;
  background: var(--surface-2);
  overflow: hidden;
}
.dash-step-bar i { display: block; height: 100%; border-radius: 0 4px 4px 0; background: var(--primary); }
.dash-step-hint { display: block; margin: 0; font-size: 11px; }

.dash-section-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 6px 0 10px; }
.dash-section-head h3 {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}

/* Every chart has its numbers as a table too, folded away under it. */
.dash-table { margin-top: 6px; font-size: 12px; }
.dash-table summary { cursor: pointer; color: var(--muted); font-size: 11px; }
.dash-table-scroll { max-height: 200px; overflow-y: auto; margin-top: 6px; }
.dash-table table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.dash-table td { padding: 3px 0; border-top: 1px solid var(--line); }
.dash-table td.num { text-align: right; }

/* Newest / growing / gone quiet: each row opens the community on Communities. */
.dash-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.dash-row {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.dash-row:hover,
.dash-row:focus-visible { background: var(--surface-2); }
.dash-row:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.dash-row .ws-avatar { width: 30px; height: 30px; font-size: 11px; border-radius: 8px; }
.dash-row-main { flex: 1 1 auto; min-width: 0; }
.dash-row-main b,
.dash-row-main .hint { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-row-main .hint { margin: 0; font-size: 11px; }
.dash-row-side { flex: 0 0 auto; font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dash-chip {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 11px;
  background: var(--surface-2);
  color: var(--muted);
}
.dash-chip.is-live { color: var(--good); background: color-mix(in srgb, var(--good) 14%, transparent); }
.dash-chip.is-warn { color: var(--warn); background: color-mix(in srgb, var(--warn) 14%, transparent); }
.dash-empty { margin: 4px 0 0; }

/* Feature use: one meter per feature, servers and workspaces side by side. */
.dash-adoption { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 28px; }
.dash-adopt {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 120px 76px;
  align-items: center;
  gap: 12px;
  padding: 6px 0;
  border-top: 1px solid var(--line);
  font-size: 13px;
}
.dash-adopt .ws-bar { height: 6px; }
.dash-adopt-n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dash-adopt-n .hint { font-size: 11px; }

@media (max-width: 1180px) {
  .dash-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .dash-grid-top,
  .dash-grid-3,
  .dash-adoption { grid-template-columns: minmax(0, 1fr); }
  .dash-adopt { grid-template-columns: minmax(0, 1fr) 80px 64px; }
}

.ws-more {
  margin-top: 4px;
  padding: 2px 6px;
  border: 0;
  border-radius: 6px;
  background: none;
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}

.ws-more:hover {
  color: var(--fg);
  background: var(--surface-2);
}

.ws-empty { margin: 2px 0 0; }

body.hub-workspace .server-tabs,
body.hub-workspace #add-server,
body.hub-workspace #live-chip {
  display: none !important;
}

.ticket {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 10px;
  background: var(--bg);
}

.ticket h4 {
  margin: 0 0 6px;
  font-size: 14px;
}

.ticket p {
  margin: 0;
  white-space: pre-wrap;
}

.ticket .ticket-reply {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}

.limit {
  margin-top: 10px;
  color: var(--muted);
  font-size: 12px;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.chip {
  border: 1px solid var(--line);
  background: var(--bg);
  border-radius: 999px;
  padding: 5px 10px;
  font-size: 12px;
  color: var(--fg);
}

.chip b {
  color: var(--muted);
  font-weight: 600;
  margin-right: 6px;
}

.timer {
  font-size: 34px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.match-maps,
.next-map {
  color: var(--muted);
  margin-top: 4px;
}

.match-maps {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.start-players {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  flex-wrap: wrap;
}

.start-players label {
  font-size: 16px;
  color: var(--muted);
}

.start-players input {
  width: 72px;
}

#start-players-apply {
  height: 44px;
  font-size: 16px;
}

#start-players-next {
  height: 44px;
  font-size: 16px;
}

#queue-map {
  width: auto;
  min-width: 9.5rem;
}

#start-players-hint {
  margin: 8px 0 0;
}

.listing-preview {
  display: block;
  width: 100%;
  max-width: 512px;
  aspect-ratio: 4 / 1;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--bg);
  margin-top: 4px;
}

.settings-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 20px;
}

/* A field is a grid of auto rows, so a short one (no hint under it) would
   otherwise spread its rows over the full row height and push its input out of
   line with the taller field beside it. Pack the rows at the top instead, and
   give every label row the same height so the inputs start on one line. */
.settings-grid .field {
  margin-bottom: 0;
  align-content: start;
}

.settings-grid .settings-label {
  min-height: 22px;
}

@media (max-width: 860px) {
  .settings-grid,
  .settings-grid-4 {
    grid-template-columns: 1fr;
  }
}

/* Game settings is a long form, so it is cut into named sections. Each section
   is a card-inside-a-card: title, one line of context, then its own grid. */
.settings-section {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.settings-section:first-of-type {
  margin-top: 4px;
  padding-top: 0;
  border-top: 0;
}

.settings-section-title {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg);
}

.settings-section-hint {
  margin: 4px 0 14px;
  font-size: 12px;
  color: var(--muted);
}

/* Key for the timing badges on the fields below it. */
.badge-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
}

.badge-legend-title {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-right: 2px;
}

.settings-grid-4 {
  grid-template-columns: repeat(4, 1fr);
}

@media (max-width: 1180px) {
  .settings-grid-4 {
    grid-template-columns: 1fr 1fr;
  }
}

/* Banner URL keeps its preview beside the input instead of below the hint. */
.banner-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 16px;
  align-items: start;
}

.banner-input {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.banner-row .listing-preview {
  max-width: 100%;
  margin-top: 0;
}

@media (max-width: 860px) {
  .banner-row {
    grid-template-columns: 1fr;
  }
}

.settings-grid .field .hint {
  margin: 0;
}

.settings-label {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.settings-label label {
  margin: 0;
}

.apply-badge {
  flex: none;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 999px;
  padding: 3px 8px;
  white-space: nowrap;
}

.apply-badge.live {
  color: var(--badge-live);
  border: 1px solid color-mix(in srgb, var(--badge-live) 55%, transparent);
}

.apply-badge.next {
  color: var(--badge-next);
  border: 1px solid color-mix(in srgb, var(--badge-next) 55%, transparent);
}

.apply-badge.restart {
  color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 55%, transparent);
}

.apply-badge.pending {
  color: var(--info);
  border: 1px solid color-mix(in srgb, var(--info) 55%, transparent);
}

.settings-span {
  grid-column: 1 / -1;
}

/* Game settings, Daily restart: 24h hour/minute selects instead of the browser time picker,
   which ignores the skin and shows AM/PM. */
.restart-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.restart-row .ctrl {
  width: auto;
  min-width: 82px;
}

.restart-colon,
.restart-utc {
  color: var(--muted);
  font-weight: 700;
}

.restart-row .btn {
  margin-left: auto;
}

.restart-row .btn.is-written {
  color: var(--good);
  border-color: color-mix(in srgb, var(--good) 55%, transparent);
  opacity: 1;
}

.restart-state {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--muted);
}

.restart-state.is-written { color: var(--good); }
.restart-state.is-pending { color: var(--warn); }

.tick-row {
  display: grid;
  grid-template-columns: 1fr 72px;
  gap: 10px;
  align-items: center;
}

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

.settings-result {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  font-size: 13px;
  line-height: 1.45;
}

.settings-result h4 {
  margin: 12px 0 6px;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.settings-result h4:first-child {
  margin-top: 0;
}

.settings-result ul {
  margin: 0;
  padding-left: 18px;
}

.feed-token-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.feed-token-row .ctrl {
  flex: 1 1 220px;
  min-width: 0;
}

.feed-match {
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg);
  margin-top: 10px;
}

.feed-match-head {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  padding: 12px 14px;
  cursor: pointer;
}
/* Feed kill log. Time, Match, Server · Map and Dist are exactly as wide as their content;
   Killer, Victim, Hit and Weapon (.feed-col-player / -hit / -weapon) have no width and share
   the rest equally, so the table always fills the card without stretching the fixed columns.
   Fixed layout, so a sort never reflows it; below min-width it scrolls inside .table-wrap. */
.feed-kills {
  width: 100%;
  min-width: 105.5em;               /* the four shared columns keep ~13em each at the minimum */
  table-layout: fixed;
  border-collapse: collapse;
}

.feed-col-time { width: 8em; }     /* "2026-09-15", with the clock on the line below */
.feed-col-match { width: 6.5em; }  /* "#b48565" + time into the match */
.feed-col-server { width: 29em; }  /* whole "#4 | WARDOGS D-A-CH powered by Qonzer | GER | Standard" */
.feed-col-dist { width: 9em; }     /* bold "12345 m" plus cell padding, in the wider theme fonts too */

/* Server · Map is the first column to give way: once the card is narrower than the table, it
   drops to the "#4" in front of the server name (name and map stay in the tooltip), and the table
   needs 22em less before it scrolls. Container query lengths resolve against .feed-wrap, so it
   takes the table's 13px to keep the breakpoint in the same em as the .feed-kills min-width. */
.feed-wrap {
  container: feed-kills / inline-size;
  font-size: 13px;
}

.feed-kills .label-short { display: none; }

@container feed-kills (max-width: 105.5em) {
  .feed-kills { min-width: 83.5em; }
  .feed-col-server { width: 7em; }   /* "#12", and the "Server" heading plus its sort mark */
  .feed-kills .label-full,
  .feed-kills .feed-server-map { display: none; }
  .feed-kills .label-short { display: inline; }
}

.feed-kills th.feed-center { text-align: center; }
.feed-kills th.feed-right { text-align: right; }     /* "1712 m" plus the sort mark */

.feed-match-head::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  flex: 0 0 auto;
  color: var(--muted);
}

.feed-match.open .feed-match-head::before {
  content: "▾";
  color: var(--primary);
}

.feed-match-title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
  min-width: 0;
  flex: 1;
}

.feed-match-title b {
  font-size: 14px;
}

.feed-map {
  color: var(--fg);
  font-weight: 600;
}

.feed-match-stats {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  font-size: 12px;
  flex: 0 0 auto;
}

.feed-live {
  color: var(--manticore);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 11px;
}

.feed-match-players {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 14px 10px 42px;
}

.feed-chip {
  padding: 3px 8px;
  font-size: 11px;
}

.feed-match-body {
  display: none;
  padding: 0 10px 12px;
  border-top: 1px solid var(--line);
}

.feed-match.open .feed-match-body {
  display: block;
}

.feed-match-meta {
  color: var(--muted, inherit);
  font-size: 12px;
  margin-top: 4px;
}


.feed-kills th {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

.feed-kills td {
  padding: 8px 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  font-size: 13px;
  vertical-align: middle;
  overflow: hidden;
  text-overflow: ellipsis;
}

.feed-kills td.feed-arrow {
  width: 1%;
  color: var(--muted);
  padding-left: 0;
  padding-right: 0;
}

/* Table values that set a filter-row dropdown when clicked (kill feed and audit log). */
.cell-pick {
  display: block;
  max-width: 100%;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  padding: 0;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Faction of killer / victim when the kill arrived (from the server's player list). */
.cell-pick.fac-valkyra { color: var(--valkyra); }
.cell-pick.fac-lonestar { color: var(--lonestar); }
.cell-pick.fac-manticore { color: var(--manticore); }

.cell-pick:hover {
  color: var(--primary);
}

.feed-name {
  font-weight: 600;
}

.feed-sub {
  display: block;
  color: var(--muted);
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Match id: fixed-width digits so the ids line up down the column. */
.cell-pick.feed-mono {
  font-family: var(--mono);
  font-size: 12px;
}

/* Player stats under the kill log: same look, narrower, numbers right-aligned. */
.feed-kills.feed-stats {
  min-width: 36em;
}

.feed-col-stat { width: 9em; }

.feed-stats th:not(:first-child),
.feed-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.feed-steam {
  display: block;
  background: none;
  border: 0;
  color: var(--muted);
  font: inherit;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  padding: 1px 0 0;
  text-align: left;
}

.feed-steam:hover {
  color: var(--primary);
}

.feed-weapon {
  white-space: nowrap;
}

/* Tags and the "—" for none sit centred, so filled and empty rows line up. */
.feed-hitpart {
  text-align: center;
  white-space: normal;
}

.feed-hitpart .feed-tag {
  margin: 2px;
  vertical-align: middle;
}

.feed-dist {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  text-align: right;
  white-space: nowrap;
}

/* Date over clock at every width. Most rows are already two lines high because the
   player name sits above the Steam ID, so the second line usually costs no height,
   and every stamp column gets by on 8em instead of the 11-14.5em a one-line stamp needed. */
.feed-time,
.audit-time,
.db-time {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.25;
}

/* Without this the .audit-table td ellipsis rule clips the clock line. */
.audit-time {
  overflow: visible;
}

/* Each half owns its line; nowrap keeps the date from breaking at its hyphens
   if a theme font ever runs wider than the column. */
.stamp-date,
.stamp-time {
  display: block;
  white-space: nowrap;
}

.stamp-time {
  opacity: 0.75;
}

.feed-mark {
  white-space: nowrap;
}

.feed-tag {
  display: inline-block;
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 2px 6px;
  margin-right: 4px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--muted);
}

/* The distance is a button on a long shot (the Long shot kill type), and .cell-pick would
   left-align it out of the column. */
.feed-dist .cell-pick {
  text-align: right;
  margin-left: auto;
}

/* Tags are buttons: they set the Kill type filter (feedKindTag / feedMarkerTag in app.js). The
   tag's own colour is the border and text colour, so the hover tint works for every severity. */
button.feed-tag:hover {
  border-color: currentColor;
  background: color-mix(in srgb, currentColor 16%, transparent);
}

.feed-tag.hs {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}

/* Kill Feed markers (FeedKillMarkers): alert = a rule fired, worth reviewing; watch = worth a look.
   The row tints below carry :root so they outrank the british / german even-row stripes
   (`[data-brand] tbody tr:nth-child(even) td`), which load later and used to hide every
   second tinted row in those skins. */
.feed-tag.alert {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 70%, transparent);
  font-weight: 700;
}

.feed-tag.watch {
  color: var(--watch);
  border-color: color-mix(in srgb, var(--watch) 70%, transparent);
  font-weight: 700;
}

:root .feed-kills tr.feed-alert td {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

:root .feed-kills tr.feed-watch td {
  background: color-mix(in srgb, var(--watch) 12%, transparent);
}

.feed-tag.team {
  color: var(--teamkill);
  border-color: color-mix(in srgb, var(--teamkill) 70%, transparent);
  font-weight: 700;
}

/* Players → Log. Same tags and alert tint as the Kill Feed; its own widths,
   since it has five columns where the kill log has eight. */
.slog-table {
  width: 100%;
  min-width: 52em;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 13px;
}

.slog-col-time { width: 8em; }
.slog-col-server { width: 16em; }
.slog-col-tags { width: 14em; }

.slog-table td {
  vertical-align: middle;
  overflow: hidden;
  text-overflow: ellipsis;
}

.slog-table .label-short { display: none; }

.slog-event .cell-pick {
  display: inline;
  width: auto;
}

.slog-arrow {
  color: var(--muted);
  padding: 0 2px;
}

:root .slog-table tr.feed-alert td {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

:root .feed-kills tr.feed-team td {
  background: color-mix(in srgb, var(--teamkill) 12%, transparent);
}

.feed-num.alert {
  color: var(--accent);
  font-weight: 700;
}

.feed-num.watch {
  color: var(--watch);
  font-weight: 700;
}

:root .feed-kills tr.feed-long td {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}

.feed-kills tr.feed-long .feed-name,
.feed-kills tr.feed-long .feed-steam,
.feed-kills tr.feed-long .feed-weapon,
.feed-kills tr.feed-long .feed-hitpart,
.feed-kills tr.feed-long .feed-dist,
.feed-kills tr.feed-long .feed-time,
.feed-kills tr.feed-long .feed-time .stamp-time {
  color: var(--accent);
}

.feed-kills tr.feed-long .feed-dist {
  font-weight: 700;
}

/* Room above a table that Previous / Next scrolls back to (scrollToTableTop). */
.card .table-wrap {
  scroll-margin-top: 16px;
}

.feed-pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

#feed-events-body td,
.feed-match-body td {
  font-size: 13px;
}

.feed-detail {
  margin-top: 12px;
  padding: 12px;
  max-height: 360px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
  border: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  border-radius: 8px;
}

.feed-setup #feed-setup-detail {
  margin-top: 4px;
}

.feed-setup #feed-setup-detail > summary,
.feed-setup > summary {
  cursor: pointer;
  list-style: none;
}

.feed-setup #feed-setup-detail > summary::-webkit-details-marker {
  display: none;
}

@media (max-width: 860px) {
  .feed-match-head {
    flex-wrap: wrap;
    align-items: flex-start;
  }

  .feed-match-stats {
    width: 100%;
    padding-left: 1.4em;
  }

  .feed-name {
    max-width: 140px;
  }
}

.feed-setup > summary::-webkit-details-marker {
  display: none;
}

.feed-setup > summary.card-head {
  margin-bottom: 0;
}

.feed-setup[open] > summary.card-head {
  margin-bottom: 12px;
}

.feed-token-cell {
  font-family: inherit;
  font-size: 12px;
  word-break: break-all;
}

.feed-hosts {
  display: grid;
  gap: 14px;
  margin-top: 4px;
}

.feed-host {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
}

.feed-host-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.feed-host-name {
  font-weight: 600;
  line-height: 1.35;
}

.feed-host-acts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  flex-shrink: 0;
}

.feed-host-meta {
  display: grid;
  gap: 8px;
  margin: 12px 0 0;
}

.feed-host-meta > div {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 8px;
  align-items: start;
}

.feed-host-meta dt {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  padding-top: 2px;
}

.feed-host-meta dd {
  margin: 0;
  word-break: break-all;
  font-size: 13px;
}

.feed-forward {
  display: grid;
  gap: 10px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.feed-forward .lbl {
  display: grid;
  gap: 6px;
}

.feed-forward .ctrl {
  max-width: 520px;
}

.feed-forward-actions {
  display: flex;
  gap: 8px;
}

.field.gs-dirty {
  border-left: 2px solid var(--primary);
  padding-left: 10px;
}

.gs-stage {
  position: fixed;
  left: calc(var(--nav-w) + 22px);
  right: 22px;
  bottom: 16px;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin: 0;
  padding: 12px 14px;
  border: 1px solid color-mix(in srgb, var(--primary) 50%, transparent);
  border-radius: 10px;
  background: color-mix(in srgb, var(--surface) 92%, var(--primary) 8%);
  box-shadow: var(--shadow-lift);
}

body.has-gs-stage .main {
  padding-bottom: 96px;
}

.gs-stage-copy {
  min-width: 0;
  font-size: 13px;
  line-height: 1.4;
}

.gs-stage-copy strong {
  display: block;
}

#gs-stage-list {
  color: var(--muted);
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gs-stage-actions {
  display: flex;
  flex: none;
  gap: 8px;
}

#ff-card,
#hpk-card,
#match-announce-card {
  margin-top: 14px;
}

.hpk-actions {
  margin-top: 12px;
}

/* Server → Auto punish. Palette comes from the skin tokens only. */
#ap-shared {
  flex: none;
  white-space: nowrap;
}

/* Label plus its "?" on one line; the label keeps its own look. */
.ap-lbl {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.ap-guide {
  margin: 12px 0 2px;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
}

.ap-guide summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--fg);
}

.ap-guide ol {
  display: grid;
  gap: 6px;
  margin: 10px 0 2px;
  padding-left: 20px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg);
}

.ap-guide b {
  font-weight: 600;
}

/* Servers → Sharing between servers: one row per server, four Off/On switches and Apply. */
.share-table td {
  vertical-align: middle;
}

.share-table .ctrl {
  width: auto;
  min-width: 76px;
}

.share-table .actions-row {
  flex-wrap: nowrap;
}

/* Apply stays greyed until a switch in its row changes. */
.share-table .btn:disabled {
  opacity: 0.45;
  cursor: default;
}

#atab-autopunish .settings-section:first-of-type {
  margin-top: 16px;
}

.ap-list {
  font-family: var(--mono);
  font-size: 13px;
  resize: vertical;
  min-height: 92px;
}

/* One line per step: label, action, delay, ban days, message. */
.ap-step {
  display: grid;
  grid-template-columns: 64px 170px 170px 110px minmax(0, 1fr);
  gap: 10px 12px;
  align-items: end;
  margin-top: 14px;
}

.ap-step .field {
  margin-bottom: 0;
  min-width: 0;
}

.ap-step-no {
  align-self: center;
  padding-top: 18px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg);
}

/* A field that does not apply to the chosen action (ban days on a kick, anything
   after "Nothing"): dimmed label and control, control disabled in JS. */
.ap-step .field.ap-na {
  opacity: 0.45;
}

.ap-step .field.ap-na .ctrl {
  cursor: not-allowed;
}

/* Names → Blocked characters: one slide switch (.req-toggle) per character set. */
.ap-charsets {
  margin-top: 14px;
}

.ap-charset-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
}

.ap-charset-list .hint {
  margin-left: 2px;
}

.ap-try {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}

.ap-try .ctrl {
  flex: 0 1 280px;
}

#ap-try-result.ap-hit {
  color: var(--bad);
}

#ap-try-result.ap-miss {
  color: var(--good);
}

/* Auto punish → Weapons & vehicles: rule list and the strike rows (no delay column). */
.wp-card {
  margin-top: 16px;
}

.wp-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}

.wp-row:first-child {
  border-top: 0;
}

.wp-row-main {
  flex: 1;
  min-width: 0;
}

.wp-row-main .hint {
  margin: 2px 0 0;
  overflow-wrap: anywhere;
}

.wp-row .chip.wp-on {
  border-color: var(--good);
  color: var(--good);
}

.ap-step.wp-step {
  grid-template-columns: 64px 170px 110px minmax(0, 1fr);
}

@media (max-width: 860px) {
  .ap-step {
    grid-template-columns: 1fr 1fr;
  }

  .ap-step-no {
    grid-column: 1 / -1;
    padding-top: 0;
  }

  .ap-step .ap-msg {
    grid-column: 1 / -1;
  }
}

.composer {
  display: grid;
  gap: 10px;
}

.composer-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
}

.actions-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.rot-raw {
  width: 100%;
  min-height: 220px;
  max-height: 420px;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.45;
  resize: vertical;
  white-space: pre-wrap;
}

.rot-row .actions-row {
  flex-wrap: nowrap;
  justify-content: flex-end;
}

.audit-target {
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.25;
}

.audit-target b {
  font-weight: 600;
}

.audit-target span {
  color: var(--muted);
  font-size: 12px;
  font-family: var(--mono);
}

/* Fixed column widths, so a sort that brings other rows onto the page does not
   reflow the table. Detail takes the rest and wraps; narrow screens scroll in .table-wrap. */
.audit-table {
  table-layout: fixed;
  min-width: 63.5em;
}

/* em follows the table font (13px), so the widths scale if that ever changes. */
.audit-col-time { width: 8em; }      /* "2026-09-15", with the clock on the line below */
.audit-col-admin { width: 11em; }
.audit-col-action { width: 8.5em; }  /* longest label: "Start players" */
.audit-col-target { width: 18em; }   /* player name + 17-digit Steam ID */

.audit-table td {
  overflow: hidden;
  text-overflow: ellipsis;
}

.audit-table .audit-target > * {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.audit-table td:last-child {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Database tab: same fixed layout; Player takes the rest. */
.db-table {
  table-layout: fixed;
  min-width: 92em;
}

.db-col-steam { width: 16em; }    /* 17-digit Steam ID + Copy */
.db-col-server { width: 29em; }   /* "#4 | WARDOGS D-A-CH powered by Qonzer | GER | Standard" */
.db-col-note { width: 18em; }     /* note preview wraps inside its own cell */
.db-col-time { width: 8.5em; }    /* "2026-09-15" over the clock; 8.5 so "First seen" stays one line */

.db-table td:not(.db-note-cell) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The note preview is the one cell that wraps; the global td nowrap would
   otherwise push it over the Last seen column. */
.db-table td.db-note-cell {
  white-space: normal;
  overflow: hidden;
}

/* Both stamp columns stack date over clock, so they need out of that nowrap too.
   Scoped to .db-table td to outrank the :not(.db-note-cell) rule above. */
.db-table td.db-time {
  white-space: normal;
  overflow: visible;
}

/* Filter row above the audit log and feed tables: --filter-count dropdowns, then the free-text
   search taking the remaining width. Colors come from .ctrl / .menu, so themes apply. */
.filter-row {
  display: grid;
  grid-template-columns: repeat(var(--filter-count, 3), minmax(0, 15em)) minmax(12em, 1fr);
  gap: 8px;
  margin-bottom: 10px;
}

.filter-row .combo,
.filter-row .ctrl {
  width: 100%;
}

@media (max-width: 760px) {
  .filter-row {
    grid-template-columns: 1fr 1fr;
  }
}

/* ---------- Combobox (createCombobox in app.js) ---------- */
.combo {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.combo .combo-input {
  padding-right: 2em;
}

/* Text weight only: themes draw input borders very differently (bevels, glass, pills). */
.combo.has-value .combo-input {
  font-weight: 600;
}

.combo-clear {
  position: absolute;
  right: 4px;
  width: 1.7em;
  height: 1.7em;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.combo-clear:hover {
  color: var(--fg);
  background: color-mix(in srgb, currentColor 14%, transparent);
}

/* The list is also a .menu, so its surface comes from .menu and each theme's .menu
   override. This rule only places it under the field (and beats .menu's position: fixed). */
.combo .combo-list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 45;
  min-width: 100%;
  width: max-content;
  max-width: min(30em, 90vw);
  max-height: 22em;
  overflow-y: auto;
  font-size: 13px;
  /* Reset what toolbars pass down (laffetie's navy .card-head sets white bold text). */
  color: var(--fg);
  font-weight: normal;
  letter-spacing: normal;
  text-transform: none;
}

/* Some themes give .menu a see-through surface; blur what is behind the list so options stay
   readable. Kept at low specificity so themes with their own backdrop-filter (niklas, win7) win. */
.combo-list {
  backdrop-filter: blur(16px);
}

.combo-group {
  padding: 8px 10px 3px;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.combo-opt {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.5em;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}

/* Same highlight as .menu button:hover, so options match the theme's other menus. */
.combo-opt.active,
.combo-opt:hover {
  background: var(--surface-2);
}

.combo-opt.selected .combo-label {
  font-weight: 600;
}

.combo-detail {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
}

.combo-empty {
  padding: 8px 10px;
  color: var(--muted);
}

/* Multi-select (createMultiCombobox): the .ctrl box holds the chips and a borderless input. */
.combo-multi .combo-box {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  min-width: 0;
  padding-right: 2em;
  overflow: hidden;
  cursor: text;
}

.combo-multi .combo-box:focus-within {
  border-color: var(--primary);
}

.combo-multi .combo-chips {
  display: contents;
}

.combo-multi .combo-input {
  flex: 1 1 4em;
  min-width: 3em;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  box-shadow: none;
}

.combo-chip {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: 0 1 auto;
  min-width: 0;
  max-width: 9em;
  padding: 1px 2px 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--primary) 18%, transparent);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}

.combo-chip-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

.combo-chip-more {
  flex: 0 0 auto;
  padding-right: 7px;
}

.combo-chip-x {
  flex: 0 0 auto;
  width: 1.4em;
  height: 1.4em;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}

.combo-chip-x:hover {
  color: var(--fg);
  background: color-mix(in srgb, currentColor 14%, transparent);
}

/* Tick box in front of each option: what is in the filter right now. */
.combo-multi .combo-opt {
  justify-content: flex-start;
}

.combo-multi .combo-opt .combo-detail {
  margin-left: auto;
}

.combo-check {
  flex: 0 0 auto;
  align-self: center;
  width: 14px;
  height: 14px;
  border: 1.5px solid var(--muted);
  border-radius: 3px;
}

.combo-opt.selected .combo-check {
  border-color: var(--primary);
  background: var(--primary);
  box-shadow: inset 0 0 0 2px var(--surface, #fff);
}

/* ---------- Command bar ---------- */

.cmd {
  display: grid;
  gap: 10px;
}

.cmd-row {
  display: grid;
  grid-template-columns: 180px 1fr auto;
  gap: 8px;
}

.cmd-extra {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

/* ---------- Tables ---------- */

.pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.pill {
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--muted);
  border-radius: 999px;
  padding: 5px 10px;
  cursor: pointer;
}

.pill.active {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-ink);
}

.pill.valkyra.active { background: var(--valkyra); border-color: var(--valkyra); color: #fff; }
.pill.lonestar.active { background: var(--lonestar); border-color: var(--lonestar); color: #0b0f12; }
.pill.manticore.active { background: var(--manticore); border-color: var(--manticore); color: #0b0f12; }

.table-wrap {
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
}

#users-body .user-role-pick {
  min-width: 10rem;
  width: auto;
  max-width: 14rem;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

th,
td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

.player-table {
  table-layout: fixed;
}

.player-table th.time-col,
.player-table td.time-col {
  width: 5.4rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 12px;
}

.player-table th.player-name-col,
.player-table td.player-col {
  width: 24%;
}

.player-table th.acts-head,
.player-table td.acts-col {
  width: 32%;
}

.player-table th.stat-head,
.player-table td.stat-col {
  width: 11%;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.player-table th[data-sort],
.audit-table th[data-audit-sort],
.db-table th[data-db-sort],
.flag-table th[data-flag-sort],
.feed-kills th[data-feed-sort],
.feed-stats th[data-stats-sort] {
  cursor: pointer;
  user-select: none;
}

.player-table th[data-sort]:hover,
.audit-table th[data-audit-sort]:hover,
.db-table th[data-db-sort]:hover,
.flag-table th[data-flag-sort]:hover,
.feed-kills th[data-feed-sort]:hover,
.feed-stats th[data-stats-sort]:hover {
  color: var(--fg);
}

.player-table th[aria-sort],
.audit-table th[aria-sort],
.db-table th[aria-sort],
.feed-kills th[aria-sort] {
  color: var(--primary);
}

.player-table th[data-sort] .s-dir,
.audit-table th[data-audit-sort] .s-dir,
.db-table th[data-db-sort] .s-dir,
.flag-table th[data-flag-sort] .s-dir,
.feed-kills th[data-feed-sort] .s-dir,
.feed-stats th[data-stats-sort] .s-dir {
  margin-left: 4px;
  font-size: 10px;
  letter-spacing: 0;
}

td.player-col {
  white-space: nowrap;
}

td.acts-col {
  white-space: normal;
}

tr.faction-valkyra td:first-child {
  box-shadow: inset 3px 0 0 var(--valkyra);
}

tr.faction-lonestar td:first-child {
  box-shadow: inset 3px 0 0 var(--lonestar);
}

tr.faction-manticore td:first-child {
  box-shadow: inset 3px 0 0 var(--manticore);
}

.player-who .name-valkyra,
.player-who .name-lonestar,
.player-who .name-manticore {
  font-weight: 600;
}

.player-acts {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}

/* Natural width, not stretched: the buttons used to grow into the whole
   Actions column and ended up sitting directly under the Kills header. */
.player-acts .btn {
  flex: 0 0 auto;
  min-width: 4.25rem;
  padding: 5px 8px;
  font-size: 11px;
}

th {
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: color-mix(in srgb, var(--bg) 70%, var(--surface));
}

tr:last-child td {
  border-bottom: 0;
}

.dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 6px;
}

.dot.valkyra { background: var(--valkyra); }
.dot.lonestar { background: var(--lonestar); }
.dot.manticore { background: var(--manticore); }
.dot.total { background: var(--primary); }

.name-valkyra { color: var(--valkyra); }
.name-lonestar { color: var(--lonestar); }
.name-manticore { color: var(--manticore); }

.sid {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 11px;
}


/* The gameserver's own ban list did not answer: the rows below are second-hand. */
.bans-warn {
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  border-left: 3px solid var(--warn);
  padding: 10px 12px;
  font-size: 12px;
}

.db-sid {
  font-family: var(--mono);
  font-size: 12px;
  user-select: all;
}

.db-copy {
  margin-left: 8px;
}

/* ---------- Flagged players ----------
 * One colour for every flagged mark: --flag, set per skin in css/themes/.
 * Marks are painted by paintFlagMarks (app.js) onto whatever the renderers tag:
 *   [data-flag-steam].is-flagged       a player name, anywhere
 *   tr[data-flag-row].is-flagged-row   a row that is one player (Overview, Players, Database, Flagged)
 *   tr[data-flag-half].is-flagged-half a Kill Feed row naming a flagged player (left half only)
 *   .btn-flag(.is-on)                  the Flag / Flagged button
 * The ⚑ glyph keeps the mark readable without relying on colour alone.
 * Skins load after this file, so wherever a skin styles the same element (win95 .btn,
 * british .nav-count, british / german row stripes) the selector here is made more specific. */

/* A flagged name stays in its team colour (.name-* on the scoreboard, .fac-* in the Kill
   Feed) and only turns bold; the purple ⚑ and the purple row carry the flag. Names with no
   team colour (Database, Flagged list, profile title) turn purple themselves. */
[data-flag-steam].is-flagged,
.player-who .player-link.is-flagged,
.feed-kills tr .feed-name.is-flagged {
  font-weight: 700;
}

[data-flag-steam].is-flagged:not([class*="name-"]):not([class*="fac-"]) {
  color: var(--flag);
}

[data-flag-steam].is-flagged::before {
  content: "\2691";
  margin-right: 4px;
  font-weight: 400;
  color: var(--flag);
}

/* :root + [data-flag-row] lift these to (0,3,2): british and german stripe even rows and
   tint hovered ones with `[data-brand] tbody tr:nth-child(even) td` (0,2,3), which loads
   later and would otherwise wash the purple out of every second flagged row. */
:root tr[data-flag-row].is-flagged-row td {
  background: color-mix(in srgb, var(--flag) 10%, transparent);
}

:root tr[data-flag-row].is-flagged-row:hover td {
  background: color-mix(in srgb, var(--flag) 18%, transparent);
}

/* Scoreboard rows keep their faction stripe on the left; only rows without a known team
   (Database, Flagged list, unknown faction) get a purple one instead. */
:root tr[data-flag-row].is-flagged-row:not(.faction-valkyra):not(.faction-lonestar):not(.faction-manticore) td:first-child {
  box-shadow: inset 3px 0 0 var(--flag);
}

/* Kill Feed: a kill naming a flagged player is purple on its left half only (time, match,
   server, killer); the right half (victim, hit, weapon, distance) keeps the kill-marker tint
   — alert, teamkill, watch, long shot — so both signals stay readable in one row. Player
   stats split the same way: player, kills, deaths purple; K/D and headshot % carry their
   own marker colours. The stats table also has .feed-kills, hence :not(.feed-stats). */
:root .feed-kills:not(.feed-stats) tr[data-flag-half].is-flagged-half td:nth-child(-n + 4),
:root .feed-stats tr[data-flag-half].is-flagged-half td:nth-child(-n + 3) {
  background: color-mix(in srgb, var(--flag) 14%, transparent);
}

:root .feed-kills tr[data-flag-half].is-flagged-half td:first-child {
  box-shadow: inset 3px 0 0 var(--flag);
}

/* Wide enough for the bold "Flagged", so the button keeps its size when it flips
   and never gets cut to an ellipsis in the fixed-width Database column. */
.btn.btn-flag {
  min-width: 5.75em;
  justify-content: center;
  text-align: center;
}

.btn.btn-flag.is-on {
  color: var(--flag);
  border-color: color-mix(in srgb, var(--flag) 70%, transparent);
  background: color-mix(in srgb, var(--flag) 14%, var(--surface));
  font-weight: 700;
}

.btn.btn-flag.is-on:hover {
  background: color-mix(in srgb, var(--flag) 24%, var(--surface));
}

.db-flag {
  margin-left: 6px;
}

/* Steam ID + Copy + Flag: only wider when the role can flag. The table grows by the
   same 6em so the Player column keeps its ~12em instead of paying for the button. */
.db-table:has(.db-flag) {
  min-width: 98em;
}

.db-table:has(.db-flag) .db-col-steam {
  width: 22em;
}

.nav .nav-count.nav-count-flag {
  background: var(--flag);
  color: var(--surface);
}

.player-flag-banner {
  border-left-color: var(--flag);
}

.player-flag-banner strong {
  color: var(--flag);
}

/* Profile penalties: the Flagged count, purple once it is above zero. */
.player-penalty.is-flag .k,
.player-penalty.is-flag .n {
  color: var(--flag);
}

.flag-online {
  display: inline-block;
  margin-left: 6px;
  padding: 0 6px;
  border: 1px solid color-mix(in srgb, var(--flag) 70%, transparent);
  border-radius: 999px;
  color: var(--flag);
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
}

/* Fixed layout like Database: the fixed columns add up to 80.5em (16em Steam column;
   the Flag button sits in its own column here), so at 96em Player keeps ~15.5em and the
   whole table still fits a 1600px screen next to the side nav without scrolling. */
.flag-table { min-width: 96em; }
/* Flagged → Personal flags: four columns, so far narrower than the workspace list. */
.personal-flag-table { min-width: 46em; }
.personal-flag-col-acts { width: 11em; }   /* "Personally flagged" */
.flag-col-reason { width: 18em; }
.flag-col-by { width: 9em; }
.flag-col-expires { width: 9.5em; }
.flag-col-server { width: 12em; }
.flag-col-acts { width: 7.5em; }

/* Expires: time left in the flag colour, the local end date under it like the other stamps. */
.flag-left {
  display: block;
  color: var(--flag);
  font-weight: 700;
}

.flag-until {
  display: block;
  color: var(--muted);
  font-size: 11px;
}

/* Which staff action set the flag (Warn / Kick / Temp ban), before the reason. */
.feed-tag.flag-source {
  color: var(--flag);
  border-color: color-mix(in srgb, var(--flag) 55%, transparent);
}

/* "Warned players are flagged …" under the Warn / Kick / Temp ban forms. */
.flag-side-effect {
  margin: 0 0 12px;
}

/* Reason wraps like the Database note preview; outranks .db-table td:not(.db-note-cell) by order. */
.db-table td.flag-reason {
  white-space: normal;
  overflow-wrap: anywhere;
}

/* ---------- Cash ---------- */

.cash-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.legend-btn {
  border: 1px solid var(--line);
  background: var(--bg);
  border-radius: 8px;
  padding: 8px 10px;
  cursor: pointer;
  text-align: left;
  min-width: 140px;
}

.legend-btn.off {
  opacity: 0.4;
}

.legend-btn .k {
  display: block;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.legend-btn .v {
  font-weight: 700;
}

.legend-btn .d {
  font-size: 11px;
}

.up { color: var(--manticore); }
.down { color: var(--valkyra); }

.cash-tools {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

#cash-canvas {
  width: 100%;
  height: 280px;
  display: block;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
}

.cash-tip {
  position: absolute;
  pointer-events: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 12px;
  display: none;
  z-index: 5;
  box-shadow: var(--shadow);
}

.cash-box {
  position: relative;
}

/* ---------- Accordion / tabs ---------- */

.tabs {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.acc {
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: 8px;
  background: var(--bg);
}

.acc-btn {
  width: 100%;
  text-align: left;
  background: var(--surface-2);
  border: 0;
  border-bottom: 1px solid var(--line);
  padding: 10px 12px;
  cursor: pointer;
  font-weight: 600;
}

.acc-body {
  padding: 12px;
  display: none;
}

.acc.open .acc-body {
  display: block;
}

.pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.sticky-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  margin-bottom: 12px;
}

.faq details {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: var(--bg);
}

.faq summary {
  cursor: pointer;
  font-weight: 600;
}

.host-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

/* ---------- Overlay ---------- */

.modal-back {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  display: grid;
  place-items: center;
  z-index: 40;
  padding: 16px;
}

.modal {
  width: min(460px, 100%);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 18px;
  box-shadow: var(--shadow);
}

/* Cases: the case dialog holds the evidence list, so it is wider and scrolls on its own. */
.modal.modal-wide {
  width: min(760px, 100%);
  max-height: calc(100vh - 32px);
  overflow-y: auto;
}

.case-table { min-width: 84em; }
.case-table .case-reason { max-width: 22em; }
.case-table tr.case-closed td { opacity: 0.6; }
.case-todo { color: var(--warn); }

.case-rules-list {
  list-style: none;
  margin: 10px 0 12px;
  padding: 0;
  max-width: 36rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}

.case-rules-list.is-empty {
  border-style: dashed;
}

.case-rules-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  border-top: 1px solid var(--line);
}

.case-rules-item:first-child {
  border-top: 0;
}

.case-rules-label {
  flex: 1;
  min-width: 0;
  line-height: 1.35;
}

.case-rules-del,
.case-rules-edit {
  flex: 0 0 auto;
}

.case-rules-empty {
  padding: 10px 12px;
}

.case-rules-add {
  display: flex;
  gap: 8px;
  align-items: center;
  max-width: 36rem;
}

.case-rules-add .ctrl {
  flex: 1;
  min-width: 0;
}

.case-ev-file-wrap {
  margin-top: 8px;
}

.case-ev-paste {
  margin-bottom: 8px;
  padding: 18px 12px;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  color: var(--muted);
  text-align: center;
  cursor: text;
  caret-color: transparent;
}

.case-ev-paste:empty::before {
  content: attr(data-placeholder);
}

.case-ev-paste.is-drag {
  border-color: var(--primary);
  color: var(--fg);
}

.case-ev-paste:focus {
  outline: 2px solid var(--primary);
  outline-offset: -1px;
  border-color: transparent;
}

.case-h {
  margin: 14px 0 8px;
  font-size: 14px;
}

.case-evidence h4 {
  display: flex;
  align-items: center;
  gap: 8px;
}

.case-evidence .case-evidence-del { margin-left: auto; }
.case-evidence .hint { margin-top: 6px; }

.case-log {
  margin: 0;
  max-height: 16em;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
}

.case-shot img {
  display: block;
  max-width: 100%;
  max-height: 22em;
  border-radius: 6px;
  border: 1px solid var(--line);
}

.case-add {
  display: grid;
  gap: 8px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}

.case-add-row {
  display: flex;
  gap: 8px;
}

.case-add-row input { flex: 1; }

/* A required case field left empty on Save; cleared once the field changes (markCaseMissing). */
.ctrl.is-missing {
  border-color: var(--bad) !important;
  box-shadow: 0 0 0 1px var(--bad);
}

.case-add.is-missing {
  outline: 2px solid var(--bad);
  outline-offset: 4px;
  border-radius: var(--radius, 6px);
}

/* Cases → Required case fields: one slide switch per field. */
.case-required-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin: 10px 0 6px;
}

.req-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

.req-toggle input {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex-shrink: 0;
  width: 30px;
  height: 17px;
  margin: 0;
  border-radius: 999px;
  background: var(--line);
  cursor: pointer;
  transition: background .15s;
}

.req-toggle input::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--bg);
  transition: transform .15s;
}

.req-toggle input:checked {
  background: var(--primary);
}

.req-toggle input:checked::after {
  transform: translateX(13px);
  background: var(--primary-ink);
}

.req-toggle input:disabled {
  opacity: 0.5;
  cursor: default;
}

.req-toggle input:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

.modal h3 {
  margin: 0 0 8px;
  color: var(--fg);
  letter-spacing: 0;
  text-transform: none;
  font-size: 18px;
}

.menu {
  position: fixed;
  z-index: 45;
  min-width: 180px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 6px;
  box-shadow: var(--shadow);
}

.menu button {
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
}

.menu button:hover {
  background: var(--surface-2);
}

.help-tip {
  color: var(--muted);
  cursor: help;
  border: 1px solid var(--line);
  border-radius: 50%;
  width: 16px;
  height: 16px;
  display: inline-grid;
  place-items: center;
  font-size: 10px;
}

/* As a button (the "?" next to a label): drop the UA button look, keep the badge. */
button.help-tip {
  flex: none;
  padding: 0;
  background: transparent;
  font: inherit;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
}

button.help-tip:hover,
button.help-tip:focus-visible,
button.help-tip[aria-expanded="true"] {
  color: var(--primary);
  border-color: var(--primary);
  outline: none;
}

.help-pop {
  position: fixed;
  z-index: 95;
  max-width: min(360px, calc(100vw - 16px));
  padding: 10px 12px;
  background: var(--surface-2);
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-line;
}

.switch {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

@media (max-width: 980px) {
  .shell {
    grid-template-columns: 1fr;
  }

  .gs-stage {
    left: 12px;
    right: 12px;
  }

  .app {
    height: auto;
    overflow: visible;
  }

  .shell {
    overflow: visible;
  }

  .nav {
    display: none;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }

  .nav.open {
    display: flex;
  }

  .main {
    overflow: visible;
  }

  .nav-toggle {
    display: inline-flex;
  }

  .grid-2,
  .composer-row,
  .cmd-row,
  .cmd-extra,
  .pair,
  .scores,
  .host-grid {
    grid-template-columns: 1fr;
  }

  .ws-grid {
    columns: 1;
  }

  .live-chip {
    display: none;
  }
}

.site-faq {
  margin-top: 28px;
  padding: 18px 18px 8px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  border: 1px solid var(--line);
  border-radius: 12px;
}

.faq-modal {
  width: min(640px, 100%);
  max-height: min(82vh, 820px);
  overflow: auto;
}

.faq-back {
  z-index: 50;
  align-items: start;
  padding-top: 36px;
}

.faq-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 12px;
}

.faq-head h2 {
  margin: 0 0 4px;
  font-size: 18px;
}

.faq-brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.04em;
  flex-shrink: 0;
}

.faq-brand img {
  width: 28px;
  height: 28px;
  object-fit: contain;
}

.faq-brand:hover {
  color: var(--primary);
}

.site-faq > .btn {
  margin: 8px 0 10px;
}

.patchlog {
  display: grid;
  gap: 22px;
  margin-top: 4px;
}

.patchlog-group {
  position: relative;
  padding-left: 18px;
}

.patchlog-group::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 4px;
  width: 2px;
  border-radius: 1px;
  background: color-mix(in srgb, var(--primary) 35%, var(--line));
}

.patchlog-date {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.patchlog-date::before {
  content: "";
  position: absolute;
  left: 0;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--primary);
  box-sizing: border-box;
}

.patchlog-date span {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--primary) 14%, var(--surface));
  color: var(--primary);
  border: 1px solid color-mix(in srgb, var(--primary) 28%, var(--line));
}

.patchlog-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

.patchlog-item {
  margin: 0;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: color-mix(in srgb, var(--surface-2, var(--surface)) 88%, transparent);
}

.patchlog-item strong {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0 0 6px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
}

.patchlog-item p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}

.patchlog-tag {
  display: inline-flex;
  align-items: center;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10px;
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--line));
}

#tour-root {
  position: fixed;
  inset: 0;
  z-index: 70;
}

#tour-root[hidden] {
  display: none !important;
}

.tour-back {
  position: absolute;
  inset: 0;
}

.tour-spot {
  position: fixed;
  border: 2px solid var(--primary);
  border-radius: 10px;
  box-shadow: 0 0 0 9999px var(--spotlight);
  pointer-events: none;
}

.tour-card {
  position: fixed;
  pointer-events: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px;
  box-shadow: var(--shadow);
}

.tour-card h3 {
  margin: 0 0 8px;
  font-size: 17px;
}

.tour-card p {
  margin: 0 0 14px;
  color: var(--muted);
}

.tour-step {
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0 0 8px !important;
}

.tour-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

/* Prepare hosts result. Staff kept missing the toast and asked whether it had worked,
   so the outcome stays on the page until it is dismissed. */
.feed-result {
  position: relative;
  margin: 12px 0;
  padding: 14px 40px 14px 16px;
  border-radius: 10px;
  border: 1px solid color-mix(in srgb, var(--good) 55%, transparent);
  background: color-mix(in srgb, var(--good) 12%, transparent);
}

.feed-result.warn {
  border-color: color-mix(in srgb, var(--warn) 55%, transparent);
  background: color-mix(in srgb, var(--warn) 12%, transparent);
}

.feed-result h4 {
  margin: 0 0 6px;
  color: var(--good);
}

.feed-result.warn h4 {
  color: var(--warn);
}

.feed-result p {
  margin: 0;
}

.feed-result-foot {
  margin-top: 8px !important;
  opacity: 0.85;
  font-size: 13px;
}

.feed-result-close {
  position: absolute;
  top: 8px;
  right: 10px;
  padding: 0 6px;
  font-size: 20px;
  line-height: 1;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
  opacity: 0.6;
}

.feed-result-close:hover {
  opacity: 1;
}

/* Below the gameserver's floor for Players to start: the input keeps the value, the warning
   says why Apply will not take it. */
.start-players-warn {
  color: var(--warn);
  margin-top: 6px !important;
}

/* ==========================================================================
   INSIGHTS TAB
   Layout for #view-insights and the chart helper in js/insights-chart.js.
   Search: ins-toolbar, ins-chart, ins-tip, WDHInsightsChart
   ========================================================================== */

/* Categorical ramp for the weapon and staff-action charts: eight fixed slots, assigned by a
   row's position and never cycled, so a filter that drops a weapon does not repaint the rest.
   Both sets were checked for colour-blind separation against their own surface rather than
   picked by eye; the light one is the default because six of the eight skins are light.
   Faction colours are not in here - those follow the faction (--valkyra and friends). */
:root {
  --ins-c1: #1565c9;
  --ins-c2: #c07a12;
  --ins-c3: #7b4fc9;
  --ins-c4: #a8432c;
  --ins-c5: #0f8fb0;
  --ins-c6: #7a8a1e;
  --ins-c7: #c2317e;
  --ins-c8: #3d9e5c;
}

[data-brand="dark"],
[data-brand="qonzer"],
[data-brand="wardogs"] {
  --ins-c1: #3f82d6;
  --ins-c2: #b87d1f;
  --ins-c3: #8f6fd8;
  --ins-c4: #c96a4c;
  --ins-c5: #1d9db8;
  --ins-c6: #879a24;
  --ins-c7: #cf4a8f;
  --ins-c8: #3fa96a;
}

/* One rhythm for the whole tab. .view is a plain block and .card carries no margin, so
   stacked cards touched while the grids inside them kept a 14px gap - the same distance read
   as nothing in one place and a gutter in another. A flex column with a single gap is what
   every dashboard layout does, and it makes the spacing between two cards, between two grid
   rows and between a card and a grid identical by construction. */
#view-insights.view.active {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.ins-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.ins-toolbar > #ins-server-filter {
  min-width: 200px;
}

.ins-dates {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}

.ins-dates .ctrl {
  width: auto;
}

/* No pill is lit while a custom range is picked, so the inputs carry the "this is the filter"
   cue instead. Weight only, like the combobox: themes draw input borders very differently. */
.ins-dates.is-custom .ctrl {
  font-weight: 600;
}

.ins-toolbar .ins-status {
  margin: 0 0 0 auto;
  text-align: right;
}

.ins-note {
  margin: 0;
  color: var(--warn);
}

/* The canvas sizes itself from this box, so it needs a height that does not depend on it. */
.ins-chart {
  position: relative;
  width: 100%;
  height: 220px;
  margin-top: 10px;
}

.ins-chart canvas {
  width: 100%;
  height: 100%;
  display: block;
}

.ins-chart-donut {
  height: 240px;
}

.ins-chart-heat {
  height: 190px;
}

/* One tooltip per chart, created by insights-chart.js and positioned inside .ins-chart. */
.ins-tip {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px 9px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--fg);
  box-shadow: var(--shadow);
  white-space: nowrap;
}

.ins-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: 6px;
  vertical-align: baseline;
}

/* Identity is never colour alone: every series carries its name next to the swatch. */
.ins-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 11px;
  color: var(--muted);
}

.ins-legend-item {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

/* Chart beside its table, stacking on a narrow screen. */
.ins-split {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) minmax(0, 2fr);
  gap: 14px;
  align-items: start;
  margin-top: 10px;
}

.ins-table {
  width: 100%;
  /* .db-table carries min-width: 92em for the Database tab's wide grid. Inheriting it forced
     every table here past its card and hid the number columns behind a scrollbar, which is
     what made the weapon header and the staff tables unreadable. */
  min-width: 0;
  /* Fixed layout is what makes the colgroup binding: the number columns get exactly the width
     they ask for and the label column takes the rest, instead of every column claiming its
     content width and pushing the table out past its card behind a scrollbar. */
  table-layout: fixed;
  font-variant-numeric: tabular-nums;
}

.ins-table td:not(:first-child),
.ins-table th:not(:first-child) {
  text-align: right;
}

/* Headers may wrap; a two-word heading over a narrow number column is fine, one that overflows
   into its neighbour is not. */
.ins-table th {
  white-space: normal;
  line-height: 1.25;
  vertical-align: bottom;
}

.ins-table td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The label column takes whatever the number columns leave. Under a fixed layout that is what
   an unset width means, so this is here to say so rather than to change anything. */
.ins-col-label {
  width: auto;
}

.ins-col-n {
  width: 4.5rem;
}

.ins-col-w {
  width: 6rem;
}

/* Weapons and Top players list up to a hundred rows. Left alone they would push their card
   down the page and leave the chart beside them stranded at the top, so the list scrolls
   inside the card instead. */
.ins-scroll {
  max-height: 22em;
  overflow-y: auto;
}

/* The header has to survive the scroll, or row forty is six unlabelled numbers. Tables here
   are border-collapse, which drops a sticky cell's own border, so the rule under the header
   is painted as an inset shadow; the background must be opaque for the rows passing beneath. */
.ins-scroll thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface);
  border-bottom: 0;
}

/* Chrome paints an inset shadow on a sticky cell of a collapsed table only on the first cell,
   so the rule stopped after the label column. A 1px bar per cell runs under every column. */
.ins-scroll thead th::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--line);
}

/* The two staff tables sit right under the legend swatches; without this they read as part
   of the chart rather than as a second thing. */
.ins-tables {
  margin-top: 14px;
}

/* Each half is a donut beside its table, so the split decides the widths and the table no
   longer has to be capped by hand to keep its numbers near their labels. */
.ins-tables .ins-split {
  margin-top: 0;
}

/* A window with no data has no chart to show, and an empty ring reserving its height leaves a
   hole in the card. The chart is hidden and the table takes the row to itself. */
.ins-split.is-bare {
  grid-template-columns: 1fr;
}

/* Same for a pair of cards where one of the two has nothing to show: the survivor takes the
   row rather than sitting in half of it beside a gap. */
.grid-2.is-bare {
  grid-template-columns: 1fr;
}

.ins-mod-split {
  margin: 10px 0 0;
}

.ins-row-total td {
  font-weight: 600;
  border-bottom: 1px solid var(--line);
}

/* Sortable headers and the search / minimum-sample tools of the Insights tables. */
.ins-table th.ins-sortable,
.case-table th[data-case-sort] {
  cursor: pointer;
  user-select: none;
}

.case-table th[data-case-sort]:hover {
  color: var(--fg);
}

.case-table th[aria-sort] {
  color: var(--primary);
}

.case-table th .s-dir {
  margin-left: 4px;
  font-size: 10px;
  letter-spacing: 0;
  opacity: 0.45;
}

.case-table th[aria-sort] .s-dir {
  opacity: 1;
}

.ins-table th.ins-sortable:hover {
  color: var(--fg);
}

.ins-table th[aria-sort] {
  color: var(--primary);
}

.ins-table th .s-dir {
  margin-left: 4px;
  font-size: 10px;
  letter-spacing: 0;
  opacity: 0.45;
}

.ins-table th[aria-sort] .s-dir {
  opacity: 1;
}

.ins-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin: 10px 0 8px;
}

.ins-table-box {
  min-width: 0;
}

.ins-tools .ins-tool-search {
  width: 11rem;
}

.ins-tools .ins-tool-min {
  width: 9rem;
  /* Firefox draws its spinner over the placeholder ("Min. starte"); typing a number is enough. */
  -moz-appearance: textfield;
  appearance: textfield;
}

.ins-tools .ins-tool-min::-webkit-outer-spin-button,
.ins-tools .ins-tool-min::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

@media (max-width: 900px) {
  .ins-split {
    grid-template-columns: 1fr;
  }

  .ins-toolbar .ins-status {
    margin-left: 0;
    text-align: left;
    width: 100%;
  }
}

.ins-hitparts {
  margin: 8px 0 0;
  text-align: center;
}

/* Kills and wins per faction side by side. auto-fit collapses the track of a half that
   insChartSlot hid, so the survivor takes the card, and the pair stacks on a narrow screen. */
.ins-duo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  margin-top: 10px;
}

.ins-sub {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}

.ins-legend-center {
  justify-content: center;
  margin-top: 8px;
}

/* Settings → Workspace → Webhooks */
.webhook-form {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.webhook-events {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0 16px;
}

.webhook-events .row-check {
  margin: 4px 0;
}

/* Settings → Flagged: which staff actions flag on their own. */
.auto-flag-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0 18px;
  margin: 8px 0 4px;
}

.auto-flag-actions .row-check {
  margin: 4px 0;
}

.webhook-error {
  color: var(--bad);
  word-break: break-word;
}

/* Settings → Workspace → Public stats */
.public-stats-link,
.public-stats-key code,
.public-stats-docs code {
  font-family: var(--mono);
  font-size: 12px;
  word-break: break-all;
}

.public-stats-key {
  margin-top: 8px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
}

.public-stats-key .settings-actions {
  margin-top: 8px;
}

.public-stats-docs {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.public-stats-docs summary {
  cursor: pointer;
  font-weight: 600;
}

.public-stats-docs ul {
  margin: 8px 0;
  padding-left: 18px;
}

.public-stats-docs li {
  margin: 4px 0;
}

/* ==========================================================================
 * WATCHDOG TAB (Players → Watchdog)
 * Intro + legend, summary tiles, one filter bar, then Waiting / Trace / Caught as
 * sections with their own head. Tables are fixed-layout: the global nowrap on td let
 * long server lists and details run past the frame.
 * ========================================================================== */
.watch-intro { margin-bottom: 12px; }
.watch-intro > .hint { margin: 0; max-width: 72em; }

.watch-legend { margin-top: 6px; font-size: 12px; }
.watch-legend summary { cursor: pointer; color: var(--muted); width: max-content; }
.watch-legend summary:hover { color: var(--fg); }
.watch-legend dl {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 8px 14px;
  margin: 10px 0 6px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
}
.watch-legend dt { margin: 0; }
.watch-legend dd { margin: 0; line-height: 1.45; }
.watch-legend > .hint { margin: 0; }

.watch-tiles { margin: 0 0 12px; }
.watch-tiles .stat-tile {
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.watch-tiles .stat-tile:hover { background: color-mix(in srgb, var(--fg) 4%, var(--surface)); }
.watch-tiles .stat-tile.is-active {
  background:
    linear-gradient(0deg, var(--primary) 0 2px, transparent 2px),
    color-mix(in srgb, var(--primary) 8%, var(--surface));
}
.watch-tiles .stat-tile.is-alert .stat-tile-n { color: var(--bad); }
.watch-tiles .stat-tile.is-warn .stat-tile-n { color: var(--warn); }

.watch-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}
.watch-tools .ctrl { flex: 1 1 260px; min-width: 0; }

.watch-unban-result {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 8px 12px;
  font-size: 12px;
  margin-bottom: 8px;
}
.watch-unban-result .bad { color: var(--bad); }
.watch-unban-result .srv-chips { margin-top: 6px; }

.watch-section { margin-top: 22px; }
.watch-section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 8px 16px;
  margin-bottom: 8px;
}
.watch-section-head h3 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}
.watch-section-head .hint { margin: 2px 0 0; }
.watch-section-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}
.watch-section-tools .ctrl { width: auto; }

.watch-count {
  font-size: 11px;
  font-weight: 600;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--muted);
}
.watch-count:empty { display: none; }

/* Column widths. em follows the table font, so they scale with it. */
.watch-table { table-layout: fixed; min-width: 62em; }
.wc-player { width: 15em; }
.wc-origin { width: 13em; }
.wc-until { width: 9em; }
.wc-owed { width: 17em; }
.wc-actions { width: 8.5em; }
.wc-when { width: 8em; }
.wc-what { width: 10em; }
.wc-server { width: 9em; }
.wc-dismiss { width: 6.5em; }

.watch-table td {
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: top;
}
.watch-table td.watch-wrap {
  white-space: normal;
  overflow-wrap: anywhere;
}
.watch-table tbody tr:hover td { background: color-mix(in srgb, var(--fg) 3%, transparent); }

.watch-name { overflow: hidden; text-overflow: ellipsis; }
.watch-sub {
  margin-top: 3px;
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
}
.watch-origin { display: flex; align-items: center; gap: 6px; min-width: 0; }
.watch-origin .srv-chip { margin: 0; }
.watch-by { overflow: hidden; text-overflow: ellipsis; }
.watch-perm {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.watch-actions { display: flex; flex-direction: column; gap: 4px; align-items: stretch; }
.watch-actions .btn { width: 100%; }
.watch-empty {
  padding: 18px 12px;
  color: var(--muted);
  white-space: normal;
  text-align: center;
}

/* The watchdog is stuck on this row, not waiting for the player to connect. */
.watch-stuck {
  color: var(--warn);
  font-size: 11px;
  margin-top: 4px;
}

.srv-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.srv-chip {
  display: inline-block;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 1px 8px;
  font-size: 11px;
  white-space: nowrap;
  cursor: default;
  background: var(--bg);
}
.srv-chip.is-bad { color: var(--bad); border-color: var(--bad); }
/* A long tab label ends in an ellipsis inside its pill instead of being cut off by the cell. */
.watch-table .srv-chip { max-width: 100%; overflow: hidden; text-overflow: ellipsis; vertical-align: top; }

/* One word per trace row: what happened, coloured by how much it matters. */
.trace-kind {
  display: inline-block;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 11px;
  white-space: nowrap;
  color: var(--muted);
}
.trace-kind.is-unaudited { color: var(--bad); border-color: var(--bad); }
.trace-kind.is-game-report,
.trace-kind.is-unconfirmed,
.trace-kind.is-watchdog-failed { color: var(--warn); border-color: var(--warn); }
.trace-kind.is-watchdog-ban { color: var(--primary); border-color: var(--primary); }

.trace-table td.trace-detail { font-size: 12px; line-height: 1.45; }
.trace-table tr.is-resolved td { opacity: 0.55; }
.trace-raw { margin-top: 4px; }
.trace-raw summary { cursor: pointer; color: var(--muted); font-size: 11px; }
.trace-raw code {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  white-space: pre-wrap;
  word-break: break-all;
  margin-top: 4px;
  padding: 6px 8px;
  border-radius: 6px;
  background: var(--bg);
}

/* Quests page, the player card's stats block and the main workspace's grant toggle. */
.quest-table td { vertical-align: top; white-space: normal; }
/* A second line under a cell's main value (Steam ID, end date, claim deadline). Block on its own,
   so it never runs into the value whatever table it sits in. */
.q-line { display: block; margin-top: 3px; font-size: 12px; line-height: 1.35; color: var(--muted); }
.q-line.sid { font-family: var(--mono); font-size: 11px; }
.quest-table td:nth-child(5) { min-width: 140px; }
.quest-table td:nth-child(6) { min-width: 140px; }
/* All quests list: rows are tall and dense, so give each quest room and a clear edge. */
#quest-body > tr > td { padding: 18px 14px; }
#quest-body > tr > td:first-child { padding-left: 18px; }
#quest-body > tr > td:last-child { padding-right: 18px; }
#quest-body > tr:hover > td { background: color-mix(in srgb, var(--fg) 3%, transparent); }
#quest-body .quest-desc { margin-top: 6px; max-width: 46ch; line-height: 1.45; }
#quest-body .quest-rules li + li { margin-top: 3px; }
#quest-body .quest-count + .quest-count { margin-top: 3px; }
#quest-body .quest-acts { gap: 8px; }
.quest-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.quest-chips .chip { margin: 0; }
.quest-count { display: block; white-space: nowrap; font-size: 12px; color: var(--muted); }
.quest-count b { color: var(--fg); font-weight: 600; }
.card-note { font-size: 12px; color: var(--muted); }
/* Same 14px between stacked cards as the other views (.stack / .grid-2 gap). */
/* ~ not +: the editor overlay sits between Defaults and All quests and broke the adjacent match. */
#view-quests > .card ~ .card { margin-top: 14px; }
#view-quests .view-head-actions { display: flex; gap: 8px; flex-wrap: nowrap; align-items: center; }
#view-quests .view-head-actions .btn { white-space: nowrap; }
.quest-players-table td:nth-child(5) { min-width: 0; }
.quest-players-table td { vertical-align: middle; }
.quest-players-table td:last-child:not([colspan]) { text-align: right; }
#quest-new { white-space: nowrap; }
.quest-checks .switch,
.quest-editor .field label.switch { text-transform: none; letter-spacing: 0; font-size: 13px; color: var(--fg); display: inline-flex; align-items: center; gap: 6px; }
/* Fields in one row no longer stretch to the tallest one (the weapon list). */
.quest-editor .grid-2 { align-items: start; }
.quest-editor .field { align-content: start; }
.quest-editor .field .grid-2 { gap: 10px; }
.quest-editor .hint, .quest-hint { font-size: 12px; margin: 0; }
.quest-editor .quest-sub + .hint { margin-bottom: 12px; }
/* The generic .field input rule would turn the radios into full-width text boxes. */
.quest-editor .field input[type="radio"] { width: 16px; height: 16px; padding: 0; margin: 0; border-radius: 50%; flex: none; }
.quest-editor .field input[type="radio"]:checked { background: var(--primary); border-color: var(--primary); box-shadow: inset 0 0 0 3px var(--field, var(--bg)); }
.quest-editor .quest-sub { border-top: 1px solid var(--line); padding-top: 14px; }
.quest-editor .quest-sub:first-of-type { border-top: 0; padding-top: 0; }
.quest-live { margin-bottom: 14px !important; color: var(--primary); }
.quest-defaults summary { cursor: pointer; list-style: none; }
.quest-defaults summary::-webkit-details-marker { display: none; }
.quest-defaults summary h3 { display: inline; }
.quest-defaults summary::after { content: " ▸"; color: var(--muted); }
.quest-defaults { margin-bottom: 12px; }
.quest-defaults[open] summary::after { content: " ▾"; }
.quest-defaults[open] summary { margin-bottom: 12px; }
.quest-settings-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
#quest-settings .quest-settings-grid,
.quest-reward-grid { grid-template-columns: repeat(4, 1fr); }
#quest-settings .actions-row { margin-top: 10px; }
.quest-link-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.quest-link-row h3 { margin: 0 0 4px; }
.quest-link-copy { display: flex; gap: 8px; align-items: center; flex: 1 1 360px; max-width: 520px; }
.quest-link-copy .ctrl { font-family: var(--mono); font-size: 12px; padding: 8px 10px; }
.quest-diff { margin-left: 6px; }
.quest-bounty { margin-left: 6px; border-color: #d9534f; color: #e8706c; }
.quest-target-results { display: flex; flex-wrap: wrap; gap: 6px; }
.quest-target-results:empty { display: none; }
.quest-targets { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.quest-target { display: inline-flex; align-items: center; gap: 6px; }
.quest-target .sid, .quest-target-results .sid { font-family: var(--mono); font-size: 11px; color: var(--muted); }
.quest-target-x { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; }
.quest-target-x:hover { color: var(--accent); }
.bounty-banner { border: 1px solid #d9534f; border-radius: 8px; padding: 10px 12px; font-size: 13px; }
.bounty-banner .quest-bounty { margin: 0 6px 0 0; }
/* A bounty target's name, wherever the console lists players. */
.is-bounty::after { content: "Bounty"; display: inline-block; margin-left: 6px; padding: 0 5px; border: 1px solid #d9534f;
  border-radius: 999px; color: #e8706c; font-size: 10px; font-weight: 600; line-height: 16px; vertical-align: middle; }
.quest-diff-easy { border-color: #4caf7a; color: #4caf7a; }
.quest-diff-medium { border-color: #d6b23a; color: #d6b23a; }
.quest-diff-hard { border-color: #e07b39; color: #e07b39; }
.quest-diff-elite { border-color: #c04ad6; color: #c04ad6; }
.quest-templates { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; margin-top: 12px; }
.quest-template { border: 1px solid var(--line); border-radius: 10px; padding: 12px; display: grid; gap: 6px; align-content: start; }
.quest-template .hint { margin: 0; font-size: 12px; }
.quest-template-acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
/* hidden must win over the flex/grid display of these blocks. */
.quest-editor [hidden], .quest-template-tools [hidden] { display: none !important; }
.quest-template-tools { display: flex; gap: 8px; flex-wrap: wrap; }
.quest-template-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
@media (max-width: 900px) { .quest-settings-grid, #quest-settings .quest-settings-grid { grid-template-columns: 1fr; } }
.quest-desc { display: block; margin-top: 4px; }
.quest-rules { margin: 0; padding-left: 16px; font-size: 12px; color: var(--muted); }
.quest-acts { flex-wrap: wrap; gap: 6px; margin: 0; }
.quest-status-active { border-color: var(--primary); color: var(--primary); }
.quest-status-closed { color: var(--muted); }
/* Run end has passed: a light yellow row, see-through so it sits on every theme's table. */
.quest-table tr.quest-ended > td { background: color-mix(in srgb, #f5c400 14%, transparent); }
.quest-sub { margin: 18px 0 8px; font-size: 13px; }
.quest-checks { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.quest-kd { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.cm-grants { display: flex; align-items: center; gap: 10px; margin: 12px 0; }
@media (max-width: 700px) { .quest-editor .grid-2 { grid-template-columns: 1fr; } }

/* Switched-off modules (body.off-<feature>, set by applyFeatureClasses): their columns and controls go. */
body.off-notes .db-col-note,
body.off-notes .db-note-th,
body.off-notes .db-note-cell,
body.off-notes .db-notes-only { display: none; }
body.off-reserved .share-col-sharedReservedSlotsEnabled,
body.off-autopunish .share-col-sharedAutoPunishEnabled { display: none; }

/* Quest editor: basics on top, rules folded into rows that show their value, a save bar at the bottom. */
.quest-editor { max-width: 980px; }
.quest-editor .qe-block { border-top: 1px solid var(--line); padding: 16px 0 6px; }
.qe-live { margin: 0 0 12px; color: var(--primary); font-size: 13px; }
.qe-row { display: grid; gap: 12px; }
.qe-row .field { margin-bottom: 12px; }
/* A datetime input's own minimum width pushed it out of its column. */
.qe-row > .field { min-width: 0; }
.qe-row-title { grid-template-columns: 1fr 110px 150px; }
.qe-row-reward { grid-template-columns: 170px 1fr; }
.qe-row-2 { grid-template-columns: 1fr 1fr; }
.qe-narrow { max-width: 220px; margin-top: 8px; }
.qe-help { margin: 0 0 10px; font-size: 12px; color: var(--muted); }
.quest-status-scheduled { color: var(--primary); border-color: var(--primary); }
.quest-weekly { color: var(--primary); }
#ins-quest-card .ins-subhead { margin-top: 14px; }
#ins-quest-card .ins-subhead h4 { margin: 0; font-size: 13px; }
.qe-title { margin: 0 0 10px; font-size: 13px; }
.qe-title span { font-weight: 400; color: var(--muted); font-size: 12px; margin-left: 8px; }
.qe-label { margin: 10px 0 6px; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.qe-label:first-child { margin-top: 0; }
.qe-label em { font-style: normal; text-transform: none; letter-spacing: 0; margin-left: 6px; }
.quest-editor .field label em { font-style: normal; text-transform: none; letter-spacing: 0; margin-left: 6px; color: var(--muted); font-weight: 400; }
.qe-rule { border: 1px solid var(--line); border-radius: 8px; margin-bottom: 6px; background: color-mix(in srgb, var(--surface, #141a20) 60%, transparent); }
.qe-rule[open] { border-color: color-mix(in srgb, var(--primary) 40%, var(--line)); }
.qe-rule summary { display: flex; align-items: center; gap: 12px; padding: 10px 14px; cursor: pointer; list-style: none; }
.qe-rule summary::-webkit-details-marker { display: none; }
.qe-rule summary::after { content: "+"; margin-left: auto; color: var(--muted); font-size: 16px; }
.qe-rule[open] summary::after { content: "−"; }
.qe-rule summary b { font-size: 13px; min-width: 130px; }
.qe-sum { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qe-sum.is-set { color: var(--primary); }
.qe-rule-body { padding: 4px 14px 14px; }
.qe-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.qe-chip { position: relative; cursor: pointer; }
.qe-chip input { position: absolute; opacity: 0; pointer-events: none; }
.qe-chip span { display: inline-block; padding: 4px 11px; border: 1px solid var(--line); border-radius: 999px; font-size: 12px; color: var(--fg); }
.qe-chip:hover span { border-color: var(--muted); }
.qe-chip input:checked + span { border-color: var(--primary); color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, transparent); }
.qe-chip input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 1px; }
.qe-check { display: flex; align-items: center; gap: 8px; font-size: 13px; margin: 4px 0 10px; cursor: pointer; }
.qe-check em { font-style: normal; color: var(--muted); font-size: 12px; }
.quest-editor .qe-check input { width: auto; accent-color: var(--primary); }
/* On/off switches in the quest editor (Unlimited, Race). */
.quest-editor .qe-toggle input { appearance: none; -webkit-appearance: none; width: 30px; height: 17px; margin: 0; flex-shrink: 0; border-radius: 999px; background: var(--line); position: relative; cursor: pointer; transition: background .15s; }
.quest-editor .qe-toggle input::after { content: ""; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%; background: var(--bg); transition: transform .15s; }
.quest-editor .qe-toggle input:checked { background: var(--primary); }
.quest-editor .qe-toggle input:checked::after { transform: translateX(13px); background: var(--primary-ink); }
.quest-editor .qe-toggle input:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.quest-editor #qf-period { margin-top: 2px; }
.quest-editor .qe-rule-body > input { width: 100%; }
.qe-claim { display: flex; gap: 8px; }
.quest-editor .qe-claim > * { flex: 1 1 0; min-width: 0; width: auto; }
.qe-rule-body .ctrl { margin-bottom: 8px; }
.qe-rule-body .quest-target-results { margin-bottom: 8px; }
.qe-foot { position: sticky; bottom: 0; display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 12px 0 2px; margin-top: 8px;
  border-top: 1px solid var(--line); background: var(--surface, var(--bg)); z-index: 2; }
.qe-error { margin: 0 auto 0 0; color: var(--accent); font-size: 13px; }
@media (max-width: 760px) {
  .qe-row-title, .qe-row-reward, .qe-row-2 { grid-template-columns: 1fr; }
  .qe-rule summary b { min-width: 0; }
}

/* The editor is a dialog over the whole page. Top: basics and rewards on the left, repeat and
   where/when on the right, two halves of about the same height. Below: the rules at full width, so
   the long chip lists wrap into few rows. The dialog scrolls on its own; the save bar stays at its bottom. */
.quest-editor-back { position: fixed; inset: 0; z-index: 40; display: grid; place-items: center; padding: 16px; background: var(--scrim); }
.quest-editor-back > .card { max-height: calc(100vh - 32px); background: var(--surface); box-shadow: var(--shadow); }
.quest-editor-back .quest-editor { width: min(1380px, 100%); max-width: none; overflow-y: auto; padding-bottom: 0; }
/* top matches the -16px margin: sticky offsets count from inside the dialog's padding. */
.quest-editor-back .card-head { position: sticky; top: -16px; z-index: 3; margin: -16px -16px 8px; padding: 14px 16px 10px;
  background: var(--surface); border-bottom: 1px solid var(--line); }
.quest-editor-back .qe-foot { padding-bottom: 14px; }
.qe-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 28px; }
.quest-editor .qe-cols > .qe-block { border-top: 0; padding-top: 4px; }
.qe-sub { border-top: 1px solid var(--line); margin-top: 4px; padding-top: 14px; }
.qe-sub .qe-chips { margin-bottom: 12px; }
body.quest-editor-open { overflow: hidden; }
/* Players of one quest: the header stays, the table scrolls under its own column heads. */
.quest-editor-back .quest-players-pop { width: min(1100px, 100%); display: flex; flex-direction: column; overflow: hidden; }
.quest-players-pop .card-head { position: static; margin: -16px -16px 12px; flex: none; }
.quest-players-pop .card-head h3 { margin-right: auto; }
.quest-players-pop .card-head .hint { font-size: 12px; }
.quest-players-pop .table-wrap { flex: 1 1 auto; min-height: 0; overflow: auto; }
.quest-players-pop thead th { position: sticky; top: 0; z-index: 1; }
@media (max-width: 1100px) {
  .qe-cols { grid-template-columns: minmax(0, 1fr); }
  .quest-editor .qe-cols > .qe-plan { border-top: 1px solid var(--line); padding-top: 16px; }
}

/* Explorer (main admin). */
.ex-bar {
  display: grid;
  gap: 10px;
}

.ex-tabs,
.ex-presets {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}

.ex-range {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

.ex-range input[type="datetime-local"] {
  width: auto;
}

.ex-range-text {
  margin: 0;
}

.ex-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.ex-chips:empty {
  display: none;
}

.ex-chip.is-out {
  border-color: var(--bad);
}

.ex-chip-x {
  background: none;
  border: 0;
  color: inherit;
  cursor: pointer;
  padding: 0 0 0 6px;
  font-size: 14px;
  line-height: 1;
}

.ex-kpis {
  margin: 14px 0;
}

.ex-delta {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.ex-delta.up {
  color: var(--good);
}

.ex-delta.down {
  color: var(--bad);
}

.ex-delta.flat {
  color: var(--muted);
}

.ex-breakdowns {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
  gap: 14px;
  margin: 14px 0;
}

.ex-breakdown .ins-table td .ex-delta {
  display: inline;
  margin: 0;
}

.ex-table th[data-ex-sort] {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.ex-table th[data-ex-sort]:hover {
  color: var(--fg);
}

.ex-table th[aria-sort] {
  color: var(--primary);
}

.ex-table th .s-dir {
  margin-left: 4px;
  font-size: 10px;
  opacity: 0.45;
}

.ex-table th[aria-sort] .s-dir {
  opacity: 1;
}

.ex-table td {
  white-space: nowrap;
  max-width: 28rem;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: top;
}

/* Messages and reasons are read in full (often Chinese, Russian …), so they wrap instead of being cut. */
.ex-table td.ex-long {
  white-space: normal;
  min-width: 16rem;
  max-width: 36rem;
  overflow-wrap: anywhere;
}

.ex-long-tools {
  display: flex;
  gap: 8px;
  margin-top: 4px;
  font-size: 11px;
}

.ex-long-tools button,
.ex-long-tools a {
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  text-decoration: underline;
  font: inherit;
}

.ex-long-tools button:hover,
.ex-long-tools a:hover {
  color: var(--fg);
}

.ex-cols {
  position: relative;
}

.ex-cols > summary {
  list-style: none;
}

.ex-cols > div {
  position: absolute;
  right: 0;
  z-index: 5;
  display: grid;
  gap: 6px;
  min-width: 12rem;
  padding: 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* Explorer: compare communities. */
.ex-cmp-pick {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 12px;
}

.ex-cmp-search {
  position: relative;
  min-width: 16rem;
}

.ex-cmp-results {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  z-index: 6;
  max-height: 20rem;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.ex-cmp-hit {
  display: block;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  background: none;
  color: var(--fg);
  text-align: left;
  cursor: pointer;
}

.ex-cmp-hit:hover {
  background: var(--surface-2);
}

.ex-cmp-head {
  margin-top: 8px;
}

.ex-cmp-table th:not(:first-child),
.ex-cmp-table td:not(:first-child) {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.ex-cmp-table td.ex-best {
  color: var(--good);
  font-weight: 600;
}

.ex-cmp-group td {
  padding-top: 14px;
  color: var(--muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
