/* ════════════════════════════════════════════════════════════════════════
   SCUM Server Automation — "TEC1 Field Terminal"
   A tactical surveillance/telemetry console for the prison-island server.
   Display: Chakra Petch · Data/readout: Share Tech Mono
   ════════════════════════════════════════════════════════════════════════ */

:root {
  --bg:        #0d0e0a;
  --bg-2:      #0a0b08;
  --panel:     #161710;
  --panel-2:   #1c1d14;
  --inset:     #0b0c08;

  --amber:     #f0820c;
  --amber-hi:  #ff9a2e;
  --on-amber:  #1a1206;   /* text on amber fills (buttons, filled badges) */
  --online:    #6cbf3f;
  --alarm:     #e5443f;
  --standby:   #e0a92e;

  --text:      #e4e2d6;
  --muted:     #8e8f82;
  --faint:     #63645a;

  --line:      rgba(228, 226, 214, 0.09);
  --line-2:    rgba(228, 226, 214, 0.05);
  --line-amber: rgba(240, 130, 12, 0.30);
  --hover-bg:  rgba(255, 255, 255, 0.05);  /* neutral hover fill on dark surfaces */
  /* Focused inputs already turn their border amber (border-color: var(--amber)); this ring used to
     add a SECOND concentric amber line just outside it — a double frame. Keep the single clean
     border only. (Every :focus rule that references this also sets border-color, so nothing loses
     its focus indicator; keyboard nav still gets the global :focus-visible outline.) */
  --focus-ring: none;

  /* Entity accents (map markers, lists, popovers) — one source of truth. */
  --c-player:  #35d07f;
  --c-base:    #ff9a2e;
  --c-vehicle: #5aa0ff;
  --c-chest:   #c9a24b;
  --c-storage: #bd7be6;
  --c-trap:    #e0503a;
  --c-turret:  #e8c33a;
  --offline:   #7c8594;
  --data-text: #b9c2ad;   /* soft sage for raw data/log/INI readouts */

  /* Integrations */
  --discord:    #5865f2;
  --discord-dn: #4752c4;
  --discord-hi: #c9cdfb;

  --mono: 'Share Tech Mono', 'Consolas', monospace;
  --ui:   'Chakra Petch', 'Segoe UI', Tahoma, sans-serif;

  --radius: 4px;      /* inputs, chips, small controls */
  --radius-md: 6px;   /* cards, rows */
  --radius-lg: 8px;   /* panels, modals, popovers */
  --pill: 999px;      /* fully rounded pills */
}

* { box-sizing: border-box; }
img { max-width: 100%; }
a:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; }

/* Base scale ≈ 20px (124% of 16px) — sized so the UI reads comfortably at 100%
   browser zoom (matches what previously needed zooming to ~110%). Phones keep
   their own tuned scale; layouts there are tight already. */
html { -webkit-text-size-adjust: 100%; font-size: 124%; }
@media (max-width: 640px) { html { font-size: 106%; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--ui);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0.01em;
}

/* faint scanlines — surveillance-monitor atmosphere */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, 0.018) 0,
      rgba(255, 255, 255, 0.018) 1px,
      transparent 1px,
      transparent 3px
    );
}

.hidden { display: none !important; }

.screen {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3 {
  font-family: var(--ui);
  font-weight: 600;
  letter-spacing: 0.02em;
}

a { color: var(--amber); }

code {
  font-family: var(--mono);
  background: var(--inset);
  border: 1px solid var(--line);
  padding: 0.05rem 0.35rem;
  border-radius: 3px;
  color: var(--amber-hi);
  font-size: 0.9em;
}

.error {
  color: var(--alarm);
  font-size: 0.85rem;
  margin: 0;
  min-height: 1em;
}

/* ── Brand lockup ──────────────────────────────────────────────────────── */

.brand {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  min-width: 0;
  cursor: pointer;
}

.brand-logo {
  height: 50px;
  width: auto;
  flex-shrink: 0;
}

.brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.05;
  min-width: 0;
}

.brand-title {
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: 0.04em;
}

.brand-sub {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--amber);
}

/* ── Header / command bar ──────────────────────────────────────────────── */

header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.75rem 1.5rem;
  background: linear-gradient(180deg, var(--panel), var(--bg-2));
  border-bottom: 1px solid var(--line);
}

/* ── Persistent topbar + tab nav (Field-Console-style) ─────────────────────── */
#app-shell { display: flex; flex-direction: column; min-height: 100vh; }
.topbar { position: sticky; top: 0; z-index: 30; transition: transform 0.25s ease; }
.topbar.nav-hidden { transform: translateY(-100%); }
.header-actions { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
/* Manager lifecycle buttons in the header (update / restart / shut down). */
.header-sep { width: 1px; align-self: stretch; background: var(--line); margin: 0.2rem 0.1rem; }
.hdr-icon-btn { padding: 0.42rem 0.7rem; }
.mgr-danger:hover { border-color: var(--alarm) !important; color: #ff6b6b !important; }
/* Field Console is an <a>, so the button{} rules don't reach it — mirror the
   secondary button look so it sits identically next to Logout (no underline). */
.header-actions a.secondary {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
  font-family: var(--ui); font-weight: 600; font-size: 0.82rem; letter-spacing: 0.03em;
  padding: 0.55rem 1.05rem; border-radius: var(--radius); text-decoration: none;
  border: 1px solid var(--line); background: var(--panel-2); color: var(--text);
  transition: background 0.14s, border-color 0.14s, color 0.14s;
}
.header-actions a.secondary:hover { border-color: var(--line-amber); color: var(--amber-hi); background: var(--panel-2); text-decoration: none; }
.header-actions a.secondary .ico { width: 16px; height: 16px; }
/* Full-screen overlay while the manager restarts / shuts down. */
.mgr-overlay { position: fixed; inset: 0; z-index: 9999; display: none; align-items: center; justify-content: center; background: rgba(8, 8, 6, 0.92); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
.mgr-overlay-card { text-align: center; color: var(--text); padding: 2rem; max-width: 440px; }
.mgr-overlay-card p { margin-top: 1.1rem; color: var(--muted); line-height: 1.55; }
.mgr-overlay-ic { width: 44px; height: 44px; color: var(--amber); }
.mgr-spinner { width: 42px; height: 42px; margin: 0 auto; border: 3px solid var(--line); border-top-color: var(--amber); border-radius: 50%; animation: mgr-spin 0.9s linear infinite; }
@keyframes mgr-spin { to { transform: rotate(360deg); } }
.admin-nav { display: flex; gap: 0.25rem; padding: 0 1.5rem; background: var(--bg-2); border-bottom: 1px solid var(--line-amber); overflow-x: auto; }
.anav-btn {
  display: inline-flex; align-items: center; gap: 0.45rem; cursor: pointer; white-space: nowrap;
  background: transparent; border: 0; border-bottom: 2px solid transparent;
  color: var(--muted); font-family: var(--ui); font-weight: 600; font-size: 0.9rem;
  padding: 0.8rem 0.9rem; letter-spacing: 0.02em; text-transform: none;
}
/* The nav items are real <a href="#tab"> so the browser's own link behaviour works —
   middle-click / Ctrl-click opens the tab in a new browser tab, and they can be bookmarked.
   These two rules keep them looking exactly like the buttons they replaced. */
.anav-btn { text-decoration: none; }
.anav-btn:hover { color: var(--text); border-color: transparent; background: transparent; text-decoration: none; }
.anav-btn.active { color: var(--amber); border-bottom-color: var(--amber); }
.anav-btn .ico { font-size: 1.05rem; }

/* Plugins nav dropdown (DESKTOP with a real pointer only). The button still works everywhere; on a
   desktop it also gets a hover menu of plugins that ship a UI. The menu is fixed-positioned on <body>
   (JS) so the horizontally-scrolling nav can't clip it. On touch / narrow screens it's disabled. */
.anav-dd { display: inline-flex; }
.anav-dd.has-dd > .anav-btn::after { content: ''; margin-left: 0.3rem; align-self: center; border: 4px solid transparent; border-top-color: currentColor; border-bottom: 0; opacity: 0.55; }
.anav-dd-menu { position: fixed; z-index: 6000; min-width: 210px; max-width: calc(100vw - 16px); background: var(--panel); border: 1px solid var(--line-amber); border-radius: 10px; box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55); padding: 6px; display: none; }
.anav-dd-menu.open { display: block; }
.anav-dd-item { display: flex; align-items: center; justify-content: flex-start; gap: 10px; width: 100%; padding: 0.5rem 0.6rem; background: none; border: 0; color: var(--text); cursor: pointer; border-radius: 7px; font-family: var(--ui); font-weight: 500; font-size: 0.88rem; text-align: left; }
.anav-dd-item:hover { background: var(--panel-2); color: var(--amber-hi, var(--amber)); }
.anav-dd-item img { width: 22px; height: 22px; border-radius: 5px; object-fit: contain; flex: none; }
.anav-dd-item .ico { width: 18px; height: 18px; color: var(--muted); flex: none; font-size: 1rem; }
.anav-dd-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.anav-dd-sep { height: 1px; background: var(--line); margin: 5px 4px; }
@media (hover: none), (max-width: 760px) { .anav-dd.has-dd > .anav-btn::after { display: none; } .anav-dd-menu { display: none !important; } }

.tab-panel { flex: 1 0 auto; }
.tab-panel.hidden { display: none !important; }

/* Slim per-screen title bar (replaces the old sub-screen headers) */
.screen-bar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin: 1.25rem 1.5rem 0; }
.screen-title { display: flex; align-items: center; gap: 0.5rem; font-size: 1rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--amber); }
.screen-title .ico { color: var(--amber); }
.screen-bar-actions { display: flex; gap: 0.5rem; }

header h1 {
  margin: 0;
  font-size: 1.15rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.nav-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* ── Buttons ───────────────────────────────────────────────────────────── */

/* ── Unified button system ─────────────────────────────────────────────────
   One consistent look everywhere. Default = PRIMARY (amber). `.secondary` =
   outline, `.danger` / `.warning` = coloured. All buttons share size + shape so
   Save/actions look the same on every screen. */
button {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
  font-family: var(--ui); font-weight: 600; font-size: 0.82rem; letter-spacing: 0.03em;
  padding: 0.55rem 1.05rem; cursor: pointer; border-radius: var(--radius);
  border: 1px solid var(--amber); background: var(--amber); color: var(--on-amber);
  transition: background 0.14s, border-color 0.14s, color 0.14s, transform 0.05s;
}
button:hover { background: var(--amber-hi); border-color: var(--amber-hi); color: var(--on-amber); }
button:active { transform: translateY(1px); }
button .ico { font-size: 1.05em; }

button.secondary {
  background: var(--panel-2); border-color: var(--line); color: var(--text);
}
button.secondary:hover { background: var(--panel-2); border-color: var(--line-amber); color: var(--amber-hi); }

button.danger { background: rgba(229, 68, 63, 0.12); border-color: rgba(229, 68, 63, 0.4); color: var(--alarm); }
button.danger:hover { background: rgba(229, 68, 63, 0.2); border-color: var(--alarm); }

button.warning { background: rgba(224, 169, 46, 0.12); border-color: rgba(224, 169, 46, 0.4); color: var(--standby); }
button.warning:hover { background: rgba(224, 169, 46, 0.2); border-color: var(--standby); }

button.btn-icon { padding: 0.5rem; }
button:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── Panels ────────────────────────────────────────────────────────────── */

.status-card,
.leaderboards,
.players,
.players-admin,
.bans,
.cmd-console,
.logs {
  position: relative;
  margin: 1.25rem 1.5rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.15rem 1.4rem;
}

/* Front-style corner ticks on every panel. */
.status-card::before, .players::before, .players-admin::before, .bans::before, .cmd-console::before, .logs::before,
.status-card::after, .players::after, .players-admin::after, .bans::after, .cmd-console::after, .logs::after {
  content: ''; position: absolute; width: 10px; height: 10px;
  border-color: var(--line-amber); border-style: solid; border-width: 0; pointer-events: none;
}
.status-card::before, .players::before, .players-admin::before, .bans::before, .cmd-console::before, .logs::before {
  top: -1px; left: -1px; border-top-width: 2px; border-left-width: 2px;
}
.status-card::after, .players::after, .players-admin::after, .bans::after, .cmd-console::after, .logs::after {
  bottom: -1px; right: -1px; border-bottom-width: 2px; border-right-width: 2px;
}

.status-card { margin-bottom: 0; }
.status-card + .status-card { margin-top: 1.25rem; }
.controls + .status-card { margin-top: 0; }

/* Eyebrow label — names the feed each panel carries */
.panel-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--amber);
  margin-bottom: 1rem;
}

.panel-eyebrow::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--amber);
  box-shadow: 0 0 7px var(--amber);
}

.panel-eyebrow .feed-id {
  margin-left: auto;
  color: var(--faint);
  letter-spacing: 0.15em;
}

/* when a live dot is present, drop the static amber marker to avoid two dots */
.panel-eyebrow:has(.live-dot)::before { display: none; }

.panel-eyebrow .live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--online);
  box-shadow: 0 0 8px var(--online);
  animation: pulse 1.6s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}

/* ── Vitals viewport (primary status panel) — the signature element ────── */

.viewport {
  position: relative;
  border-color: var(--line-amber);
}

.viewport::before,
.viewport::after {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
  border: 2px solid var(--amber);
  pointer-events: none;
}

.viewport::before { top: -1px; left: -1px; border-right: 0; border-bottom: 0; }
.viewport::after  { bottom: -1px; right: -1px; border-left: 0; border-top: 0; }

/* ── Status grid / telemetry readouts ──────────────────────────────────── */

.status-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1.1rem 1.4rem;
}

.status-item {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding-left: 0.7rem;
  border-left: 1px solid var(--line-2);
  min-width: 0;   /* let long values wrap instead of overflowing the grid cell */
}

.status-item .label {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.16em;
}

.status-item .value {
  font-family: var(--mono);
  font-size: 1.4rem;
  color: var(--text);
  letter-spacing: 0.01em;
  min-width: 0;
  overflow-wrap: anywhere;   /* break long strings (filenames) that have no spaces */
}
/* Backup filename is long and not a headline metric — smaller so it wraps neatly. */
#last-backup-value { font-size: 0.92rem; line-height: 1.3; }

/* ── Vitals badge ──────────────────────────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  align-self: flex-start;
  padding: 0.2rem 0.7rem 0.2rem 0.6rem;
  border-radius: 3px;
  font-family: var(--ui);
  font-weight: 600;
  font-size: 0.92rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--panel-2);
  border: 1px solid var(--line);
  color: var(--muted);
}

.badge::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}

.badge.online {
  color: var(--online);
  border-color: rgba(108, 191, 63, 0.4);
  background: rgba(108, 191, 63, 0.08);
}
.badge.online::before { box-shadow: 0 0 8px var(--online); }

.badge.offline {
  color: var(--alarm);
  border-color: rgba(229, 68, 63, 0.4);
  background: rgba(229, 68, 63, 0.08);
}

.badge.transitional {
  color: var(--standby);
  border-color: rgba(224, 169, 46, 0.4);
  background: rgba(224, 169, 46, 0.08);
}
.badge.transitional::before { animation: pulse 1s ease-in-out infinite; }

/* Win over `.status-item .value` font-size for the badge specifically */
.status-item .value.badge { font-size: 0.9rem; }

/* ── Controls ──────────────────────────────────────────────────────────── */

.controls {
  margin: 1.25rem 1.5rem;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
}
/* "When" picker inside the confirm dialog — scheduling lives in the confirm an admin already
   has to click, so the controls row stays exactly as it was. */
.ssa-when { display: flex; flex-wrap: wrap; gap: 0.4rem 0.75rem; margin: 0.15rem 0 0.9rem; }
.ssa-when-opt { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.85rem;
  color: var(--text); cursor: pointer; }
.ssa-when-opt input[type="radio"] { accent-color: var(--amber, #ff6a1a); cursor: pointer; }
.ssa-when-min { width: 62px; background: var(--inset); border: 1px solid var(--line-2); border-radius: 6px;
  color: var(--text); font: inherit; font-size: 0.82rem; padding: 0.2rem 0.35rem; margin-left: 0.15rem; }
.ssa-when-note { flex-basis: 100%; margin: 0.15rem 0 0; font-size: 0.76rem; color: var(--muted); }
.sched-pending { display: inline-flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.sched-chip { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.78rem;
  background: color-mix(in srgb, var(--amber, #ff6a1a) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--amber, #ff6a1a) 40%, transparent);
  border-radius: 999px; padding: 0.2rem 0.3rem 0.2rem 0.65rem; }
.sched-x { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: 1rem;
  line-height: 1; padding: 0 0.25rem; }
.sched-x:hover { color: var(--alarm, #e5443f); }

.controls button {
  padding: 0.6rem 1.25rem;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--text);
  font-size: 0.82rem;
  text-transform: uppercase;
}

.controls button:hover { border-color: var(--line-amber); color: var(--amber-hi); }

/* Primary action — Start */
#start-btn {
  background: var(--amber);
  border-color: var(--amber);
  color: var(--on-amber);
}
#start-btn:hover { background: var(--amber-hi); border-color: var(--amber-hi); color: var(--on-amber); }

.controls button.danger { color: var(--alarm); border-color: rgba(229, 68, 63, 0.35); }
.controls button.danger:hover { background: rgba(229, 68, 63, 0.12); color: var(--alarm); }

.controls button.warning { color: var(--standby); border-color: rgba(224, 169, 46, 0.35); }
.controls button.warning:hover { background: rgba(224, 169, 46, 0.12); color: var(--standby); }

#control-message {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--muted);
  letter-spacing: 0.04em;
}

/* ── Skip-restart switch ───────────────────────────────────────────────── */

.switch {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  cursor: pointer;
  font-family: var(--mono);
  font-size: 1rem;
}

.switch input {
  width: 1.1rem;
  height: 1.1rem;
  accent-color: var(--amber);
}

/* ── Section headers w/ feed tick ──────────────────────────────────────── */

.leaderboards h2,
.players h2,
.players-admin h2,
.bans h2,
.cmd-console h2,
.logs h2 {
  margin: 0 0 0.85rem;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

/* Inline SVG icons (shared with the public site look). */
.svg-defs { position: absolute; }
.ico {
  width: 1.05em; height: 1.05em; flex: none; vertical-align: middle;
  stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.players h2 .ico, .players-admin h2 .ico, .bans h2 .ico, .cmd-console h2 .ico, .logs h2 .ico { color: var(--amber); }
.nav-actions button, .controls button, #player-search-btn { display: inline-flex; align-items: center; gap: 0.4rem; }

/* ── Players list ──────────────────────────────────────────────────────── */

#players-list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--mono);
  font-size: 0.9rem;
  /* Fill the width with as many columns as fit instead of one tall column that wastes the space on
     the right. Items flow left→right, top→bottom in login order. */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 0 1.4rem;
}

#players-list li {
  padding: 0.4rem 0.2rem;
  border-bottom: 1px solid var(--line-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#players-list li:first-child::before {
  content: none;
}

/* ── Live log feed ─────────────────────────────────────────────────────── */

.logs {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

#log-tail {
  flex: 1;
  overflow-y: auto;
  background: var(--inset);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  font-family: var(--mono);
  font-size: 0.82rem;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-all;
  max-height: 400px;
  color: var(--data-text);
}

/* ── App footer ────────────────────────────────────────────────────────── */

/* Footer styled to match the Field Console: full-width, amber top accent, a brand
   line and a bottom bar with social links. */
.app-footer {
  margin-top: auto;   /* pin to the bottom of the screen */
  border-top: 1px solid var(--line-amber);
  background: linear-gradient(180deg, var(--bg-2), var(--bg));
}
.af-top {
  display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 0.4rem 2rem;
  padding: 1.3rem 1.5rem 0.9rem;
}
.af-brand { display: flex; align-items: center; gap: 0.55rem; font-weight: 700; letter-spacing: 0.04em; }
.af-logo { width: 24px; height: 24px; }
.af-bottom {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.6rem;
  padding: 0.7rem 1.5rem 1.1rem; border-top: 1px solid var(--line);
}
.af-social { display: flex; gap: 1.4rem; }
.af-social a { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--muted); }
.af-social a:hover { color: var(--amber-hi); }

.app-footer-links {
  display: flex;
  gap: 1.5rem;
}

.app-footer-links a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.14s;
}

.app-footer-links a:hover {
  color: var(--amber-hi);
}

/* ── Login screen ──────────────────────────────────────────────────────── */

#login-screen {
  align-items: center;
  justify-content: center;
  padding: 2rem 1rem;
}

.login-box {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line-amber);
  padding: 2.25rem 2rem 2rem;
  border-radius: var(--radius);
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  width: 400px;
  max-width: calc(100vw - 2rem);
  text-align: center;
}

.login-box::before,
.login-box::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 16px;
  border: 2px solid var(--amber);
  pointer-events: none;
}
.login-box::before { top: -1px; left: -1px; border-right: 0; border-bottom: 0; }
.login-box::after  { bottom: -1px; right: -1px; border-left: 0; border-top: 0; }

.login-logo {
  width: 64px;
  height: 64px;
  border-radius: var(--radius-lg);
  margin: 0 auto 0.25rem;
  border: 1px solid var(--line);
}

.login-box h1 {
  font-size: 1rem;
  margin: 0 0 0.4rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.login-box .login-tagline {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--amber);
  margin: 0 0 0.5rem;
}

.login-box input {
  padding: 0.6rem 0.7rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--inset);
  color: var(--text);
  font-family: var(--mono);
  text-align: center;
  letter-spacing: 0.1em;
}

.login-box input:focus { outline: none; border-color: var(--amber); }

.login-box button {
  padding: 0.6rem;
  border-radius: var(--radius);
  border: 1px solid var(--amber);
  background: var(--amber);
  color: var(--on-amber);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.login-box button:hover { background: var(--amber-hi); border-color: var(--amber-hi); }

/* ── Settings / Game Settings / Discord notes ──────────────────────────── */

.settings-note, .settings-message {
  margin: 0 1.5rem;
  font-size: 0.85rem;
  color: var(--muted);
}

.settings-note { margin-top: 1rem; line-height: 1.6; }

.settings-message {
  font-family: var(--mono);
  letter-spacing: 0.03em;
}
.settings-message.success { color: var(--online); }
.settings-message.error { color: var(--alarm); }

.settings-form {
  margin: 1rem 1.5rem 2rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* ── Settings search toolbar + collapsible categories ──────────────────── */

.settings-toolbar {
  margin: 1rem 1.5rem 0;
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
}

/* Inside the Game Settings tab the container already has horizontal margin */
.gs-tab-content .settings-toolbar {
  margin: 0 0 1rem;
}

.settings-search {
  flex: 1;
  min-width: 200px;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--inset);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
}

.settings-search:focus {
  outline: none;
  border-color: var(--amber);
  box-shadow: var(--focus-ring);
}

.settings-toolbar-actions {
  display: flex;
  gap: 0.5rem;
}

/* Expand/collapse buttons use the shared .secondary button style. */
.settings-toolbar-actions button { font-size: 0.76rem; padding: 0.45rem 0.85rem; }

.settings-section { margin-bottom: 1.8rem; }
.settings-section-head { margin: 0 0 0.75rem; padding-bottom: 0.55rem; border-bottom: 1px solid var(--line-amber); }
.settings-section-title { display: flex; align-items: center; gap: 0.5rem; font-size: 1.15rem; font-weight: 700; color: var(--amber-hi); }
.settings-section-title .ico { width: 1.15em; height: 1.15em; }
.settings-section-desc { margin: 0.35rem 0 0; font-size: 0.85rem; color: var(--muted); line-height: 1.45; max-width: 70ch; }
.settings-section .settings-category { margin-bottom: 0.6rem; }

/* Sub-section divider heading (e.g. Discord → Actions) */
.subhead { display: flex; align-items: center; gap: 0.5rem; margin: 2rem 1.5rem 0.9rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--line-amber); font-size: 0.9rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--amber); }
.subhead .ico { width: 1.05em; height: 1.05em; color: var(--amber); }
.group-note { margin: 0 0 0.9rem; font-size: 0.85rem; color: var(--muted); line-height: 1.5; }
.group-actions { display: flex; align-items: center; gap: 0.8rem; margin-top: 0.9rem; flex-wrap: wrap; }
.group-result { font-size: 0.82rem; color: var(--muted); }

/* Data tables (linked accounts, rosters, bans, user lists) */
.table-wrap { overflow-x: auto; margin-top: 0.4rem; }
.data-table { width: 100%; border-collapse: collapse; font-size: 0.86rem; }
.data-table th { text-align: left; padding: 0.5rem 0.7rem; border-bottom: 1px solid var(--line-amber); color: var(--muted); font-weight: 600; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em; white-space: nowrap; }
.data-table td { padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--line-2); }
.data-table tbody tr:hover { background: rgba(240, 130, 12, 0.05); }
.data-table tr.clickable { cursor: pointer; }
.data-table td.mono { font-family: var(--mono); font-size: 0.8rem; color: var(--muted); }
.data-table td.dim { color: var(--muted); font-size: 0.8rem; }

/* Click-to-edit row editors (Raid Times, Notifications…) */
.editor-rows { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.6rem; }
.editor-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.7rem; padding: 0.85rem 0.9rem; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); }
.editor-row .er-f { display: flex; flex-direction: column; gap: 0.28rem; font-size: 0.68rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); }
.editor-row .er-day { flex: 1 1 150px; }
.editor-row input { padding: 0.45rem 0.55rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--inset); color: var(--text); font-family: var(--mono); font-size: 0.85rem; }
.editor-row input:focus { outline: none; border-color: var(--amber); box-shadow: var(--focus-ring); }
.editor-row input[type="number"] { width: 6rem; }
.editor-row .rr-del { margin-left: auto; align-self: center; }
/* Make the (black by default) time/date picker icon visible on the dark theme */
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator { filter: invert(0.85); cursor: pointer; }
.editor-empty { color: var(--muted); font-size: 0.88rem; padding: 1.1rem 0; }
.editor-row.notif-row .er-msg { flex: 1 1 100%; }
.editor-row.notif-row .er-day { flex: 1 1 130px; }
.editor-row.notif-row .er-times { flex: 2 1 220px; }
.editor-row.notif-row .er-num { flex: 0 0 auto; }
.editor-row.notif-row .er-num input { width: 5rem; }
.editor-row.notif-row .er-col { flex: 0 0 auto; }
.editor-row.notif-row .nn-col-wrap { display: inline-flex; align-items: center; gap: 0.4rem; }
.editor-row.notif-row .nn-color-on { width: 1rem; height: 1rem; accent-color: var(--amber); cursor: pointer; }
.editor-row.notif-row .nn-del { align-self: flex-end; margin-bottom: 0.1rem; }
.editor-row input[type="color"] { width: 3rem; height: 2.25rem; padding: 2px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--inset); cursor: pointer; }

/* ── Economy Override editor ─────────────────────────────────────────────── */
.eco-subtabs { display: flex; gap: 0.4rem; margin: 0.6rem 0 1rem; }
.eco-subtab { background: var(--panel-2); border: 1px solid var(--line); color: var(--muted); font-size: 0.82rem; }
.eco-subtab.active { background: var(--amber); border-color: var(--amber); color: var(--on-amber); }
.eco-subtab:not(.active):hover { background: var(--panel); border-color: var(--line-amber); color: var(--amber-hi); }
.eco-subtab.active:hover { background: var(--amber-hi); border-color: var(--amber-hi); color: var(--on-amber); }
.eco-pane.hidden { display: none; }
.eco-global-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: 0.85rem; }
.eco-gfield { display: flex; flex-direction: column; gap: 0.22rem; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.7rem 0.8rem; }
.eco-glabel { font-size: 0.82rem; font-weight: 600; color: var(--text); }
.eco-ghelp { font-size: 0.73rem; color: var(--muted); line-height: 1.35; }
.eco-gin { margin-top: 0.3rem; padding: 0.45rem 0.55rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--inset); color: var(--text); font-family: var(--mono); font-size: 0.85rem; }
.eco-gin:focus, .eco-search:focus { outline: none; border-color: var(--amber); box-shadow: var(--focus-ring); }
/* Toggle fields (0/1 settings) */
.eco-gtoggle-f { flex-direction: row; align-items: center; justify-content: space-between; gap: 0.7rem; }
.eco-gtxt { display: flex; flex-direction: column; gap: 0.22rem; min-width: 0; }
.eco-switch { position: relative; flex: none; width: 40px; height: 22px; cursor: pointer; }
.eco-switch input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.eco-slider { position: absolute; inset: 0; background: var(--inset); border: 1px solid var(--line); border-radius: var(--pill); transition: background 0.15s, border-color 0.15s; }
.eco-slider::before { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--muted); transition: transform 0.15s, background 0.15s; }
.eco-switch input:checked + .eco-slider { background: rgba(240,130,12,0.25); border-color: var(--amber); }
.eco-switch input:checked + .eco-slider::before { transform: translateX(18px); background: var(--amber-hi); }
/* Vehicle limits editor */
.eco-veh { margin-top: 1.3rem; padding-top: 1rem; border-top: 1px solid var(--line-amber); }
.eco-veh-head { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; }
.eco-veh-title { margin: 0; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--text); }
.eco-veh-sub { font-family: var(--mono); font-size: 0.72rem; color: var(--muted); text-transform: none; letter-spacing: 0; margin-left: 0.35rem; }
.eco-veh-rows { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.6rem; }
.eco-veh-row { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.eco-veh-row .evr-group { flex: 1 1 240px; min-width: 0; }
.eco-veh-row .evr-max { flex: 0 0 150px; }
.eco-veh-row input { padding: 0.45rem 0.55rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--inset); color: var(--text); font-family: var(--mono); font-size: 0.85rem; }
.eco-veh-row input:focus { outline: none; border-color: var(--amber); }
.eco-trader { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); margin-bottom: 0.55rem; }
.eco-trader[open] { border-color: var(--line-amber); }
.eco-trader-h { display: flex; justify-content: space-between; align-items: center; gap: 0.6rem; padding: 0.7rem 0.9rem; cursor: pointer; list-style: none; }
.eco-trader-h::-webkit-details-marker { display: none; }
.eco-trader-name { font-weight: 600; color: var(--amber); }
.eco-trader-n { font-family: var(--mono); font-size: 0.76rem; color: var(--muted); }
.eco-trader-body { padding: 0 0.9rem 0.9rem; }
.eco-items { display: flex; flex-direction: column; gap: 0.5rem; }
.eco-item { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.6rem; padding: 0.6rem 0.65rem; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); }
.eco-item-id { display: flex; align-items: center; gap: 0.5rem; flex: 1 1 180px; min-width: 140px; }
.eco-item-img { width: 34px; height: 34px; object-fit: contain; flex: none; }
/* item image placeholders (shown when an item has no image — free tier / no active subscription) */
.eco-item-imgslot { width: 34px; height: 34px; flex: none; display: inline-flex; align-items: center; justify-content: center; }
.eco-item-imgslot img { width: 34px; height: 34px; object-fit: contain; }
.eco-item-ph { width: 22px; height: 22px; color: var(--muted); }
.mp-c-ph { width: 14px; height: 14px; color: var(--muted); }
.cmd-sg-ph { display: inline-flex; align-items: center; justify-content: center; color: var(--muted); }
.cmd-sg-ph .ico { width: 16px; height: 16px; }
.gl-preview-ph { width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; background: var(--inset); border-radius: 6px; flex: none; color: var(--muted); }
.gl-preview-ph .ico { width: 30px; height: 30px; }
.eco-item-txt { display: flex; flex-direction: column; min-width: 0; }
.eco-item-name { font-weight: 600; font-size: 0.87rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.eco-item-code { font-family: var(--mono); font-size: 0.68rem; color: var(--faint); }
.eco-item .er-f { display: flex; flex-direction: column; gap: 0.22rem; font-size: 0.62rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.eco-item .er-f input, .eco-item .er-f select { width: 5.4rem; padding: 0.4rem 0.45rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); color: var(--text); font-family: var(--mono); font-size: 0.82rem; }
.eco-item .ei-del { align-self: center; margin-left: auto; }
.eco-add { position: relative; margin-top: 0.75rem; }
.eco-add-search { display: flex; flex-direction: column; gap: 0.22rem; font-size: 0.62rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); max-width: 340px; }
.eco-search { padding: 0.45rem 0.55rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); color: var(--text); font-size: 0.85rem; }
.eco-results { position: absolute; z-index: 20; left: 0; max-width: 360px; width: 100%; background: var(--panel-2); border: 1px solid var(--line-amber); border-radius: var(--radius); margin-top: 0.2rem; max-height: 280px; overflow-y: auto; }
.eco-res { display: flex; align-items: center; gap: 0.5rem; width: 100%; text-align: left; background: none; border: none; border-bottom: 1px solid var(--line-2); color: var(--text); border-radius: 0; padding: 0.45rem 0.6rem; }
.eco-res:hover { background: rgba(240,130,12,0.08); color: var(--text); }
.eco-res img { width: 26px; height: 26px; object-fit: contain; flex: none; }
.eco-res-ph { width: 26px; height: 26px; flex: none; display: flex; align-items: center; justify-content: center; color: var(--muted); }
.eco-res-ph .ico { width: 18px; height: 18px; }
.eco-res-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.eco-res-code { font-family: var(--mono); font-size: 0.68rem; color: var(--faint); }
.eco-res-empty { padding: 0.5rem 0.6rem; color: var(--muted); font-size: 0.82rem; }

.settings-category {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.settings-category[open] { border-color: var(--line-amber); }

.settings-cat-summary {
  cursor: pointer;
  list-style: none;
  padding: 0.95rem 1.3rem;
  user-select: none;
}

.settings-cat-summary::-webkit-details-marker { display: none; }
.settings-cat-summary:hover .settings-cat-title { color: var(--amber-hi); }

.settings-cat-title {
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: 0.82rem;
  color: var(--text);
}

.settings-cat-title::before {
  content: "▸";
  color: var(--amber);
  margin-right: 0.6rem;
  display: inline-block;
  transition: transform 0.15s;
}

.settings-category[open] .settings-cat-title::before { transform: rotate(90deg); }

.settings-cat-desc {
  display: block;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--muted);
  letter-spacing: 0.02em;
  margin-top: 0.3rem;
  padding-left: 1.2rem;
}

.settings-cat-body {
  padding: 0.4rem 1.3rem 1.2rem;
  border-top: 1px solid var(--line);
}

.settings-cat-body > .settings-field:first-child { margin-top: 0.8rem; }

.settings-cat-body .settings-group {
  background: var(--bg-2);
  margin-top: 0.85rem;
}

.filtered-hidden { display: none !important; }

/* INI setting metadata: unit/type badge + description help text */
.ini-type {
  margin-left: 0.5rem;
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--line-amber);
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--amber);
  vertical-align: middle;
}

.ini-desc {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.74rem;
  line-height: 1.45;
  color: var(--muted);
}

/* checkbox rows need to wrap so the description sits on its own line */
.settings-field.checkbox { flex-wrap: wrap; }
.settings-field.checkbox .ini-desc { flex-basis: 100%; margin-top: 0.35rem; }

.sync-notify-btn {
  align-self: flex-start;
  margin-top: 0.55rem;
  padding: 0.4rem 0.85rem;
  font-size: 0.78rem;
  background: var(--panel-2);
  color: var(--amber);
  border: 1px solid var(--line-amber);
}
/* Keep the quiet background on hover — without it the global amber button
   hover shines through and amber-on-amber text becomes unreadable. */
.sync-notify-btn:hover { background: var(--panel-2); border-color: var(--amber-hi); color: var(--amber-hi); }
.sync-notify-btn:disabled { opacity: 0.5; cursor: default; }

.settings-group {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem 1.4rem 1.2rem;
}

.settings-group > legend {
  font-weight: 600;
  padding: 0 0.5rem;
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--amber);
}

.settings-group .settings-group {
  background: var(--bg-2);
  margin-top: 0.75rem;
}

/* Premium-locked group (Field Console without an active subscription). */
.settings-group.settings-locked { border-color: var(--line-amber); position: relative; }
.settings-group.settings-locked > legend { color: var(--muted); }
.settings-group.settings-locked .settings-field,
.settings-group.settings-locked .settings-group { opacity: 0.55; pointer-events: none; }
.settings-lock-note {
  opacity: 1; margin: 0.2rem 0 1rem; padding: 0.6rem 0.85rem;
  background: rgba(240, 130, 12, 0.1); border: 1px solid var(--line-amber);
  border-radius: var(--radius); color: var(--amber-hi); font-size: 0.85rem; line-height: 1.5;
}
.settings-lock-note strong { color: var(--amber-hi); }
.settings-lock-note .link-btn { font-size: 0.85rem; vertical-align: baseline; }

/* Two-column row: name + description on the left, the control on the right —
   scannable and clear, instead of stacked mystery inputs. */
.settings-field {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 360px);
  grid-template-areas: "label control" "desc control";
  align-items: center;
  column-gap: 1.5rem;
  row-gap: 0.25rem;
  margin: 0;
  padding: 0.8rem 0;
  border-top: 1px solid var(--line-2);
}
.settings-field:first-child { border-top: none; }

.settings-field.checkbox {
  grid-template-columns: minmax(0, 1fr) auto;
}
.settings-field.checkbox input[type="checkbox"] { grid-area: control; justify-self: end; }

.settings-field label {
  grid-area: label;
  font-family: var(--ui);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text);
  text-transform: none;
  letter-spacing: normal;
}

.settings-field .ini-desc {
  grid-area: desc;
  font-family: var(--ui);
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.45;
  margin: 0;
  letter-spacing: normal;
  text-transform: none;
}
/* A field can carry a second hint (e.g. restart times + the sync note) and an
   action button. Only the FIRST description owns the "desc" grid area — the rest
   would overlap it in the same cell. Flow them into fresh rows in column 1. */
.settings-field .ini-desc ~ .ini-desc { grid-area: auto; grid-column: 1; margin-top: 0.15rem; }
.settings-field .sync-notify-btn { grid-area: auto; grid-column: 1; justify-self: start; }
/* Image (logo / wallpaper) upload control sits under the URL input. */
.settings-field .img-upload { grid-area: auto; grid-column: 2; display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem 0.7rem; margin-top: 0.45rem; }

/* Leaderboard/stat visibility checklists: span the FULL field width and flow into columns, with
   group headers — so a long category list stays scannable instead of a cramped single column. */
.settings-field.lb-vis-field { grid-template-columns: 1fr; grid-template-areas: "label" "desc" "control"; align-items: start; }
.settings-field.lb-vis-field > label { grid-area: label; }
.lb-vis {
  grid-area: control; margin-top: 0.6rem;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 0.1rem 1.4rem; align-content: start;
  background: var(--inset, rgba(0,0,0,0.15)); border: 1px solid var(--line-2); border-radius: var(--radius-md, 6px);
  padding: 0.7rem 0.9rem;
}
.lb-vis-cats { max-height: 460px; overflow-y: auto; }
.lb-vis-groups { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.lb-vis .lb-vis-grp {
  grid-column: 1 / -1; font-family: var(--ui); font-weight: 700; font-size: 0.72rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--amber, #f0820c); margin: 0.85rem 0 0.3rem; padding-bottom: 0.25rem;
  border-bottom: 1px solid var(--line-2);
}
.lb-vis .lb-vis-grp:first-child { margin-top: 0; }
/* IMPORTANT: `.settings-field label { grid-area: label }` (the 2-col field grid) also matches these
   inner labels and would pile them all into the top-left cell. Reset placement so they flow normally. */
.lb-vis .lang-check, .lb-vis .ini-desc { grid-area: auto; grid-column: auto; grid-row: auto; }
.lb-vis .lang-check { display: flex; align-items: center; gap: 0.5rem; font-family: var(--ui); font-weight: 400;
  font-size: 0.86rem; color: var(--text); padding: 0.2rem 0; cursor: pointer; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lb-vis .lang-check input[type="checkbox"] { flex: none; margin: 0; width: 1rem; height: 1rem; }
@media (max-width: 640px) { .settings-field .img-upload { grid-column: 1; } }
.img-upload-btn { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.4rem 0.7rem; background: var(--panel-2); border: 1px solid var(--line-amber); color: var(--amber-hi); border-radius: var(--radius); cursor: pointer; font-family: var(--ui); font-size: 0.82rem; }
.img-upload-btn:hover { background: var(--amber); color: var(--on-amber); }
.img-upload-btn .ico { width: 0.9em; height: 0.9em; }
.img-upload-status { font-size: 0.8rem; color: var(--muted); }
.img-upload-prev { display: none; max-height: 40px; max-width: 170px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg-2); object-fit: contain; }
/* Theme colour picker swatch next to the hex input. */
.settings-field .color-field { grid-area: auto; grid-column: 2; margin-top: 0.45rem; }
@media (max-width: 640px) { .settings-field .color-field { grid-column: 1; } }
.color-pick { width: 48px; height: 30px; padding: 0; border: 1px solid var(--line-amber); border-radius: var(--radius); background: var(--inset); cursor: pointer; }

.settings-field input[type="text"],
.settings-field input[type="number"],
.settings-field input[type="password"],
.settings-field textarea,
.settings-field select { grid-area: control; }

@media (max-width: 640px) {
  .settings-field {
    grid-template-columns: 1fr;
    grid-template-areas: "label" "desc" "control";
    row-gap: 0.4rem;
  }
  .settings-field.checkbox {
    grid-template-columns: 1fr auto;
    grid-template-areas: "label control" "desc desc";
  }
}

.settings-field input[type="text"],
.settings-field input[type="number"],
.settings-field input[type="password"],
.settings-field textarea,
.setup-box .settings-field input {
  padding: 0.55rem 0.65rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--inset);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.9rem;
  width: 100%;
}

.settings-field input:focus,
.settings-field textarea:focus,
.setup-box .settings-field input:focus,
.login-box input:focus {
  outline: none;
  border-color: var(--amber);
  box-shadow: var(--focus-ring);
}

.settings-field textarea {
  min-height: 4.5rem;
  resize: vertical;
  white-space: pre;
}

.settings-field input[type="checkbox"] {
  width: 1.1rem;
  height: 1.1rem;
  accent-color: var(--amber);
}

/* ── Game Settings tabs ────────────────────────────────────────────────── */

.gs-tabs {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
  margin: 1.2rem 1.5rem 0;
  border-bottom: 1px solid var(--line);
}

.gs-tab {
  padding: 0.55rem 1.1rem;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0;
  background: transparent;
  color: var(--muted);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.gs-tab:hover { color: var(--text); background: var(--panel-2); border-color: var(--line); }

.gs-tab.active {
  background: var(--panel);
  border-color: var(--line);
  color: var(--amber);
  margin-bottom: -1px;
}

.gs-tab-content {
  margin: 0 1.5rem 2rem;
  padding-top: 1.25rem;
}
/* Notes/messages inside a tab already sit in the padded tab body — drop the extra
   horizontal margin so they line up with the header and form fields. */
.gs-tab-content > .settings-note,
.gs-tab-content > .settings-message { margin-left: 0; margin-right: 0; }

/* Editor ⇄ JSON mode toggle */
.gs-mode { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.gs-mode-btn { background: var(--panel-2); color: var(--muted); border: 0; padding: 0.42rem 0.85rem; font-family: var(--ui); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; cursor: pointer; }
.gs-mode-btn + .gs-mode-btn { border-left: 1px solid var(--line); }
.gs-mode-btn.active { background: var(--amber); color: var(--bg); font-weight: 700; }
.gs-mode-btn.active:hover { background: var(--amber-hi); color: var(--bg); }
.gs-mode-btn:not(.active):hover { background: var(--panel); color: var(--amber-hi); }
.gs-tab-content.json-mode .gs-editor-body { display: none; }
.gs-tab-content:not(.json-mode) .gs-json-pane { display: none; }
.gs-tab-content.json-mode .gs-add-btn { display: none; }
.gs-json-ta { width: 100%; min-height: 320px; box-sizing: border-box; }
.gs-json-err { margin: 0.55rem 0 0; }
.gs-json-err.hidden { display: none; }

.gs-tab-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.85rem;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.gs-tab-header h2, .gs-tab-header h3 {
  margin: 0;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text);
}

.gs-btn-row { display: flex; gap: 0.5rem; }

/* .gs-save-btn / #settings-save-btn / #discord-config-save inherit the unified
   primary button — all Save buttons now look identical. */

.gs-tab-content .secondary {
  padding: 0.45rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel-2);
  color: var(--text);
  font-size: 0.78rem;
  text-transform: uppercase;
}
.gs-tab-content .secondary:hover { border-color: var(--line-amber); color: var(--amber-hi); }

.gs-ini-form { margin: 0; }

.gs-user-lists {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.4rem;
}

@media (max-width: 700px) {
  .gs-user-lists { grid-template-columns: 1fr; }
}

.gs-list-section {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.gs-list-section textarea,
.gs-code-textarea {
  width: 100%;
  padding: 0.75rem 0.85rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--inset);
  color: var(--data-text);
  font-family: var(--mono);
  font-size: 0.85rem;
  line-height: 1.6;
  resize: vertical;
}

.gs-code-textarea:focus,
.gs-list-section textarea:focus {
  outline: none;
  border-color: var(--amber);
}

/* ── Interactive user lists (admins / bans / whitelist / exclusive) ────────── */
.ul-section { background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.9rem 1rem; gap: 0.6rem; }
.ul-wide { grid-column: 1 / -1; }
.ul-count { color: var(--muted); font-family: var(--mono); font-weight: 600; letter-spacing: 0; text-transform: none; }
.ul-note { margin: 0; }
.ul-add { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: flex-start; }
.ul-ac-wrap { position: relative; flex: 1 1 200px; min-width: 0; }
.ul-add-input { width: 100%; box-sizing: border-box; }
.ul-add-note { flex: 1 1 140px; min-width: 0; }
.ul-add input { background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); color: var(--text); font-family: var(--ui); font-size: 0.85rem; padding: 0.45rem 0.6rem; }
.ul-add input:focus { outline: none; border-color: var(--amber); }
/* Styled autocomplete dropdown */
.ul-ac { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20; max-height: 260px; overflow-y: auto; background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius); box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45); padding: 0.25rem; }
.ul-ac.hidden { display: none; }
.ul-ac-item { display: flex; align-items: center; gap: 0.55rem; width: 100%; text-align: left; background: transparent; border: 0; border-radius: var(--radius); color: var(--text); padding: 0.4rem 0.5rem; cursor: pointer; }
.ul-ac-item:hover, .ul-ac-item:focus { background: var(--hover-bg); color: var(--amber-hi); }
.ul-ac-name { font-weight: 600; font-size: 0.85rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ul-ac-id { margin-left: auto; font-size: 0.72rem; color: var(--muted); white-space: nowrap; }
.ul-avatar.sm { width: 24px; height: 24px; }
.ul-avatar.sm .ico { font-size: 0.85rem; }
.ul-rows { display: flex; flex-direction: column; gap: 0.35rem; }
.ul-empty { color: var(--muted); font-size: 0.85rem; margin: 0.2rem 0; }
.ul-row { display: flex; align-items: center; gap: 0.6rem; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.45rem 0.6rem; }
.ul-avatar { display: inline-flex; width: 30px; height: 30px; flex: none; align-items: center; justify-content: center; border-radius: 50%; background: var(--panel); border: 1px solid var(--line); }
.ul-avatar .ico { font-size: 1rem; color: var(--amber); }
.ul-idcol { display: flex; flex-direction: column; gap: 0.05rem; min-width: 0; flex: 1 1 auto; }
.ul-name { font-weight: 600; font-size: 0.9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ul-sid { font-size: 0.74rem; color: var(--muted); }
.ul-flags { display: flex; align-items: center; gap: 0.7rem; flex: none; }
.ul-flag { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.76rem; color: var(--muted); white-space: nowrap; cursor: pointer; }
.ul-flag input { accent-color: var(--amber); }
.ul-extra { font-family: var(--mono); font-size: 0.7rem; color: var(--standby); border: 1px dashed var(--line); border-radius: var(--radius); padding: 0.05rem 0.35rem; }
.ul-bancol { display: flex; flex-direction: column; gap: 0.1rem; flex: 1 1 140px; min-width: 0; text-align: right; }
.ul-bannote { font-size: 0.8rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; }
.ul-when { font-size: 0.7rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.ul-del { flex: none; width: 28px; height: 28px; cursor: pointer; background: transparent; border: 1px solid var(--line); border-radius: var(--radius); color: var(--muted); font-size: 0.85rem; line-height: 1; }
.ul-del:hover { color: var(--alarm); border-color: var(--alarm); background: transparent; }

/* ── Setup wizard ──────────────────────────────────────────────────────── */

.setup-center {
  align-items: center;
  justify-content: center;
  padding: 2.5rem 1rem;
}

.setup-box {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg, 14px);
  padding: 2rem 2.4rem 2.2rem;
  width: 100%;
  max-width: 720px;
  box-shadow: 0 24px 60px -28px rgba(0, 0, 0, 0.7);
}
@media (max-width: 640px) { .setup-box { padding: 1.5rem 1.3rem 1.7rem; } }

.setup-brand {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.4rem;
  padding-bottom: 1.2rem;
  border-bottom: 1px solid var(--line);
}

.setup-brand img {
  width: 52px;
  height: 52px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  flex-shrink: 0;
}
.setup-brand-text { min-width: 0; }

.setup-box h1 {
  font-size: 1.15rem;
  margin: 0;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.setup-tagline {
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  margin: 0.25rem 0 0;
}

/* ── Wizard progress bar ───────────────────────────────────────────────── */
.su-progress {
  height: 6px;
  border-radius: 99px;
  background: var(--inset);
  overflow: hidden;
  margin-bottom: 1rem;
}
.su-progress-lg { height: 9px; margin: 0.4rem 0 1.2rem; }
.su-progress-fill {
  height: 100%;
  width: 0;
  border-radius: 99px;
  background: linear-gradient(90deg, var(--amber), var(--amber-hi));
  transition: width 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Indeterminate shimmer for the long install phases. */
.su-progress-anim {
  background-image: linear-gradient(90deg, var(--amber), var(--amber-hi)),
    linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.35) 50%, transparent 100%);
  background-size: 100% 100%, 40% 100%;
  background-repeat: no-repeat, no-repeat;
  animation: su-shimmer 1.4s linear infinite;
}
@keyframes su-shimmer { from { background-position: 0 0, -40% 0; } to { background-position: 0 0, 140% 0; } }

/* Indeterminate "working" bar — moving diagonal stripes filling the track. Used
   during the game download, where SteamCMD gives no reliable fine-grained
   progress. Clearly animating (never a frozen fill), and the stripes read as
   "in progress, unknown %" rather than a solid "done" bar. */
.su-progress-fill.su-progress-indet {
  width: 100% !important;
  transition: none;
  background-image: repeating-linear-gradient(
    -45deg,
    var(--amber) 0, var(--amber) 12px,
    var(--amber-hi) 12px, var(--amber-hi) 24px
  );
  background-size: 34px 100%;
  animation: su-indet 0.7s linear infinite;
}
@keyframes su-indet { from { background-position: 0 0; } to { background-position: 34px 0; } }

/* ── Stepper dots ──────────────────────────────────────────────────────── */
.su-stepper {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}
.su-dot {
  flex: 1 1 0;
  min-width: 12px;
  height: 4px;
  border-radius: 99px;
  background: var(--line-2, #2a2c22);
  border: 0;
  padding: 0;
  transition: background 0.3s;
}
.su-dot.done { background: var(--amber); }
.su-dot.active { background: var(--amber-hi); box-shadow: 0 0 0 3px rgba(240, 130, 12, 0.18); }
.su-dot.done { cursor: pointer; }

.su-step-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1.2rem;
}
.su-step-title {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text);
}
.su-step-count {
  font-family: var(--mono);
  font-size: 0.74rem;
  color: var(--faint);
  white-space: nowrap;
}

/* ── Wizard steps + stacked fields ─────────────────────────────────────── */
.su-step { animation: su-fade 0.28s ease; }
.su-step[hidden] { display: none; }
@keyframes su-fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.su-field { margin-bottom: 1.35rem; }
.su-field:last-child { margin-bottom: 0; }
.su-field > label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.15rem;
}
.su-field .su-help {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--muted);
}
.su-field input[type="text"],
.su-field input[type="number"],
.su-field input[type="password"] {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--inset);
  color: var(--text);
  font-family: var(--mono);
  font-size: 0.9rem;
}
.su-field input:focus {
  outline: none;
  border-color: var(--amber);
  box-shadow: var(--focus-ring);
}

/* Checkbox field: box + label on one row, help underneath. */
.su-field.su-check {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: 0.6rem;
  row-gap: 0.35rem;
}
.su-field.su-check input[type="checkbox"] {
  width: 1.2rem;
  height: 1.2rem;
  accent-color: var(--amber);
  margin: 0;
}
.su-field.su-check > label { margin: 0; grid-column: 2; }
.su-field.su-check .su-help { grid-column: 1 / -1; margin: 0; }

.su-req { color: #f87171; font-weight: 700; }
.su-opt, .su-hint { font-weight: normal; font-size: 0.82em; color: var(--faint); }

/* ── Review summary ────────────────────────────────────────────────────── */
.su-review {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-2);
  overflow: hidden;
}
.su-review-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 0.9rem;
  border-top: 1px solid var(--line-2, #2a2c22);
  font-size: 0.86rem;
}
.su-review-row:first-child { border-top: 0; }
.su-review-row .k { color: var(--muted); }
.su-review-row .v { font-family: var(--mono); color: var(--text); text-align: right; word-break: break-word; }
.su-review-row .v.muted { color: var(--faint); }

/* ── Wizard nav ────────────────────────────────────────────────────────── */
.su-nav {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-top: 1.6rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--line);
}
.su-btn-primary, .su-btn-ghost {
  padding: 0.65rem 1.3rem;
  border-radius: var(--radius);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
}
.su-btn-primary {
  margin-left: auto;
  border: 1px solid var(--amber);
  background: var(--amber);
  color: var(--on-amber);
}
.su-btn-primary:hover { background: var(--amber-hi); border-color: var(--amber-hi); }
.su-btn-primary:disabled { opacity: 0.55; cursor: not-allowed; }
.su-btn-ghost {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
}
.su-btn-ghost:hover { color: var(--text); border-color: var(--faint); }
.su-btn-ghost[hidden] { display: none; }

/* ── Install progress log + done / error ───────────────────────────────── */
.su-log {
  background: var(--inset);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
  font-family: var(--mono);
  font-size: 0.82rem;
  line-height: 1.7;
  min-height: 180px;
  max-height: 420px;
  overflow-y: auto;
  color: var(--data-text);
}
.su-done-title { color: #4ade80; margin: 1.2rem 0 0.4rem; font-weight: 700; }
.su-done-text { color: var(--muted); font-size: 0.9em; margin: 0; line-height: 1.6; }
.su-install-error { color: #f87171; margin: 1rem 0 0; }

/* First-run wizard language picker (top-right of the setup box header) — compact
   so it doesn't dominate the header. */
.su-lang { margin-left: auto; flex: none; }
.su-lang[hidden] { display: none; }
.su-lang .admin-lang-select { padding: 0.32rem 0.55rem; font-size: 0.76rem; gap: 0.4rem; letter-spacing: 0.02em; }
.su-lang .lang-flag { width: 16px; height: 12px; }
.su-lang .lang-dd-chev { font-size: 0.62rem; }
.su-lang .lang-dd-list { min-width: 150px; }
.su-lang .lang-dd-item { font-size: 0.8rem; padding: 0.4rem 0.55rem; }
.su-lang .lang-dd-item .lang-flag { width: 18px; height: 13.5px; }

/* ── Field Console premium promo (Frontend tab without a subscription) ────── */
.fc-promo {
  max-width: 580px;
  margin: 2.5rem auto;
  text-align: center;
  padding: 2.2rem 1.8rem;
  background: linear-gradient(135deg, rgba(240, 130, 12, 0.14), rgba(240, 130, 12, 0.02));
  border: 1px solid var(--line-amber);
  border-radius: var(--radius-lg, 14px);
}
.fc-promo-icon {
  width: 54px; height: 54px; margin: 0 auto 1rem;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(240, 130, 12, 0.16);
  border: 1px solid var(--line-amber);
  color: var(--amber-hi);
}
.fc-promo-icon .ico { width: 1.6em; height: 1.6em; }
.fc-promo h3 { margin: 0 0 0.6rem; font-size: 1.05rem; letter-spacing: 0.02em; color: var(--text); }
.fc-promo p { margin: 0 auto 1.4rem; max-width: 46ch; color: var(--muted); font-size: 0.9rem; line-height: 1.6; }
.fc-promo-btn {
  padding: 0.65rem 1.4rem;
  border: 1px solid var(--amber);
  border-radius: var(--radius);
  background: var(--amber);
  color: var(--on-amber);
  font-size: 0.9rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  cursor: pointer;
}
.fc-promo-btn:hover { background: var(--amber-hi); border-color: var(--amber-hi); }

/* ── Premium lock overlay (frosted glass over visible-but-locked settings) ── */
.prem-lock-wrap { position: relative; min-height: 210px; border-radius: var(--radius-lg); }
.prem-lock-overlay {
  position: absolute; inset: 0; z-index: 6;
  display: flex; align-items: flex-start; justify-content: center;
  padding: 1.6rem 1.2rem;
  background: rgba(10, 11, 8, 0.5);
  -webkit-backdrop-filter: blur(2.5px);
  backdrop-filter: blur(2.5px);
  border-radius: var(--radius-lg);
}
.prem-lock-card {
  position: sticky; top: 1.2rem;
  max-width: 480px; text-align: center;
  padding: 1.5rem 1.6rem;
  background: linear-gradient(135deg, rgba(240, 130, 12, 0.18), rgba(18, 18, 14, 0.94));
  border: 1px solid var(--line-amber);
  border-radius: var(--radius-lg);
  box-shadow: 0 18px 44px -14px rgba(0, 0, 0, 0.7);
}
.prem-lock-card h3 { margin: 0 0 0.5rem; font-size: 1rem; letter-spacing: 0.02em; color: var(--text); }
.prem-lock-card p { margin: 0 auto 1.2rem; max-width: 44ch; color: var(--muted); font-size: 0.86rem; line-height: 1.55; }

/* ── Focus visibility (a11y) ───────────────────────────────────────────── */

button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
.gs-tab:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 1px;
}

/* ── Responsive ────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
  header { padding: 0.85rem 1rem; }
  .brand-title { font-size: 1.1rem; }
  /* Tighten the 1.5rem desktop gutters to 1rem so content isn't squeezed. */
  .status-card, .leaderboards, .players, .logs, .controls,
  .screen-bar, .subhead, .settings-form, .settings-note, .settings-message,
  .prem-body, .adm-card, .adm-form, .gs-tabs, .gs-tab-content,
  .players-admin, .bans, .cmd-console, #pl-lockwrap, .pl-workspace, .mu-card {
    margin-left: 1rem; margin-right: 1rem;
  }
  .admin-nav { padding: 0 0.75rem; }
  .anav-btn { padding: 0.75rem 0.7rem; font-size: 0.85rem; }
  /* Modals fill the phone width with slimmer padding. */
  .amodal { padding: 0.6rem; }
  .amodal-box { padding: 1.1rem 1rem; }
  /* Roster table scrolls sideways instead of crushing its columns. */
  .roster-table { min-width: 640px; }
}
/* The roster wrapper always allows horizontal scrolling (kicks in on phones). */
#player-roster { overflow-x: auto; }

/* Phone: enlarge icon/close buttons to a comfortable ~40px touch target. */
@media (max-width: 640px) {
  .amodal-close, .pd-close, .ul-del, .rr-admin-btn {
    width: 40px; height: 40px;
  }
  .mp-close { width: 34px; height: 34px; }
}
/* Body-positioned dropdowns never grow wider than the viewport on mobile. */
.cdd-menu, .roster-country-menu, .lang-dd-list { max-width: calc(100vw - 16px); }

/* ── Reduced motion ────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ── Players & bans (admin) ───────────────────────────────────────────────── */
.roster-bar { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.9rem; }
.player-search { flex: 1; display: flex; align-items: center; gap: 0.5rem; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.5rem 0.7rem; }
.player-search .ico { color: var(--muted); flex: none; }
.player-search input { flex: 1; background: transparent; border: 0; outline: none; color: var(--text); font-family: var(--ui); font-size: 0.95rem; }
.roster-count { font-family: var(--mono); font-size: 0.82rem; color: var(--muted); white-space: nowrap; }
/* Filter / sort / page-size dropdowns in the roster + chat toolbars. */
.roster-select {
  padding: 0.5rem 0.6rem; font-family: var(--ui); font-size: 0.85rem;
  background: var(--inset); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius);
  cursor: pointer; outline: none;
}
.roster-select:hover, .roster-select:focus { border-color: var(--line-amber); }
/* Custom country filter dropdown (flags in a native <select> aren't possible) */
.roster-country { position: relative; }
.roster-country-btn { display: inline-flex; align-items: center; gap: 0.4rem; }
.roster-country-btn .rr-flag, .roster-country-btn .rr-flag-unknown { margin-right: 0.1rem; }
.dd-caret { color: var(--muted); font-size: 0.7rem; }
.roster-country-menu { position: absolute; z-index: 40; top: calc(100% + 4px); left: 0; min-width: 12rem; max-height: 320px; overflow-y: auto; background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius); padding: 0.3rem; box-shadow: 0 8px 24px rgba(0,0,0,0.45); }
.rc-item { display: flex; align-items: center; gap: 0.5rem; width: 100%; padding: 0.4rem 0.55rem; background: none; border: none; border-radius: var(--radius); color: var(--text); cursor: pointer; font: inherit; font-size: 0.85rem; text-align: left; }
.rc-item:hover { background: var(--hover-bg); color: var(--amber-hi); }
.rc-item.on { background: rgba(240, 130, 12, 0.18); color: var(--amber-hi); }
.rc-name { flex: 1; }
.rc-n { font-family: var(--mono); font-size: 0.78rem; color: var(--muted); }
.rc-empty { display: block; padding: 0.5rem; color: var(--muted); font-size: 0.82rem; }
/* Enhanced native <select> → styled dropdown identical to the country/language pickers */
.cdd { position: relative; display: inline-flex; }
.cdd-native { position: absolute; width: 1px; height: 1px; padding: 0; margin: 0; opacity: 0; pointer-events: none; }
.cdd-btn { display: inline-flex; align-items: center; gap: 0.5rem; white-space: nowrap; }
/* higher specificity than the global `button { justify-content:center }` + chevron rule → left-align + drop bg arrow */
.cdd .cdd-btn { justify-content: flex-start; text-align: left; background-image: none; padding-right: 0.7rem; }
.cdd-lbl { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: left; }
.cdd .cdd-btn .dd-caret { margin-left: auto; padding-left: 0.4rem; }
/* Menu is moved to <body> and absolutely positioned in page coords by JS (escapes clip/transform). */
.cdd-menu { position: absolute; z-index: 3000; min-width: 8rem; overflow-y: auto; background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius); padding: 0.3rem; box-shadow: 0 10px 28px rgba(0,0,0,0.5); }
.cdd-menu[hidden] { display: none; }
.cdd-item { display: flex; align-items: center; justify-content: flex-start; gap: 0.5rem; width: 100%; white-space: nowrap; padding: 0.4rem 0.55rem; background: none; border: none; border-radius: var(--radius); color: var(--text); cursor: pointer; font: inherit; font-size: 0.85rem; text-align: left; }
.cdd-item:hover { background: var(--hover-bg); color: var(--amber-hi); }
.cdd-item.on { background: rgba(240, 130, 12, 0.18); color: var(--amber-hi); }
/* Checkable items — a multi-select rendered as the same dropdown, so "vehicles AND chests"
   is one familiar control instead of a native multi-list. */
.cdd-item.cdd-check { gap: 0.55rem; }
.cdd-item.cdd-check .cdd-box {
  flex: none; width: 14px; height: 14px; border-radius: 3px;
  border: 1px solid var(--line-amber, var(--line)); background: var(--inset);
}
.cdd-item.cdd-check.on { background: none; }
.cdd-item.cdd-check.on .cdd-box {
  background: var(--amber); border-color: var(--amber);
  /* tick drawn in the box, so no sprite icon is needed inside a generated menu */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230d0e0a' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12.5l4.5 4.5L19 7.5'/></svg>");
  background-size: 11px 11px; background-repeat: no-repeat; background-position: center;
}
.cdd-item.cdd-check .cdd-t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* full-width contexts: settings forms (grid control cell), row editors, game settings */
.settings-field .cdd, .er-f .cdd, .gs-field .cdd { grid-area: control; display: flex; width: 100%; }
.settings-field .cdd-btn, .er-f .cdd-btn, .gs-field .cdd-btn { flex: 1; width: 100%; }
/* Live-map layer filters: compact + full-width, matching the original .sf-select look */
.map-layers .cdd { display: flex; width: 100%; }
.map-layers .cdd-btn { width: 100%; padding: 0.4rem 0.55rem; font-size: 0.78rem; font-weight: 600; background: var(--panel-2); }
.map-layers .cdd-menu { font-size: 0.8rem; }
@media (max-width: 900px) { .roster-bar { flex-wrap: wrap; } .player-search { flex-basis: 100%; } }
/* Chat history: channel badge + wrapping message cell. */
.chat-ts { white-space: nowrap; }
.chat-ch { display: inline-block; padding: 0.1rem 0.5rem; border-radius: var(--pill); font-size: 0.75rem; font-weight: 600; background: var(--inset); border: 1px solid var(--line); color: var(--muted); }
.chat-ch-global { color: var(--amber-hi); border-color: var(--line-amber); }
.chat-ch-squad { color: #57f287; }
.chat-ch-local { color: #6cb2f7; }
.chat-ch-admin { color: var(--alarm); }
.chat-msg { word-break: break-word; }
/* Chat table: shrink time/channel/player to their content so the MESSAGE column
   gets all remaining width — everything packs left instead of spreading out. */
.chat-table th, .chat-table td { text-align: left; }
.chat-table th:nth-child(1), .chat-table td:nth-child(1),
.chat-table th:nth-child(2), .chat-table td:nth-child(2),
.chat-table th:nth-child(3), .chat-table td:nth-child(3) { width: 1%; white-space: nowrap; }
/* Log Viewer table (time · category · entry): undo the chat-table shrink on the
   LAST column so the log entry takes all remaining width and wraps normally. */
.gamelog-table th:last-child, .gamelog-table td:last-child { width: auto; white-space: normal; }
.gamelog-line { font-family: var(--mono); font-size: 0.85rem; }
/* Player names inside a log entry are clickable; 📍 opens the position on scum-map. */
/* Raw log line reads as plain text; players + locations get a subtle underline to show they're
   clickable, without recolouring the sentence (see increment 19). */
.gl-player { color: inherit; cursor: pointer; text-decoration: underline; text-decoration-color: rgba(240, 130, 12, 0.4); text-decoration-thickness: 1px; text-underline-offset: 2px; }
.gl-player:hover { color: var(--amber-hi); text-decoration-color: var(--amber); }
.gl-loc { color: inherit; cursor: pointer; text-decoration: underline dotted; text-decoration-color: rgba(240, 130, 12, 0.45); text-underline-offset: 2px; }
.gl-loc:hover { color: var(--amber); text-decoration-color: var(--amber); }
.gl-map {
  display: inline-flex; align-items: center; gap: 0.15rem; margin-left: 0.3rem;
  padding: 0 0.45rem; border: 1px solid var(--line); border-radius: var(--pill);
  color: var(--muted); font-size: 0.78rem; text-decoration: none; white-space: nowrap;
}
.gl-map:hover { color: var(--amber-hi); border-color: var(--line-amber); }
.gl-dim { color: var(--muted); }
.gl-sid { font-size: 0.8em; }
/* Item / vehicle / weapon class codes → compact mono chips. */
.gl-item { white-space: nowrap; }   /* raw look — styling is in the increment-21 block (no chip box) */
/* Category badge palettes: stable colour per tag (hash-picked), plus semantic
   green/red for login/activated vs logout/finished. */
.gl-tag-ok  { color: #57f287; }
.gl-tag-bad { color: #eb6a6a; }
.gl-tag-0 { color: #6cb2f7; }
.gl-tag-1 { color: #c792ea; }
.gl-tag-2 { color: var(--amber-hi); border-color: var(--line-amber); }
.gl-tag-3 { color: #4dd0c4; }
.gl-tag-4 { color: #e8a87c; }
.gl-tag-5 { color: #9fb2f7; }

/* Player roster table (admin: status · name · steam · squad · IP · Discord · logins) */
.roster-table td.rr-status { width: 1.8rem; text-align: center; }
.roster-table td.rr-name { font-weight: 600; color: var(--text); }
.roster-table td.dim { white-space: nowrap; }
.rr-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--faint); }
.rr-dot.on { background: var(--online); box-shadow: 0 0 7px var(--online); }
.rr-squad, .rr-discord { font-size: 0.85rem; }
.rr-online { color: var(--online); font-weight: 600; }
.roster-table td.rr-act { width: 2.2rem; text-align: center; }
.rr-admin-btn { border: 1px solid var(--line); background: var(--inset); color: var(--amber); cursor: pointer;
  width: 26px; height: 26px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; }
.rr-admin-btn:hover { background: var(--amber); color: var(--on-amber); border-color: var(--amber); }
.rr-admin-btn .ico { width: 15px; height: 15px; }
#pd-admin-actions { color: var(--amber); }

/* Chat: send-message box */
.chat-send { display: flex; flex-direction: column; gap: 0.7rem; }
.cs-head { display: flex; align-items: center; gap: 0.5rem; font-size: 0.82rem; text-transform: uppercase; letter-spacing: 0.18em; color: var(--text); }
.cs-head .ico { color: var(--amber); }
.cs-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.cs-inline { display: inline-flex; align-items: center; gap: 0.45rem; }

/* locked config fields (premium/bridge-gated, e.g. Discord→game relay) */
.cfg-field-locked { opacity: 0.5; }
.cfg-lock-note { display: flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: var(--amber);
  background: rgba(230,185,106,0.08); border: 1px solid var(--line-amber); border-radius: 8px; padding: 0.5rem 0.7rem; margin: 0.5rem 0; }
.cfg-lock-note .ico { width: 14px; height: 14px; }
/* Roster column widths. Everything except Name and Squad is fixed-shape content (an id, a figure,
   a timestamp), so those columns are told to take only what they need — `width: 1%` on a table cell
   collapses it to its content — and Name absorbs the slack. Without this the browser shared the
   width evenly and a 3-digit ID claimed as much room as the player name. */
/* Column WIDTHS live with the fixed-layout block further down (the table is `table-layout: fixed`,
   so a width set here on a <td> would do nothing anyway). This only keeps their content on one line. */
.roster-table td.c-uid, .roster-table td.c-steam, .roster-table td.num,
.roster-table td.c-ip, .roster-table td.c-login, .roster-table td.c-logout { white-space: nowrap; }
/* Hidden by CLASS, never :nth-child — column positions move whenever a column is added. */
@media (max-width: 1400px) {
  .roster-table th.c-logout, .roster-table td.c-logout { display: none; }
}
@media (max-width: 1250px) {
  .roster-table th.c-login, .roster-table td.c-login { display: none; }
}
@media (max-width: 1100px) {
  .roster-table th.c-fame, .roster-table td.c-fame,
  .roster-table th.c-playtime, .roster-table td.c-playtime { display: none; }
}
@media (max-width: 900px) {
  .roster-table th.c-ip, .roster-table td.c-ip,
  .roster-table th.c-money, .roster-table td.c-money,
  .roster-table th.c-gold, .roster-table td.c-gold { display: none; }
}
/* Squad block in the player detail */
.pd-squad-head { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.55rem; }
.pd-squad-name { font-weight: 700; font-size: 1.05rem; }
.pd-squad-meta { font-family: var(--mono); font-size: 0.8rem; color: var(--muted); }
.pd-members { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 0.4rem; margin-bottom: 0.9rem; }
.pd-member {
  display: flex; align-items: center; gap: 0.5rem; cursor: pointer; text-align: left;
  padding: 0.45rem 0.6rem; background: var(--inset); border: 1px solid var(--line);
  border-radius: var(--radius); color: var(--text); font-family: var(--ui);
}
.pd-member:hover { border-color: var(--amber); background: rgba(240, 130, 12, 0.14); }
.pd-m-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); flex: none; }
.pd-m-dot.on { background: var(--online); box-shadow: 0 0 7px var(--online); }
.pd-m-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-m-rank { margin-left: auto; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--amber); white-space: nowrap; }

.player-detail { background: var(--inset); border: 1px solid var(--line-amber); border-radius: var(--radius); padding: 0.9rem 1rem; }
.player-detail.hidden { display: none; }
/* Player detail hero: avatar + name/flag/status + Steam ID subline */
.pd-hero { display: flex; align-items: center; gap: 0.9rem; margin-bottom: 0.9rem; padding-right: 2.2rem; }
.pd-avatar { position: relative; width: 54px; height: 54px; border-radius: 50%; flex: none; display: flex; align-items: center; justify-content: center; overflow: hidden; }
.pd-avatar-ph { background: var(--inset); border: 1px solid var(--line-amber); color: var(--amber); font-weight: 700; font-size: 1.5rem; }
.pd-avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pd-hero-main { min-width: 0; display: flex; flex-direction: column; gap: 0.28rem; }
.pd-hero-top { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; }
.pd-hero-sub { display: flex; align-items: center; gap: 0.4rem; font-family: var(--mono); font-size: 0.8rem; color: var(--muted); }
.pd-hero-sub .ico { width: 1em; height: 1em; color: var(--amber); }
.pd-hero-top .rr-flag { width: 1.5em; height: 1.12em; margin: 0; }
.pd-name { font-size: 1.25rem; font-weight: 700; }
.pd-online { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.08em; padding: 0.15rem 0.5rem; border-radius: var(--pill); border: 1px solid var(--line); color: var(--muted); }
.pd-online.on { color: var(--online); border-color: var(--online); }
.pd-banned { font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--alarm); border: 1px solid var(--alarm); padding: 0.15rem 0.5rem; border-radius: var(--pill); }
.pd-id { display: flex; flex-wrap: wrap; gap: 0.35rem 1.4rem; margin-bottom: 0.8rem; padding-bottom: 0.7rem; border-bottom: 1px solid var(--line); }
/* CFTools-style player summary card */
.pd-card { background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius); padding: 1rem 1.1rem; margin: 0.5rem 0 1.1rem; }
.pd-id-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 0.8rem 1.5rem; }
.pd-idc { display: flex; flex-direction: column; gap: 0.22rem; min-width: 0; }
.pd-il { display: flex; align-items: center; gap: 0.35rem; font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: 600; }
.pd-il .ico { width: 1.5em; height: 1.5em; color: var(--amber); flex: none; }
.pd-iv { font-size: 0.9rem; color: var(--text); overflow-wrap: anywhere; display: flex; align-items: center; gap: 0.3rem; }
.pd-iv.mono { font-family: var(--mono); font-size: 0.85rem; }
/* Position → compact map link (mono, fits its cell; full value in the tooltip). */
.pd-maplink {
  font-family: var(--mono); font-size: 0.82rem; font-variant-numeric: tabular-nums;
  color: var(--text); text-decoration: none; border-bottom: 1px dashed var(--line-amber); white-space: nowrap;
}
.pd-maplink:hover { color: var(--amber-hi); }
.pd-quick { display: flex; flex-wrap: wrap; gap: 0.55rem; margin: 0 0 0.9rem; }
.pd-q { flex: 1 1 88px; display: flex; flex-direction: column; align-items: center; gap: 0.18rem; padding: 0.55rem 0.4rem; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); }
.pd-qv { font-family: var(--mono); font-size: 1.05rem; font-weight: 700; color: var(--amber-hi); }
.pd-qk { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.pd-card .pd-ban { margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--line); }
.pd-id span { font-size: 0.86rem; color: var(--text); font-family: var(--mono); }
.pd-id i { font-style: normal; color: var(--muted); margin-right: 0.3rem; text-transform: uppercase; font-size: 0.66rem; letter-spacing: 0.04em; }
/* Stat cards (icon + value/label), uniform like the public My Stats. */
.pd-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 0.5rem; margin-bottom: 1.1rem; }
.pd-stat { display: flex; align-items: center; gap: 0.55rem; padding: 0.55rem 0.7rem; background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius); }
.pd-stat .ico { color: var(--amber); font-size: 1.3rem; flex: none; }
.pd-stat-t { display: flex; flex-direction: column; line-height: 1.1; min-width: 0; }
.pd-stat-v { font-family: var(--mono); font-size: 1.05rem; color: var(--text); overflow-wrap: anywhere; min-width: 0; }
.pd-stat-k { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
/* Player-detail tabs + close */
.pd-close { margin-left: auto; cursor: pointer; background: transparent; border: 1px solid var(--line); border-radius: var(--radius); color: var(--muted); width: 28px; height: 28px; font-size: 0.9rem; line-height: 1; }
.pd-close:hover { background: transparent; color: var(--alarm); border-color: var(--alarm); }
/* Detail tabs: pill buttons (Stats · Skills · Squad · Bank) — clearer active
   state than the old underline-only look. */
.pd-tabnav { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 1rem 0 0.9rem; }
.pd-tab {
  display: inline-flex; align-items: center; gap: 0.45rem; cursor: pointer;
  background: var(--inset); border: 1px solid var(--line); border-radius: var(--pill);
  color: var(--muted); font-family: var(--ui); font-weight: 600; font-size: 0.85rem;
  padding: 0.45rem 0.95rem;
}
.pd-tab .ico { font-size: 1rem; }
.pd-tab:hover { color: var(--text); background: var(--hover-bg); border-color: var(--line-amber); }
.pd-tab.active { color: var(--amber-hi); border-color: var(--line-amber); background: rgba(255, 154, 46, 0.09); }
.pd-pane[hidden] { display: none; }
/* Skills & attributes (grouped by attribute, with the attribute value) */
.pd-sec-title { display: flex; align-items: center; gap: 0.4rem; margin: 0.2rem 0 0.7rem; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--amber); font-weight: 700; }
.pd-sec-title .ico { color: var(--amber); }
.pd-skills { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 0.8rem; margin-bottom: 0.9rem; }
.pd-sg { display: flex; flex-direction: column; gap: 0.4rem; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.8rem 0.85rem; }
.pd-sg-head { display: flex; align-items: center; gap: 0.4rem; padding-bottom: 0.3rem; border-bottom: 1px solid var(--line-amber); }
.pd-sg-head .ico { color: var(--amber); }
.pd-sg-head b { color: var(--amber); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; }
.pd-attr { margin-left: auto; font-family: var(--mono); color: var(--amber-hi); font-size: 0.95rem; }
.pd-sk { display: grid; grid-template-columns: 1fr auto; gap: 0.1rem 0.5rem; font-size: 0.82rem; }
.pd-sk-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pd-sk-tier { font-size: 0.68rem; text-transform: uppercase; color: var(--muted); letter-spacing: 0.04em; }
.pd-sk-bar { grid-column: 1 / -1; height: 4px; background: var(--inset); border: 1px solid var(--line); border-radius: 3px; overflow: hidden; }
.pd-sk-bar > span { display: block; height: 100%; background: var(--amber); }
.pd-sk.sk-l0 .pd-sk-bar > span { background: var(--faint); }
.pd-sk.sk-l1 .pd-sk-bar > span { background: var(--standby); }
.pd-sk.sk-l2 .pd-sk-bar > span { background: #b8bcc2; }
.pd-sk.sk-l3 .pd-sk-bar > span { background: var(--amber); }
.pd-sk.sk-l4 .pd-sk-bar > span { background: var(--amber-hi); }
.pd-ban-note { font-size: 0.82rem; color: var(--standby); }
/* Admin action bar on the player card */
.pd-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--line); }
.pd-actions .ico { font-size: 0.95rem; }
.pd-note-in { display: block; width: 100%; margin-top: 0.6rem; min-height: 68px; background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius); color: var(--text); font-family: var(--ui); font-size: 0.88rem; line-height: 1.4; padding: 0.55rem 0.7rem; box-sizing: border-box; resize: vertical; }
.pd-note-in:focus { outline: none; border-color: var(--amber); }
.pd-action-msg { display: inline-block; margin-top: 0.5rem; font-size: 0.85rem; color: var(--standby); }
#ban-msg { font-size: 0.85rem; color: var(--standby); }

/* Player Intelligence / risk */
.bad { color: #e39a9a; }
.pd-stat-v.bad { color: #e39a9a; }
.pd-risk { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase; padding: 0.15rem 0.5rem; border-radius: 999px; border: 1px solid var(--line); }
.pd-risk.high  { color: #f0b2b2; border-color: rgba(224,80,80,0.6);  background: rgba(224,80,80,0.12); }
.pd-risk.watch { color: #e6c789; border-color: rgba(230,166,26,0.55); background: rgba(230,166,26,0.12); }
.pd-risk.clean { color: #a4d6ad; border-color: rgba(59,165,93,0.5);  background: rgba(59,165,93,0.12); }
.pd-risk-head { display: flex; align-items: center; gap: 0.8rem; padding: 0.7rem 0.9rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--inset); }
.pd-risk-head.high  { border-color: rgba(224,80,80,0.5); }
.pd-risk-head.watch { border-color: rgba(230,166,26,0.45); }
.pd-risk-badge { font-weight: 700; font-size: 0.9rem; white-space: nowrap; }
.pd-risk-bar { flex: 1; height: 8px; background: var(--bg); border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.pd-risk-fill { height: 100%; background: linear-gradient(90deg, var(--standby), var(--amber-hi)); }
.pd-risk-head.high .pd-risk-fill  { background: linear-gradient(90deg, #d98b8b, #e05050); }
.pd-risk-head.watch .pd-risk-fill { background: linear-gradient(90deg, #d9bd7a, #e6a61a); }
.pd-risk-head.clean .pd-risk-fill { background: linear-gradient(90deg, #7ec48a, #3ba55d); }
.pd-risk-score { font-family: var(--mono); font-size: 1.1rem; font-weight: 700; white-space: nowrap; }
.pd-risk-score span { font-size: 0.72rem; color: var(--muted); }
.pd-flags { margin: 0.3rem 0 0.6rem; padding-left: 1.1rem; font-size: 0.85rem; color: var(--standby); }
.pd-flags li { margin: 0.15rem 0; }
/* Intel tab — readable label→value rows (values wrap fully, no truncation) */
.pi-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 1rem; margin-bottom: 1.1rem; }
.pi-rows { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--panel-2); }
.pi-row { display: grid; grid-template-columns: minmax(104px, 36%) 1fr; gap: 0.3rem 1rem; padding: 0.5rem 0.8rem; border-top: 1px solid var(--line); align-items: baseline; }
.pi-row:first-child { border-top: none; }
.pi-k { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); font-weight: 600; }
.pi-v { color: var(--text); font-size: 0.88rem; overflow-wrap: anywhere; display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; }
.pi-row.bad .pi-v { color: #e39a9a; }
.pi-v .rr-flag { margin: 0; }
/* Intel-tab section headings get a bit more breathing room */
.pd-pane[data-ppane="intel"] .pd-sec-title { margin-top: 1.5rem; margin-bottom: 1rem; }
.pd-intel-checked { align-self: center; font-size: 0.76rem; color: var(--muted); }
/* Risk marker shown after the player name — icon coloured by level */
.rr-risk { display: inline-flex; vertical-align: -0.15em; }
.rr-risk .ico { width: 0.95em; height: 0.95em; }
.rr-risk.high { color: #e05050; }
.rr-risk.watch { color: #e6a61a; }
.rr-risk.clean { color: #57b87f; opacity: 0.85; }
.rr-risk.watch .ico, .rr-risk.clean .ico { stroke-width: 1.9; }
/* Country flag before a player name (dashboard + roster) — bundled SVG, real flag on every OS */
img.rr-flag { width: 1.15em; height: 0.86em; margin-right: 0.35rem; vertical-align: -0.08em; border-radius: 1px; box-shadow: 0 0 0 1px rgba(0,0,0,0.25); object-fit: cover; }
/* "unknown country" placeholder — identical footprint to a flag so rows stay aligned */
.rr-flag-unknown { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; width: 1.15em; height: 0.86em; margin-right: 0.35rem; vertical-align: -0.08em; border-radius: 1px; background: var(--inset); box-shadow: 0 0 0 1px rgba(0,0,0,0.25); color: var(--muted); overflow: hidden; }
.rr-flag-unknown i { font-size: 0.58rem; font-style: normal; font-weight: 700; line-height: 1; }
.pd-hero-top .rr-flag-unknown { width: 1.5em; height: 1.12em; font-size: 0.8em; }

/* Player Intelligence dashboard panel (above the online-players box) */
/* Dashboard panel — clickable stat tiles (each filters the Players table) */
.intel-tiles { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; }
.intel-tile { display: inline-flex; align-items: center; gap: 0.45rem; padding: 0.55rem 0.85rem; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); color: var(--text); cursor: pointer; font: inherit; transition: border-color 0.12s, background 0.12s; }
.intel-tile:hover { border-color: var(--amber); background: rgba(240, 130, 12, 0.14); }
.intel-tile .ico { width: 1.15em; height: 1.15em; color: var(--muted); }
.intel-tile .v { font-size: 1.2rem; font-weight: 700; font-family: var(--mono); color: var(--text); }
.intel-tile .k { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
.intel-tile.high .ico, .intel-tile.high .v { color: #e05050; }
.intel-tile.watch .ico, .intel-tile.watch .v { color: #e6a61a; }
.intel-tile.wl .ico { color: var(--amber); }
.intel-tile.bad .ico { color: #e05050; }
/* panel sub-sections: top countries + flagged */
.intel-sub-block { margin-top: 0.9rem; }
.intel-sub-h { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); font-weight: 700; margin-bottom: 0.45rem; }
.intel-countries { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.intel-cc { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.24rem 0.55rem 0.24rem 0.4rem; background: var(--inset); border: 1px solid var(--line); border-radius: var(--pill); color: var(--text); cursor: pointer; font: inherit; }
.intel-cc:hover { border-color: var(--amber); background: rgba(240, 130, 12, 0.14); }
.intel-cc .rr-flag { margin: 0; }
.intel-cc-n { font-family: var(--mono); font-size: 0.82rem; font-weight: 700; color: var(--text); }
/* flagged players — name button + a "mark reviewed" ✓ */
.intel-flagged { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.intel-fp { display: inline-flex; align-items: stretch; background: var(--inset); border: 1px solid var(--line); border-radius: var(--pill); overflow: hidden; max-width: 17rem; }
.intel-fp:hover { border-color: var(--line-amber); }
.intel-fp-open { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.3rem 0.55rem; background: none; border: none; color: var(--text); cursor: pointer; font: inherit; font-size: 0.84rem; min-width: 0; }
.intel-fp-open:hover { background: rgba(240, 130, 12, 0.14); }
.intel-fp .rr-risk .ico { width: 0.9em; height: 0.9em; }
.intel-fp-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.intel-fp-on { width: 7px; height: 7px; border-radius: 50%; background: var(--online); flex: none; margin-left: 0.1rem; }
.intel-fp-ok { display: inline-flex; align-items: center; justify-content: center; padding: 0 0.45rem; background: none; border: none; border-left: 1px solid var(--line); color: var(--muted); cursor: pointer; }
.intel-fp-ok:hover { background: rgba(87,184,127,0.16); color: #57b87f; }
.intel-fp-ok .ico { width: 0.95em; height: 0.95em; }
/* active dashboard filter chip in the roster bar */
.roster-intel-chip:empty { display: none; }
.roster-fchip { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.2rem 0.25rem 0.2rem 0.5rem; background: rgba(240,130,12,0.12); border: 1px solid var(--line-amber); border-radius: var(--pill); font-size: 0.8rem; color: var(--amber-hi); }
.roster-fchip .rr-flag { margin: 0 0.15rem 0 0; }
.roster-fchip-x { background: none; border: none; color: inherit; cursor: pointer; font-size: 1.05rem; line-height: 1; padding: 0 0.15rem; }
.roster-fchip-x:hover { color: var(--text); }

.bans code { font-family: var(--mono); color: var(--amber); }
#bans-table { width: 100%; border-collapse: collapse; }
#bans-table th, #bans-table td { text-align: left; padding: 0.45rem 0.55rem; border-bottom: 1px solid var(--line); font-size: 0.9rem; }
#bans-table th { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
#bans-table .mono { font-family: var(--mono); color: var(--muted); }
#bans-table .muted { color: var(--muted); }

/* ── Roster pagination ────────────────────────────────────────────────────── */
.roster-pager { display: flex; align-items: center; justify-content: center; gap: 0.9rem; margin-top: 0.9rem; }
.roster-pager.hidden { display: none; }
.roster-pager button[disabled] { opacity: 0.4; cursor: default; }
.rr-uid, .pd-uid { margin-left: .45rem; color: var(--muted); font-size: .78rem; opacity: .85; }
.roster-pager-info { flex-basis: 100%; text-align: center; font-family: var(--mono); font-size: 0.8rem; color: var(--muted); }

/* ── Clickable player rows / online list ──────────────────────────────────── */
.clickable { cursor: pointer; transition: color 0.12s, background 0.12s; }
#players-list li.clickable:hover { color: var(--amber-hi); }
#dc-linked-tbody tr.clickable:hover { background: rgba(240, 130, 12, 0.06); }
.players-hint { color: var(--muted); font-size: 0.82rem; margin: 0 0 0.6rem; }

/* ── Field Console link (back to public site) ─────────────────────────────── */
.nav-actions .navlink, .header-actions .navlink {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.5rem 1rem; border: 1px solid var(--line-amber); border-radius: var(--radius);
  background: var(--panel-2); color: var(--amber-hi);
  font-family: var(--ui); font-weight: 600; font-size: 0.82rem; letter-spacing: 0.05em; text-transform: uppercase;
}
.nav-actions .navlink:hover, .header-actions .navlink:hover { background: var(--panel); border-color: var(--amber); }

/* ── Player detail: bank cards ────────────────────────────────────────────── */
.pd-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: 0.7rem; margin-bottom: 0.9rem; }
.pd-cards .pd-card { display: flex; gap: 0.8rem; padding: 0.7rem 0.8rem; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); margin: 0; }
.pd-card-img { width: 80px; height: 52px; flex: none; object-fit: contain; align-self: center; }
.pd-card-body { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.pd-card-type { font-weight: 700; color: var(--amber); text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.82rem; }
.pd-card-rows { display: flex; flex-wrap: wrap; gap: 0.1rem 1rem; font-size: 0.8rem; color: var(--muted); }
.pd-card-rows b { color: var(--text); font-family: var(--mono); margin-left: 0.2rem; }

/* ── Dashboard top menu: lighter, Field-Console-like nav (ghost buttons) ───── */
#dashboard-screen .nav-actions .secondary,
#dashboard-screen .nav-actions .navlink {
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
}
#dashboard-screen .nav-actions .secondary:hover,
#dashboard-screen .nav-actions .navlink:hover {
  color: var(--amber-hi);
  border-color: var(--line-amber);
  background: var(--panel-2);
}
#dashboard-screen .nav-actions #logout-btn:hover { color: var(--alarm); border-color: rgba(229,68,63,0.4); background: transparent; }

/* ── App footer + App status modal ─────────────────────────────────────────── */
.foot-link { background: none; border: 0; padding: 0; color: var(--amber); cursor: pointer; font: inherit; }
.foot-link:hover { background: none; border: 0; color: var(--amber-hi); text-decoration: underline; }
.amodal { position: fixed; inset: 0; z-index: 100; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,0.6); padding: 1rem; }
.amodal.hidden { display: none; }
.amodal-box { position: relative; background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius); padding: 1.4rem 1.6rem; max-width: 440px; width: 100%; max-height: 85vh; overflow: auto; }
.amodal.wide .amodal-box { max-width: 1040px; }
.amodal-close { position: absolute; top: 0.7rem; right: 0.7rem; cursor: pointer; background: transparent; border: 1px solid var(--line); border-radius: var(--radius); color: var(--muted); width: 28px; height: 28px; }
.amodal-close:hover { background: transparent; color: var(--alarm); border-color: var(--alarm); }
.amodal-box h2 { margin: 0 0 0.4rem; font-size: 1.1rem; }
.appstat { display: flex; flex-direction: column; margin-top: 0.6rem; }
.appstat-row { display: flex; align-items: center; gap: 0.6rem; padding: 0.55rem 0.1rem; border-bottom: 1px solid var(--line); }
.appstat-row:last-child { border-bottom: 0; }
.appstat-k { color: var(--muted); font-size: 0.85rem; }
.appstat-v { color: var(--text); font-family: var(--mono); margin-left: auto; text-align: right; }

/* ── Premium ──────────────────────────────────────────────────────────────── */
.prem-body { margin: 1rem 1.5rem 2rem; }
/* Notes/messages inside the premium column already sit in the padded body — drop
   the global horizontal margin (was double-indenting them) and give real spacing. */
.prem-body .settings-note, .prem-body .settings-message { margin-left: 0; margin-right: 0; }
.prem-form .settings-note { margin: 0.4rem 0 1.1rem; }
.prem-form .settings-message { margin: 0 0 0.6rem; }
.prem-hero { display: flex; align-items: center; gap: 1.4rem; flex-wrap: wrap; background: linear-gradient(135deg, rgba(240,130,12,0.14), rgba(240,130,12,0.02)); border: 1px solid var(--line-amber); border-radius: var(--radius); padding: 1.3rem 1.5rem; margin: 0 0 1.2rem; }
.prem-hero-txt { flex: 1 1 320px; min-width: 0; }
.prem-h { margin: 0 0 0.4rem; font-size: 1.35rem; color: var(--amber-hi); letter-spacing: 0.01em; }
.prem-lead { margin: 0; color: var(--text); line-height: 1.55; font-size: 0.92rem; }
.prem-lead code { font-family: var(--mono); color: var(--amber); }
.prem-price { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 0.1rem; padding: 0.6rem 1.1rem; border: 1px solid var(--line-amber); border-radius: var(--radius); background: var(--panel); }
.prem-price-row { display: flex; align-items: baseline; gap: 0.3rem; }
.prem-price-amt { font-size: 2.1rem; font-weight: 800; color: var(--amber-hi); font-family: var(--mono); }
.prem-price-per { font-size: 0.85rem; color: var(--muted); }
.prem-price-extra { font-size: 0.72rem; color: var(--muted); white-space: nowrap; }
.prem-features { background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.1rem 1.3rem; margin-bottom: 1.2rem; }
.prem-list { list-style: none; margin: 0.3rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.prem-list li { position: relative; padding-left: 1.5rem; font-size: 0.9rem; color: var(--text); line-height: 1.45; }
.prem-list li::before { content: '✓'; position: absolute; left: 0; color: var(--online); font-weight: 700; }
.prem-list li.prem-soon { color: var(--muted); }
.prem-list li.prem-soon::before { content: '+'; color: var(--amber); }
.prem-note-min { margin: 0.9rem 0 0; font-size: 0.82rem; color: var(--muted); line-height: 1.5; }
.prem-status { display: flex; align-items: center; gap: 0.85rem; background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 0.85rem 1.1rem; margin-bottom: 1.4rem; }
.prem-status-dot { width: 12px; height: 12px; border-radius: 50%; flex: none; background: var(--faint); }
.prem-status-dot[data-state="active"] { background: var(--online); box-shadow: 0 0 8px var(--online); }
.prem-status-dot[data-state="inactive"] { background: var(--standby); }
.prem-status-dot[data-state="error"] { background: var(--alarm); }
.prem-status-dot[data-state="unknown"] { background: var(--faint); }
.prem-status-txt { display: flex; flex-direction: column; gap: 0.12rem; min-width: 0; flex: 1 1 auto; }
.prem-status-line { font-weight: 700; font-size: 0.95rem; color: var(--text); }
.prem-status-sub { font-size: 0.8rem; color: var(--muted); }
.prem-manage { flex: none; display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.9rem; border: 1px solid var(--line-amber); border-radius: var(--radius); background: var(--panel-2); color: var(--amber-hi); font-weight: 600; font-size: 0.82rem; }
.prem-manage:hover { background: var(--panel); border-color: var(--amber); text-decoration: none; }
.prem-manage .ico { width: 1em; height: 1em; }
.prem-form { background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.1rem 1.3rem 1.3rem; }
.prem-field { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 0.9rem; }
.prem-field label { font-size: 0.8rem; font-weight: 600; color: var(--text); }
.prem-field input { width: 100%; max-width: 620px; box-sizing: border-box; padding: 0.55rem 0.7rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--inset); color: var(--text); font-family: var(--mono); font-size: 0.88rem; }
.prem-field input:focus { outline: none; border-color: var(--amber); box-shadow: var(--focus-ring); }
/* The shared .subhead carries a 1.5rem side margin; inside the premium cards that
   double-indents it — reset so it lines up with the card content. */
.prem-features .subhead, .prem-form .subhead { margin: 0 0 0.9rem; }
/* Kill the browser autofill's light background/text on the dark theme. */
.prem-field input:-webkit-autofill,
.prem-field input:-webkit-autofill:hover,
.prem-field input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 1000px var(--inset) inset;
  box-shadow: 0 0 0 1000px var(--inset) inset;
  caret-color: var(--text);
}
.prem-form-actions { display: flex; gap: 0.6rem; margin-top: 1.1rem; flex-wrap: wrap; }

/* ── Live Map ────────────────────────────────────────────────────────────── */
.map-updated { color: var(--muted); font-size: 0.82rem; align-self: center; }
.map-wrap {
  position: relative; display: flex; margin: 1.2rem;
  border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden;
}

/* Side panel — layer toggles, options + searchable entity lists (CFTools-style). */
.map-side {
  width: 280px; flex: 0 0 280px; display: flex; flex-direction: column;
  height: 72vh; min-height: 380px; background: var(--panel); border-right: 1px solid var(--line);
  overflow-y: auto;   /* whole panel (filters + lists) scrolls as one */
}
/* Player filter — same shape as the search row above it so the two read as one control block.
   A type-to-search combobox, not a <select>: a full server has hundreds of names. */
.map-owner-row { position: relative; display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--line); }
.map-owner-row .ico { width: 15px; height: 15px; color: var(--muted); flex: none; }
.map-owner-row input {
  flex: 1; min-width: 0; padding: 0.3rem 0.4rem; font-family: var(--ui); font-size: 0.8rem;
  background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius); color: var(--text);
}
.map-owner-row input:focus { outline: none; border-color: var(--amber); }
.map-owner-row #map-owner-clear[hidden] { display: none; }
.map-owner-sug {
  position: absolute; z-index: 20; left: 0.75rem; right: 0.75rem; top: 100%;
  max-height: 260px; overflow-y: auto; display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line-amber, var(--line)); border-radius: var(--radius);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
}
.map-owner-sug[hidden] { display: none; }
/* Beats the global button skin, which would paint each suggestion solid amber. */
.map-owner-sug .mos-item,
.map-owner-sug .mos-item:hover {
  display: block; width: 100%; text-align: left; padding: 0.35rem 0.6rem; border: 0; border-radius: 0;
  background: none; color: var(--text); font: inherit; font-size: 0.8rem; letter-spacing: 0; transform: none;
}
.map-owner-sug .mos-item:hover, .map-owner-sug .mos-item.hi { background: var(--panel-2); color: var(--amber-hi); }

.map-search-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--line); }
.map-search-row .ico { width: 15px; height: 15px; color: var(--muted); flex: none; }
.map-search-row input {
  flex: 1; min-width: 0; background: none; border: none; color: var(--text);
  font-family: var(--ui); font-size: 0.85rem; padding: 0.15rem 0;
}
.map-search-row input:focus { outline: none; }

/* Collapsible "Layers & filters" dropdown — keeps the tall toggle list from crowding
   out the entity lists below. */
.map-filters { border-bottom: 1px solid var(--line); }
.map-filters-head {
  display: flex; align-items: center; gap: 0.5rem; width: 100%;
  padding: 0.6rem 0.75rem; background: none; border: none; cursor: pointer;
  color: var(--muted); font-family: var(--ui); font-weight: 700; font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: 0.08em;
}
.map-filters-head:hover { color: var(--text); background: var(--hover-bg); border-color: transparent; }
.map-filters-head .ico { width: 15px; height: 15px; flex: none; color: var(--amber); }
.mf-chev { margin-left: auto; font-size: 0.85rem; transition: transform 0.15s; }
.map-filters.collapsed .mf-chev { transform: rotate(-90deg); }
.map-filters.collapsed .map-layers { display: none; }

/* Layer cards: a header (badge + name + count, toggles visibility) + segmented sub-filter. */
.map-layers { display: flex; flex-direction: column; gap: 0.4rem; padding: 0.6rem; }
.mlyr { border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; background: var(--panel-2); }
.map-layer {
  display: flex; align-items: center; gap: 0.55rem; width: 100%; padding: 0.5rem 0.6rem;
  background: none; border: none; color: var(--text);
  font-family: var(--ui); font-weight: 600; font-size: 0.88rem; cursor: pointer; text-align: left;
}
.ml-badge {
  display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  border-radius: var(--radius-md); flex: none; border: 1px solid rgba(0, 0, 0, 0.35);
}
.ml-badge .ico { width: 14px; height: 14px; color: var(--bg); }
.ml-badge.mk-player { background: var(--c-player); }
.ml-badge.mk-base { background: var(--c-base); }
.ml-badge.mk-vehicle { background: var(--c-vehicle); }
.ml-badge.mk-chest { background: var(--c-chest); }
.ml-badge.mk-storage { background: var(--c-storage); }
.ml-badge.mk-trap { background: var(--c-trap); }
.ml-badge.mk-turret { background: var(--c-turret); }
.map-layer .ml-name { flex: 1; }
.map-layer:hover { background: rgba(255, 255, 255, 0.06); color: var(--text); }
.map-count {
  min-width: 1.6em; padding: 0.05rem 0.45em; text-align: center; border-radius: var(--pill);
  background: rgba(0, 0, 0, 0.3); color: var(--muted); font-size: 0.75rem; font-variant-numeric: tabular-nums;
}
.map-layer.active .map-count { color: var(--text); }
/* Hidden layer: dim the group, grey the badge, strike the name. */
.mlyr:has(.map-layer:not(.active)) { opacity: 0.55; }
.map-layer:not(.active) .ml-badge { filter: grayscale(1); }
.map-layer:not(.active) .ml-name { text-decoration: line-through; text-decoration-color: var(--muted); }

.map-opts { display: flex; align-items: center; justify-content: space-between; flex-wrap: nowrap;
  gap: 0.5rem; padding: 0.4rem 0.7rem 0.6rem; border-bottom: 1px solid var(--line); }
.map-toggle { display: inline-flex; align-items: center; gap: 0.3rem; color: var(--muted);
  font-size: 0.78rem; line-height: 1; white-space: nowrap; flex: 0 0 auto; cursor: pointer; }
.map-toggle input { accent-color: var(--amber); width: 14px; height: 14px; margin: 0; flex: none; }
.map-zoom-btn {
  display: inline-flex; margin-left: auto; padding: 0.3rem; background: var(--panel-2); border: 1px solid var(--line);
  color: var(--muted); border-radius: var(--radius-md); cursor: pointer;
}
.map-zoom-btn:hover { color: var(--amber-hi); border-color: var(--line-amber); background: var(--panel-2); }
.map-zoom-btn .ico { width: 15px; height: 15px; }

.map-lists { flex: 0 0 auto; padding: 0 0 0.6rem; }
.ml-sec { margin-bottom: 0.3rem; }
/* Prominent, flush sticky header — full width, bottom rule, no top gap. */
.ml-sec-h {
  display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.6rem; position: sticky; top: 0; z-index: 2;
  background: var(--panel); border-bottom: 1px solid var(--line);
  color: var(--text); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
}
.ml-sec-h .ico { width: 13px; height: 13px; color: var(--amber-hi); }
/* Section count — same pill as .map-count so all counters in the panel match. */
.ml-sec-n {
  margin-left: auto; min-width: 1.6em; padding: 0.05rem 0.45em; text-align: center;
  border-radius: var(--pill); background: rgba(0, 0, 0, 0.3); color: var(--muted);
  font-size: 0.75rem; font-variant-numeric: tabular-nums;
}
.ml-row {
  display: flex; align-items: center; gap: 0.5rem; width: 100%; padding: 0.4rem 0.6rem;
  background: none; border: none; cursor: pointer; text-align: left; color: var(--text);
}
.ml-row:hover { background: rgba(255, 255, 255, 0.06); color: var(--text); }
.ml-row .ml-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; border: 1px solid rgba(0, 0, 0, 0.5); }
.mlr-main { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.mlr-name { font-size: 0.82rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mlr-meta { font-size: 0.7rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mlr-sec { font-size: 0.72rem; color: var(--muted); font-variant-numeric: tabular-nums; padding: 0 0.35em; border: 1px solid var(--line); border-radius: var(--radius); align-self: center; }
.ml-empty { padding: 1rem; text-align: center; color: var(--muted); font-size: 0.85rem; }
.ml-dot.mk-player  { background: var(--c-player); }
.ml-dot.mk-base    { background: var(--c-base); }
.ml-dot.mk-vehicle { background: var(--c-vehicle); }
.ml-dot.mk-chest   { background: var(--c-chest); }
.ml-dot.mk-storage { background: var(--c-storage); }
.ml-dot.mk-trap    { background: var(--c-trap); }
.ml-dot.mk-turret  { background: var(--c-turret); }

/* Sub-filter = a compact dropdown at the bottom of each layer card (scales to any
   number of options, stays readable in the narrow panel — unlike a row of chips). */
.map-subf { padding: 0.4rem 0.5rem 0.5rem; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 0.35rem; }
.sf-select, .sf-type-select {
  width: 100%; padding: 0.4rem 1.6rem 0.4rem 0.55rem; background: var(--panel-2); border: 1px solid var(--line);
  color: var(--text); font-family: var(--ui); font-weight: 600; font-size: 0.78rem; border-radius: var(--radius-md); cursor: pointer;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23ff9a2e' stroke-width='2.5'><path d='M6 9l6 6 6-6'/></svg>");
  background-repeat: no-repeat; background-position: right 0.55rem center;
}
.sf-select:hover, .sf-select:focus, .sf-type-select:hover, .sf-type-select:focus { border-color: var(--line-amber); outline: none; }
.sf-select option, .sf-type-select option { background: var(--panel); color: var(--text); }
.map-mk.mk-player:not(.off) .mk-dot { box-shadow: 0 0 0 2px rgba(53, 208, 127, 0.4), 0 1px 3px rgba(0, 0, 0, 0.6); }
.map-mk.mk-player.off .mk-dot { background: var(--offline); }
/* Online but dead (awaiting respawn): red ring so the state reads at a glance. */
.map-mk.mk-player.dead:not(.off) .mk-dot { background: var(--alarm); box-shadow: 0 0 0 2px rgba(237, 66, 69, 0.45), 0 1px 3px rgba(0, 0, 0, 0.6); }
.map-mk.mk-player.off { opacity: 0.72; }
.ml-row.off .ml-dot { background: var(--offline); }
.ml-row.off .mlr-name { color: var(--muted); }

/* Sector grid — inside the canvas so it pans/zooms with the map. */
.map-sectors { position: absolute; inset: 0; pointer-events: none; z-index: 1; }
.map-sectors.hidden { display: none; }
.sec-line { position: absolute; background: rgba(255, 200, 120, 0.20); }
.sec-v { top: 0; bottom: 0; width: 1px; }
.sec-h { left: 0; right: 0; height: 1px; }
.sec-lab {
  position: absolute; transform: scale(var(--mz, 1)); transform-origin: top left;
  padding: 3px 6px; color: #fff; font-family: var(--ui); font-weight: 800; font-size: 22px;
  letter-spacing: 0.04em; white-space: nowrap;
  text-shadow: 0 0 3px #000, 1px 1px 2px #000, -1px 1px 2px #000;
}

.map-viewport {
  position: relative; flex: 1; min-width: 0; height: 72vh; min-height: 380px; overflow: hidden; cursor: grab;
  background: #070a10; touch-action: none; user-select: none;
}
@media (max-width: 760px) {
  .map-wrap { flex-direction: column; margin: 0.75rem; }
  .map-side { width: auto; flex: none; height: auto; max-height: 46vh; border-right: none; border-bottom: 1px solid var(--line); }
  .map-viewport { height: 58vh; }
}
.map-viewport.dragging { cursor: grabbing; }
/* On-screen zoom buttons (touch has no wheel). */
.map-zoom { position: absolute; right: 10px; bottom: 10px; z-index: 15; display: flex; flex-direction: column; gap: 5px; }
.map-zoom-b {
  width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
  font-size: 1.4rem; line-height: 1; background: var(--panel); border: 1px solid var(--line-amber);
  color: var(--amber-hi); border-radius: var(--radius-md); cursor: pointer; user-select: none; padding: 0;
}
.map-zoom-b:hover { background: var(--panel-2); }
.map-zoom-b:active { background: var(--amber); color: var(--on-amber); }
/* No will-change/GPU layer here: it would cache one rasterisation and upscale it,
   blurring the markers/labels (and the map) on zoom. Without it the browser
   re-rasterises at the current zoom, keeping icons + text crisp. */
.map-canvas { position: absolute; top: 0; left: 0; width: 100%; transform-origin: 0 0; }
.map-img { display: block; width: 100%; height: auto; user-select: none; -webkit-user-drag: none; }
.map-img.map-img-missing {
  min-height: 640px;
  background:
    repeating-linear-gradient(0deg, rgba(240,130,12,0.05) 0 1px, transparent 1px 64px),
    repeating-linear-gradient(90deg, rgba(240,130,12,0.05) 0 1px, transparent 1px 64px), #0a1018;
}
.map-markers { position: absolute; inset: 0; }

.map-area {
  position: absolute; border: 1px solid; border-radius: 3px;
}
.map-area.area-player { border-color: rgba(255, 154, 46, 0.55); background: rgba(240, 130, 12, 0.10); }
.map-area.area-npc { border-color: rgba(120, 170, 255, 0.45); background: rgba(90, 140, 240, 0.08); }

/* The dot is anchored exactly on the point; the label floats below (out of flow) so
   it never shifts the dot, and ::before widens the click target. */
/* Zero-size anchor placed EXACTLY at the point (its top-left = X%,Y%); the dot and
   label position + counter-scale themselves against that anchor. No box-model math. */
.map-mk {
  position: absolute; width: 0; height: 0; padding: 0; background: none; border: none; cursor: pointer; z-index: 2;
}
.map-mk .mk-dot {
  position: absolute; left: 0; top: 0; transform: translate(-50%, -50%) scale(var(--mz, 1));
  box-sizing: border-box; display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  border: 1.5px solid rgba(0, 0, 0, 0.55); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
.map-mk .mk-dot::before { content: ''; position: absolute; inset: -8px; border-radius: 50%; }
.map-mk .mk-dot .ico { width: 12px; height: 12px; color: var(--bg); }
.map-mk .mk-label {
  /* The vertical offset is counter-scaled too (calc · --mz), so the gap between the
     dot and the name stays constant on screen at every zoom (was growing with zoom). */
  display: none; position: absolute; left: 0; top: 0;
  transform: translate(-50%, calc(13px * var(--mz, 1))) scale(var(--mz, 1)); transform-origin: top center;
  max-width: 130px; padding: 1px 5px; border-radius: var(--radius);
  background: rgba(8, 10, 14, 0.85); color: var(--text); font-size: 11px; font-weight: 600;
  line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none;
}
.map-markers.labels-on .mk-label, .map-mk:hover .mk-label { display: block; }
.map-mk:hover { z-index: 5; }
.map-mk:hover .mk-dot { outline: 2px solid var(--amber-hi); }

.mk-player .mk-dot { background: var(--c-player); }
.mk-base   .mk-dot { background: var(--c-base); }
.mk-vehicle .mk-dot { background: var(--c-vehicle); }
.mk-chest  .mk-dot { background: var(--c-chest); }
.mk-storage .mk-dot { background: var(--c-storage); }
.mk-trap   .mk-dot { background: var(--c-trap); }
.mk-turret .mk-dot { background: var(--c-turret); }
/* Popover header icon fallback tints for the new layers */
.mp-ico.mk-trap, .mp-ico-fb.mk-trap { background: var(--c-trap); }
.mp-ico.mk-turret, .mp-ico-fb.mk-turret { background: var(--c-turret); }

/* Info card — anchored next to the clicked marker (position set in JS). */
.map-popover {
  position: absolute; z-index: 20; width: 330px; max-width: calc(100% - 24px); padding: 0.85rem 1rem;
  background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius-lg);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
}

/* Right-click context menu — "Copy teleport" for the clicked spot. */
.map-ctx {
  position: absolute; z-index: 25; padding: 0.25rem;
  background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55);
}
.map-ctx-item {
  display: flex; align-items: center; gap: 0.45rem; width: 100%; white-space: nowrap;
  background: none; border: none; color: var(--text); font-size: 0.82rem; font-weight: 600;
  padding: 0.45rem 0.6rem; border-radius: var(--radius); letter-spacing: 0;
}
.map-ctx-item:hover { background: var(--hover-bg); border: none; color: var(--amber-hi); }
.map-ctx-item .ico { color: var(--amber); }
.map-ctx-item.copied, .map-ctx-item.copied:hover { color: var(--online); background: none; }
.map-ctx-xy { color: var(--muted); font-family: var(--mono); font-size: 0.75rem; font-weight: 400; }
.mp-close {
  position: absolute; top: 5px; right: 7px; width: 22px; height: 22px; padding: 0; line-height: 1;
  background: none; border: none; color: var(--muted); font-size: 20px; cursor: pointer;
}
.mp-close:hover { color: var(--amber-hi); background: none; border: none; }
.mp-head { display: flex; align-items: center; gap: 0.55rem; margin: 0 1.2rem 0.6rem 0; }
.mp-ico { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: var(--radius-md); flex: none; border: 1px solid rgba(0, 0, 0, 0.4); }
.mp-ico .ico { width: 15px; height: 15px; color: var(--bg); }
.mp-ico.mk-player { background: var(--c-player); }
.mp-ico.mk-base { background: var(--c-base); }
.mp-ico.mk-vehicle { background: var(--c-vehicle); }
.mp-ico.mk-chest { background: var(--c-chest); }
.mp-ico.mk-storage { background: var(--c-storage); }
.mp-headtxt { min-width: 0; }
.mp-title { color: var(--text); font-weight: 700; font-size: 0.95rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-sub { font-size: 0.75rem; color: var(--muted); }
.mp-on { color: var(--c-player); font-weight: 600; }
.mp-off { color: var(--offline); font-weight: 600; }
.map-popover .mp-row { display: flex; justify-content: space-between; gap: 0.75rem; font-size: 0.82rem; padding: 0.2rem 0; border-top: 1px solid var(--line-2); }
.map-popover .mp-rows .mp-row:first-child { border-top: none; }
.map-popover .mp-row span { color: var(--muted); }
.map-popover .mp-row b { color: var(--text); font-variant-numeric: tabular-nums; text-align: right; }
.map-popover .dim { color: var(--muted); }
.mp-id { font-family: var(--mono); font-size: 0.78rem; user-select: all; cursor: text; }
/* Player card → Property: collapsible groups, one row per owned thing, the whole row opens it
   on the live map.

   Everything below fights ONE thing: the global `button:hover` at the top of this file paints
   every button solid amber. These are buttons for keyboard/AT reasons, not visually — so each
   state is stated explicitly and at a specificity that beats it, or the amber block comes back
   and the grey sub-text on it becomes unreadable. */
.pd-stuff-head {
  display: flex; align-items: center; gap: .45rem; width: 100%; margin: .8rem 0 .1rem;
  padding: .35rem .1rem; text-align: left; cursor: pointer; font: inherit; letter-spacing: .04em;
  background: none; border: 0; border-bottom: 1px solid var(--line-2); color: var(--text); border-radius: 0;
}
.pd-stuff-head:hover, .pd-stuff-head:focus-visible { background: none; border-color: var(--line-2); color: var(--amber-hi); }
.pd-stuff-head:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
/* Drawn, not from the sprite — there is no chevron in it, and inventing one would mean an
   icon that renders as an empty box everywhere it is reused. */
.pd-stuff-head .pd-caret {
  margin-left: auto; width: 0; height: 0; transition: transform .15s, border-top-color .14s;
  border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 5px solid var(--muted);
}
.pd-stuff-head[aria-expanded="false"] .pd-caret { transform: rotate(-90deg); }
.pd-stuff-head:hover .pd-caret { border-top-color: var(--amber-hi); }
.pd-stuff-n { padding: 0 .4rem; border-radius: 999px; background: var(--inset); color: var(--muted); font-size: .72rem; font-weight: 400; }
.pd-stuff-list { display: flex; flex-direction: column; gap: .3rem; margin: .45rem 0 .3rem; }
.pd-stuff-list[hidden] { display: none; }
.pd-stuff {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .15rem .6rem;
  width: 100%; padding: .5rem .65rem; text-align: left; cursor: pointer; font: inherit; letter-spacing: 0;
  background: var(--panel-2); border: 1px solid var(--line-2); border-radius: var(--radius); color: var(--text);
}
/* Tinted, not filled: the row keeps a dark ground so both lines stay legible on hover. */
.pd-stuff:hover:not([disabled]), .pd-stuff:focus-visible:not([disabled]) {
  background: rgba(240, 130, 12, 0.10); border-color: var(--amber); color: var(--text);
}
.pd-stuff:focus-visible { outline: none; }
.pd-stuff[disabled] { cursor: default; opacity: .55; background: var(--panel-2); border-color: var(--line-2); color: var(--text); }
.pd-stuff-img {
  grid-column: 1; grid-row: 1 / span 2; display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: var(--radius); background: var(--inset); overflow: hidden;
}
.pd-stuff-img img { max-width: 100%; max-height: 100%; object-fit: contain; }
.pd-stuff-img-fb { color: var(--muted); }
.pd-stuff-main { grid-column: 2; font-weight: 600; }
.pd-stuff-sub { grid-column: 2; font-size: .76rem; color: var(--muted); font-weight: 400; }
.pd-stuff:hover:not([disabled]) .pd-stuff-sub { color: var(--text); opacity: .75; }
.pd-stuff-go { grid-column: 3; grid-row: 1 / span 2; color: var(--muted); }
.pd-stuff:hover:not([disabled]) .pd-stuff-go { color: var(--amber-hi); }

/* Owner name inside a popup row. It sits in running text, so it must NOT look or behave like a
   button — the global button skin is cancelled in every state and only the colour reacts. */
.map-popover .mp-owner,
.map-popover .mp-owner:hover,
.map-popover .mp-owner:active {
  display: inline; padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none;
  transform: none; font: inherit; letter-spacing: 0;
}
.map-popover .mp-owner { color: var(--text); cursor: pointer; border-bottom: 1px dotted var(--muted); }
.map-popover .mp-owner:hover { color: var(--amber-hi); border-bottom: 1px solid var(--amber-hi); }
.map-popover .mp-owner:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.mp-card-btn {
  display: flex; align-items: center; justify-content: center; gap: 0.4rem; width: 100%; margin-top: 0.65rem;
  padding: 0.4rem; background: var(--panel-2); border: 1px solid var(--line-amber); color: var(--amber-hi);
  font-family: var(--ui); font-weight: 600; font-size: 0.82rem; border-radius: var(--radius-md); cursor: pointer;
}
.mp-card-btn:hover { background: var(--amber-hi); color: var(--on-amber); }
.mp-card-btn .ico { width: 14px; height: 14px; }
.mp-tp {
  display: flex; align-items: center; justify-content: center; gap: 0.4rem; width: 100%; margin-top: 0.6rem;
  padding: 0.4rem; background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
  font-family: var(--ui); font-weight: 600; font-size: 0.8rem; border-radius: var(--radius-md); cursor: pointer;
}
.mp-tp:hover { border-color: var(--line-amber); color: var(--amber-hi); background: var(--panel-2); }
.mp-tp.copied { border-color: var(--c-player); color: var(--c-player); }
.mp-tp .ico { width: 14px; height: 14px; }
/* Container contents (chest/vehicle) */
.mp-contents-btn, .mp-parts-btn {
  display: flex; align-items: center; justify-content: center; gap: 0.4rem; width: 100%; margin-top: 0.5rem;
  padding: 0.4rem; background: var(--panel-2); border: 1px solid var(--line); color: var(--text);
  font-family: var(--ui); font-weight: 600; font-size: 0.8rem; border-radius: var(--radius-md); cursor: pointer;
}
.mp-contents-btn:hover, .mp-parts-btn:hover { border-color: var(--line-amber); color: var(--amber-hi); background: var(--panel-2); }
.mp-contents-btn.open, .mp-parts-btn.open { color: var(--amber-hi); border-color: var(--line-amber); }
.mp-contents-btn .ico, .mp-parts-btn .ico { width: 14px; height: 14px; }
.mp-contents { margin-top: 0.5rem; border-top: 1px solid var(--line); max-height: 240px; overflow-y: auto; overscroll-behavior: contain; }
.mp-contents[hidden] { display: none; }
.mp-c-head {
  display: flex; align-items: center; gap: 0.4rem; padding: 0.45rem 0.4rem; position: sticky; top: 0; z-index: 1;
  background: var(--panel); border-bottom: 1px solid var(--line);
  color: var(--text); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
}
.mp-c-head .ico { width: 13px; height: 13px; color: var(--amber-hi); }
.mp-c-count { margin-left: auto; color: var(--muted); font-weight: 600; text-transform: none; letter-spacing: 0; }
.mp-c-msg { padding: 0.7rem; text-align: center; color: var(--muted); font-size: 0.82rem; }
.mp-c-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.18rem 0.1rem; }
.mp-c-img { width: 22px; height: 22px; flex: none; display: inline-flex; align-items: center; justify-content: center; background: var(--panel-2); border-radius: var(--radius); overflow: hidden; }
.mp-c-img img { width: 100%; height: 100%; object-fit: contain; }
.mp-c-ph { width: 13px; height: 13px; color: var(--muted); opacity: 0.7; }
.mp-c-name { flex: 1; min-width: 0; font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-c-n { font-size: 0.78rem; color: var(--muted); font-variant-numeric: tabular-nums; }
/* Vehicle-parts group header (kind: body / wheel / armor / …). */
.mp-c-grp { display: flex; align-items: center; gap: 0.35rem; margin: 0.35rem 0 0.1rem; padding: 0.1rem 0.1rem;
  color: var(--amber-hi); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; }
.mp-c-grp:first-of-type { margin-top: 0.1rem; }
.mp-c-gn { color: var(--muted); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Slim, themed scrollbars for the map's scroll areas. */
.map-side, .mp-contents { scrollbar-width: thin; scrollbar-color: rgba(240, 130, 12, 0.4) transparent; }
.map-side::-webkit-scrollbar, .mp-contents::-webkit-scrollbar { width: 9px; }
.map-side::-webkit-scrollbar-track, .mp-contents::-webkit-scrollbar-track { background: transparent; }
.map-side::-webkit-scrollbar-thumb, .mp-contents::-webkit-scrollbar-thumb {
  background: rgba(240, 130, 12, 0.35); border-radius: var(--radius-md); border: 2px solid transparent; background-clip: content-box;
}
.map-side::-webkit-scrollbar-thumb:hover, .mp-contents::-webkit-scrollbar-thumb:hover {
  background: rgba(240, 130, 12, 0.6); background-clip: content-box;
}
/* Header thumbnail (item-DB image) with icon fallback */
.mp-ico.mp-img { position: relative; overflow: hidden; background: var(--panel-2); }
.mp-ico.mp-img img { width: 100%; height: 100%; object-fit: contain; display: block; }
.mp-ico.mp-img .mp-ico-fb { display: none; position: absolute; inset: 0; align-items: center; justify-content: center; }
.mp-ico.mp-img .mp-ico-fb .ico { width: 15px; height: 15px; color: var(--amber-hi); }
.mp-ico.mp-img.mp-imgfail img { display: none; }
.mp-ico.mp-img.mp-imgfail .mp-ico-fb { display: flex; }
/* List-row thumbnail */
.ml-thumb { width: 22px; height: 22px; flex: none; border-radius: var(--radius); overflow: hidden; background: var(--panel-2); display: inline-flex; align-items: center; justify-content: center; }
.ml-thumb img { width: 100%; height: 100%; object-fit: contain; }

.map-empty {
  position: absolute; top: 1rem; left: 50%; transform: translateX(-50%);
  padding: 0.4rem 0.9rem; background: rgba(8, 10, 14, 0.85); border: 1px solid var(--line);
  border-radius: var(--pill); color: var(--muted); font-size: 0.85rem;
}

.map-locked {
  position: absolute; inset: 0; z-index: 30; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 0.5rem; text-align: center;
  background: rgba(8, 10, 8, 0.9); backdrop-filter: blur(3px); border: 1px solid var(--line); border-radius: var(--radius-md);
}
.map-locked .map-lock-ico { width: 40px; height: 40px; color: var(--amber); margin-bottom: 0.3rem; }
.map-locked h3 { margin: 0; color: var(--text); }
.map-locked p { margin: 0; color: var(--muted); max-width: 340px; }
.map-locked button { margin-top: 0.6rem; }
.map-locked.hidden { display: none; }

/* ── Login (Discord + username) + Admins section ─────────────────────────── */
.login-discord {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem; width: 100%; margin-top: 0.5rem;
  padding: 0.6rem; background: var(--discord); border: 1px solid var(--discord); color: #fff;
  font-family: var(--ui); font-weight: 600; border-radius: var(--radius-md); cursor: pointer; text-decoration: none;
}
.login-discord:hover { background: var(--discord-dn); border-color: var(--discord-dn); }
.login-discord .ico { width: 18px; height: 18px; }
.anav-btn[hidden] { display: none; }

.amodal.amodal-md .amodal-box { max-width: 620px; }
#admins-content { margin-top: 1.25rem; }
.adm-card {
  display: flex; align-items: center; gap: 1rem; padding: 0.85rem 1rem; margin: 0 1.5rem 0.6rem;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-lg);
}
.adm-card.adm-default { border-color: var(--line-amber); }
.adm-card.adm-off { opacity: 0.6; }
.adm-main { flex: 1; min-width: 0; }
.adm-avatar { width: 44px; height: 44px; border-radius: 50%; flex: none; object-fit: cover; border: 1px solid var(--line); }
.adm-avatar-fb {
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 1.1rem; color: var(--muted); background: var(--panel-2);
}
.adm-avatar-fb.discord { color: #fff; background: var(--discord); border-color: var(--discord); }
.adm-name { font-weight: 700; color: var(--text); }
.adm-sub { display: flex; align-items: center; font-size: 0.8rem; color: var(--muted); margin: 0.1rem 0 0.4rem; }
.adm-did { font-variant-numeric: tabular-nums; opacity: 0.75; }
.adm-dot { margin: 0 0.4rem; opacity: 0.5; }
.adm-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; }
.adm-methods { display: inline-flex; gap: 0.3rem; margin-right: 0.15rem; }
.adm-method, .adm-badge {
  display: inline-flex; align-items: center; height: 20px; box-sizing: border-box;
  padding: 0 0.5em; border-radius: var(--radius); background: var(--panel-2); border: 1px solid var(--line);
  color: var(--muted); font-size: 0.7rem; line-height: 1;
}
.adm-method { font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
.adm-method.discord { color: var(--discord-hi); background: rgba(88, 101, 242, 0.18); border-color: rgba(88, 101, 242, 0.5); }
.adm-method.off { color: var(--alarm); border-color: rgba(229, 68, 63, 0.4); }
.adm-perms { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.adm-badge.full { font-weight: 700; color: var(--on-amber); background: var(--amber); border-color: var(--amber); letter-spacing: 0.01em; }
.adm-badge.dim { opacity: 0.7; }
.adm-actions { display: flex; gap: 0.4rem; flex: none; }
.adm-actions .secondary { padding: 0.35rem 0.6rem; font-size: 0.82rem; }
.adm-toggle { display: inline-flex; align-items: center; gap: 0.45rem; color: var(--text); font-weight: 600; font-size: 0.85rem; cursor: pointer; flex: none; }
.adm-toggle input { accent-color: var(--amber); }
.adm-form { margin: 1rem 1.5rem 0; padding: 1rem; background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius-lg); }
.adm-form-title { font-weight: 700; color: var(--amber-hi); margin-bottom: 0.6rem; }
.adm-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin-bottom: 0.75rem; }
.adm-field { display: flex; flex-direction: column; gap: 0.3rem; }
.adm-field label { font-size: 0.8rem; color: var(--muted); font-weight: 600; }
.adm-field input { padding: 0.5rem 0.6rem; background: var(--panel-2); border: 1px solid var(--line); color: var(--text); border-radius: var(--radius-md); font-family: var(--ui); }
.adm-field input:disabled { opacity: 0.6; }
.adm-perm-actions { display: flex; align-items: center; gap: 0.5rem; margin: 0.5rem 0; }
.adm-perm-heading { font-size: 0.82rem; color: var(--muted); font-weight: 600; margin-right: auto; }
.adm-perm-group { margin-bottom: 0.7rem; }
.adm-perm-gtitle { font-size: 0.68rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700; margin: 0 0 0.35rem; }
.adm-perm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(155px, 1fr)); gap: 0.45rem; }
.adm-perm {
  display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.6rem;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius-md); cursor: pointer;
  font-size: 0.82rem; font-weight: 600; color: var(--text); user-select: none;
}
.adm-perm:hover { border-color: var(--line-amber); background: var(--hover-bg); }
.adm-perm:has(input:checked) { border-color: var(--amber); background: rgba(240, 130, 12, 0.14); color: var(--amber-hi); }
.adm-perm input { accent-color: var(--amber); width: 15px; height: 15px; flex: none; }
.adm-form-actions { display: flex; gap: 0.6rem; margin-top: 1rem; }
.link-btn { background: none; border: none; color: var(--amber-hi); cursor: pointer; font-family: var(--ui); font-weight: 600; font-size: 0.8rem; padding: 0.15rem 0.25rem; }
.link-btn:hover { background: none; color: #fff; text-decoration: underline; }
@media (max-width: 640px) { .adm-grid { grid-template-columns: 1fr; } .adm-card { flex-direction: column; align-items: stretch; } }

/* Language settings: default-language dropdown + enabled-languages checkbox list */
.settings-field select { font-family: var(--ui); font-size: 0.9rem; padding: 0.5rem 0.6rem; background: var(--panel-2, #14150f); color: var(--fg, #e8e6df); border: 1px solid var(--line, #2a2c22); border-radius: 6px; }
.lang-checks { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; margin-top: 0.4rem; }
.lang-check { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.9rem; cursor: pointer; }
.lang-check input { width: auto; margin: 0; }
.lang-check input:disabled { opacity: 0.6; cursor: default; }
/* Header per-admin language switcher (premium) — same metrics as the nav links
   next to it (padding/font/border), so all header controls share one height. */
.admin-lang-select {
  padding: 0.5rem 0.8rem; font-size: 0.82rem; font-family: var(--ui); font-weight: 600; letter-spacing: 0.05em;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius);
  cursor: pointer; outline: none;
}
.admin-lang-select:hover { background: var(--panel-2); border-color: var(--line-amber); color: var(--amber-hi); }
/* Custom language dropdown with flags (native selects can't show images). */
.lang-dd { position: relative; display: inline-flex; }
/* line-height 1.5 = what the neighbouring <a class="navlink"> controls inherit
   from body; buttons default to ~1.2 and end up a few px shorter without it. */
.lang-dd-btn { display: inline-flex; align-items: center; gap: 0.5rem; line-height: 1.5; }
.lang-flag { width: 1.333em; height: 1em; border-radius: 2px; object-fit: cover; flex: none; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.45); } /* 4:3, matches flag-icons SVGs (640×480) */
.lang-dd-chev { color: var(--muted); font-size: 0.7rem; }
.lang-dd-list {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 90; min-width: 175px;
  display: flex; flex-direction: column; gap: 2px; padding: 0.35rem;
  background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
}
.lang-dd-list[hidden] { display: none; }
.lang-dd-item {
  display: flex; align-items: center; gap: 0.55rem; padding: 0.45rem 0.6rem;
  background: none; border: 0; border-radius: var(--radius); color: var(--text);
  font-family: var(--ui); font-size: 0.85rem; cursor: pointer; text-align: left;
}
.lang-dd-item:hover { background: var(--hover-bg); color: var(--amber-hi); }
.lang-dd-item.active { color: var(--amber-hi); }

/* Unified MOTD editor: full-width field — label + language buttons on the top row,
   one large textarea spanning underneath (the default label/control grid is too
   narrow for a text banner). */
.settings-field.motd-field { display: flex; flex-direction: column; align-items: stretch; gap: 0.45rem; }
.motd-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.motd-langs { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.motd-lang-btn {
  padding: 0.22rem 0.65rem; font-size: 0.8rem; cursor: pointer;
  background: var(--inset); color: var(--muted); border: 1px solid var(--line); border-radius: var(--pill);
}
.motd-lang-btn:hover { background: var(--inset); color: var(--text); border-color: var(--line-amber); }
.motd-lang-btn.active { background: var(--panel-2); color: var(--amber-hi); border-color: var(--line-amber); }
.motd-editor { display: block; }
.motd-editor-text { width: 100%; min-height: 5.5rem; resize: vertical; line-height: 1.4; }

/* Custom dropdown chevron with breathing room — the native arrow sits glued to the
   right border and ignores padding, so replace it (appearance:none) with an inline
   SVG placed a comfortable 0.7rem from the edge. Kept at the END of the sheet so no
   later `background:` shorthand can wipe the image. Covers the header language
   switcher, roster/chat toolbars, config pickers and row editors. */
.roster-select, .settings-field select, .er-f select {
  appearance: none; -webkit-appearance: none;
  padding-right: 2rem;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23949aa8' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.7rem center;
}

/* Floating "back to top" button (bottom-right). Overrides the global amber button
   base — this one is a quiet circular outline control that fades in on scroll. */
.back-top {
  position: fixed; right: 1.1rem; bottom: 1.1rem; z-index: 80;
  width: 46px; height: 46px; padding: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel-2); border: 1px solid var(--line-amber); color: var(--amber-hi);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
  opacity: 0; visibility: hidden; transform: translateY(10px);
  transition: opacity 0.18s, transform 0.18s, visibility 0.18s, border-color 0.14s, color 0.14s;
}
.back-top.show { opacity: 1; visibility: visible; transform: none; }
.back-top:hover { background: var(--panel-2); border-color: var(--amber); color: var(--amber); }
.back-top svg { width: 20px; height: 20px; }

/* ══ Motion design (mirrors the public site) ════════════════════════════════
   Tab transitions, modal reveal and microinteractions. CSS-only; animations
   restart naturally when an element is re-shown (.hidden toggles display).
   NOTE: nothing here sets a `background:` shorthand on selects — the custom
   dropdown-chevron rule above must stay effective. */

/* Tab switch: the shown panel fades in and rises slightly. */
@keyframes viewIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.tab-panel { animation: viewIn 0.26s ease both; }

/* Intro: the nav buttons settle in once on load. */
@keyframes topIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.anav-btn { animation: topIn 0.3s ease both; }

/* Modal reveal (player detail / app status). */
@keyframes modalIn { from { opacity: 0; transform: translateY(14px) scale(0.985); } to { opacity: 1; transform: none; } }
.amodal-box { animation: modalIn 0.22s ease; }

/* Dropdown reveal (language picker). */
@keyframes ddIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.lang-dd-list { animation: ddIn 0.16s ease; }

/* Microinteractions: smooth state changes on nav/tab/quiet controls (the main
   button system already transitions via the global `button` rule). */
.anav-btn, .pd-tab, .lang-dd-btn, .lang-dd-item, .navlink, .roster-select,
.motd-lang-btn, .foot-link, .gl-map, .gl-player, .pd-maplink {
  transition: color 0.15s, border-color 0.15s, background-color 0.15s, transform 0.15s;
}

/* Summary/stat cards lift gently on hover. */
.pd-stat, .pd-card { transition: border-color 0.18s, transform 0.18s; }
.pd-stat:hover { border-color: var(--line-amber); transform: translateY(-2px); }

/* Themed scrollbars for the whole panel (the map lists already had them). */
html { scrollbar-width: thin; scrollbar-color: rgba(255, 154, 46, 0.35) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(255, 154, 46, 0.28); border-radius: 5px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255, 154, 46, 0.45); }

/* Accessibility: honour the OS "reduce motion" preference. */
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; scroll-behavior: auto; } }

/* ── Manager self-update: badge, footer link, card, modal, progress ───────── */
#mgr-update-btn.has-update { border-color: var(--amber); color: var(--amber-hi); }
#mgr-update-btn.has-update::after { content: ''; position: absolute; top: -3px; right: -3px; width: 9px; height: 9px; border-radius: 50%; background: var(--amber); box-shadow: 0 0 0 2px var(--panel), 0 0 6px var(--amber); animation: mu-pulse 1.8s ease-in-out infinite; }
#mgr-update-btn { position: relative; }
@keyframes mu-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

.foot-update { margin-left: .5rem; background: none; border: 0; padding: 0; font: inherit; color: var(--amber); cursor: pointer; text-decoration: none; }
.foot-update:hover { color: var(--amber-hi); text-decoration: underline; }
.foot-update.hidden { display: none; }

.mu-card { border: 1px solid var(--line); background: var(--panel); border-radius: var(--radius); padding: 1.1rem 1.3rem; margin: 0.5rem 1.5rem 2rem; }
.mu-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.mu-head-l { min-width: 0; }
.mu-title { display: flex; align-items: center; gap: .5rem; font-family: var(--display, inherit); font-size: .82rem; font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--text); }
.mu-title .ico { width: 16px; height: 16px; color: var(--amber); }
.mu-ver { margin-top: .35rem; color: var(--muted); font-size: .84rem; }
.mu-ver b { color: var(--text); font-weight: 600; }
.mu-head #mu-check-btn { flex: none; }
.mu-status { margin-top: .7rem; font-size: .9rem; min-height: 1.2em; }
.mu-avail { color: var(--amber); font-weight: 600; }
.mu-ok { color: var(--online); }
.mu-muted { color: var(--muted); }
.mu-link { background: none; border: 0; padding: 0 0 0 .3rem; font: inherit; color: var(--amber); cursor: pointer; text-decoration: underline; }
.mu-auto { display: flex; align-items: center; gap: .5rem; margin-top: .9rem; padding-top: .8rem; border-top: 1px dashed var(--line); color: var(--muted); font-size: .86rem; cursor: pointer; }
.mu-auto.hidden { display: none; }

.mu-modal-ver { font-size: 1.15rem; margin: .3rem 0 .8rem; }
.mu-vfrom { color: var(--muted); }
.mu-arrow { color: var(--amber); margin: 0 .3rem; }
.mu-vto { color: var(--amber-hi); font-weight: 700; }
.mu-notes { max-height: 40vh; overflow: auto; background: var(--bg-2); border: 1px solid var(--line); border-radius: 6px; padding: .7rem .9rem; font-size: .86rem; line-height: 1.55; color: var(--data-text); white-space: pre-wrap; }
.mu-links { margin: .8rem 0; font-size: .88rem; }
.mu-links a { color: var(--amber); }
.mu-modal-actions { margin: 1rem 0 .5rem; }
.mu-install-btn { background: var(--amber); color: var(--on-amber); border: 0; padding: .6rem 1.4rem; border-radius: 6px; font-weight: 700; cursor: pointer; letter-spacing: .02em; }
.mu-install-btn:hover { background: var(--amber-hi); }
.mu-prem-note { margin: 1rem 0 .5rem; font-size: .86rem; line-height: 1.5; }
.mu-dismiss { display: flex; align-items: center; gap: .5rem; margin-top: 1rem; padding-top: .8rem; border-top: 1px solid var(--line); color: var(--muted); font-size: .84rem; cursor: pointer; }

.mu-progbar { width: 100%; max-width: 320px; height: 8px; margin: 1rem auto 0; background: var(--bg-2); border: 1px solid var(--line); border-radius: 5px; overflow: hidden; }
.mu-progfill { height: 100%; width: 0; background: var(--amber); transition: width .3s ease; }
.mu-progfill.mu-progerr { background: #d9534f; }

.mu-feed { margin-top: .9rem; padding-top: .8rem; border-top: 1px dashed var(--line); }
.mu-feed-label { display: block; font-size: .8rem; letter-spacing: .03em; text-transform: uppercase; color: var(--muted); margin-bottom: .4rem; }
.mu-feed-row { display: flex; gap: .5rem; flex-wrap: wrap; }
.mu-feed-input { flex: 1 1 340px; min-width: 0; background: var(--bg-2); border: 1px solid var(--line); border-radius: 6px; padding: .5rem .7rem; color: var(--text); font-family: inherit; font-size: .86rem; }
.mu-feed-input:focus { outline: none; border-color: var(--amber); }
.mu-feed-hint { margin-top: .4rem; font-size: 0.75rem; line-height: 1.45; color: var(--muted); }
.mu-feed-msg { margin-top: .4rem; font-size: .84rem; min-height: 1em; }
.mu-feed-msg.mu-ok { color: var(--online); }
.mu-feed-msg.mu-err, .mu-err { color: #d9534f; }

/* ── Plugins section ─────────────────────────────────────────────────────── */
.pl-viewtabs { display: inline-flex; gap: 2px; background: rgba(255,255,255,0.04); border: 1px solid var(--line); border-radius: 999px; padding: 2px; }
.pl-vtab { border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 0.8rem; padding: 0.32rem 0.95rem; border-radius: 999px; cursor: pointer; }
.pl-vtab.active { background: var(--amber); color: var(--on-amber); font-weight: 600; }
.pl-installed { font-size: 0.76rem; color: #8fe0a8; display: inline-flex; align-items: center; gap: 0.3rem; }
.pl-filter { display: inline-flex; gap: 2px; background: rgba(255,255,255,0.04); border: 1px solid var(--line); border-radius: 999px; padding: 2px; }
.pl-fbtn { border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 0.8rem; padding: 0.3rem 0.8rem; border-radius: 999px; cursor: pointer; }
.pl-fbtn.active { background: var(--amber); color: var(--on-amber); font-weight: 600; }
#pl-lockwrap { margin: 1rem 1.5rem 2rem; }
/* drag-and-drop install overlay */
#plugins-screen { position: relative; }
.pl-drop { position: absolute; inset: 0; z-index: 60; display: none; align-items: center; justify-content: center;
  background: rgba(10,11,8,0.82); backdrop-filter: blur(2px); border: 2px dashed var(--amber); border-radius: var(--radius-lg); pointer-events: none; }
#plugins-screen.pl-dragging .pl-drop { display: flex; }
.pl-drop-in { display: flex; align-items: center; gap: 0.6rem; font-family: var(--ui, inherit); font-weight: 600; font-size: 1.1rem; color: var(--amber); }
.pl-drop-in .ico { width: 22px; height: 22px; }
.pl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr)); gap: 1rem; padding: 0.2rem; }

/* Reusable section card for plugin workspaces (the SDK documents `.card`). A plain boxed panel
   with its own padding — plugins stack these inside their workspace. */
.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-md); padding: 1.1rem 1.2rem; }
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }

/* card: fixed-shape row (thumb + body); body is a column with the footer pinned to the bottom
   so every card lines up regardless of description length. */
.pl-card { display: flex; gap: 0.9rem; padding: 1rem; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-lg); transition: border-color 0.15s, box-shadow 0.15s; }
.pl-card.on { border-color: var(--line-amber); }
.pl-thumb { flex: 0 0 56px; width: 56px; height: 56px; border-radius: var(--radius); overflow: hidden;
  background: rgba(255,255,255,0.05); display: flex; align-items: center; justify-content: center; }
.pl-thumb img { width: 100%; height: 100%; object-fit: cover; }
.pl-ph { width: 26px; height: 26px; opacity: 0.4; }
.pl-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 0.35rem; }

/* header row: name grows & truncates, badge + toggle stay put on one line */
.pl-head { display: flex; align-items: center; gap: 0.5rem; }
.pl-name { font-weight: 600; color: var(--text); font-size: 0.98rem; min-width: 0; flex: 1 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-badge { font-size: 0.64rem; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.14rem 0.44rem;
  border-radius: 999px; border: 1px solid var(--line); color: var(--muted); flex: 0 0 auto; white-space: nowrap; }
.pl-b-ue { border-color: rgba(240,130,12,0.5); color: var(--amber); }
.pl-b-rt { border-color: rgba(120,160,255,0.5); color: #9db8ff; }
.pl-b-mgr { border-color: rgba(120,220,150,0.5); color: #8fe0a8; }
.pl-actions { display: flex; align-items: center; gap: 0.4rem; flex: 0 0 auto; }
.pl-switch { position: relative; display: inline-block; width: 40px; height: 22px; flex: 0 0 auto; }
.pl-switch input { opacity: 0; width: 0; height: 0; }
.pl-slider { position: absolute; inset: 0; background: rgba(255,255,255,0.14); border-radius: 999px; cursor: pointer; transition: 0.18s; }
.pl-slider::before { content: ""; position: absolute; height: 16px; width: 16px; left: 3px; top: 3px; background: #ddd; border-radius: 50%; transition: 0.18s; }
.pl-switch input:checked + .pl-slider { background: var(--amber); }
.pl-switch input:checked + .pl-slider::before { transform: translateX(18px); background: var(--on-amber); }
.pl-switch input:disabled + .pl-slider { opacity: 0.4; cursor: not-allowed; }

/* meta / description / deps — all clamp so cards keep an even height */
.pl-meta { color: var(--muted); font-size: 0.76rem; display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; min-width: 0; }
.pl-meta a { color: var(--amber); text-decoration: none; }
.pl-rt { font-size: 0.66rem; color: #e6b96a; border: 1px dashed rgba(230,185,106,0.5); border-radius: 4px; padding: 0.02rem 0.34rem; }
.pl-desc { margin: 0; color: var(--muted); font-size: 0.82rem; line-height: 1.5; min-width: 0; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.pl-deps { font-size: 0.74rem; color: var(--muted); display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; min-width: 0; }
.pl-deps-l { text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.66rem; }
.pl-dep { padding: 0.06rem 0.4rem; border-radius: 999px; border: 1px solid var(--line); }
.pl-dep.ok { border-color: rgba(120,220,150,0.5); color: #8fe0a8; }
.pl-dep.bad { border-color: rgba(220,120,120,0.5); color: #e39a9a; }
.pl-incompat { display: flex; align-items: center; gap: 0.4rem; font-size: 0.74rem; color: #e39a9a;
  background: rgba(220,120,120,0.1); border: 1px solid rgba(220,120,120,0.4); border-radius: 6px; padding: 0.35rem 0.5rem; overflow-wrap: anywhere; }
.pl-incompat .ico { width: 14px; height: 14px; flex: 0 0 auto; }
.pl-empty { grid-column: 1 / -1; color: var(--muted); font-size: 0.85rem; padding: 1.4rem; text-align: center; }

/* footer: buttons on one aligned row, pinned to the card bottom; uninstall floats right */
.pl-foot { margin-top: auto; padding-top: 0.5rem; display: flex; flex-wrap: wrap; gap: 0.45rem; align-items: center; }
.pl-btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.35rem; font: inherit;
  font-size: 0.76rem; line-height: 1; height: 30px; box-sizing: border-box; white-space: nowrap;
  border: 1px solid var(--line); background: rgba(255,255,255,0.03); color: var(--text);
  padding: 0 0.7rem; border-radius: 7px; cursor: pointer; transition: background .12s, border-color .12s, color .12s; }
.pl-btn:hover { background: rgba(230,185,106,0.14); border-color: rgba(230,185,106,0.5); color: var(--amber); }
.pl-btn .ico { width: 15px; height: 15px; flex: 0 0 auto; }
.pl-btn.primary { background: var(--amber); border-color: var(--amber); color: var(--on-amber); font-weight: 600; }
.pl-btn.primary:hover { filter: brightness(1.08); color: var(--on-amber); }
.pl-btn.pl-update { border-color: rgba(120,160,255,0.55); color: #9db8ff; }
.pl-btn.pl-update:hover { background: rgba(120,160,255,0.14); border-color: rgba(120,160,255,0.7); color: #b9cbff; }
.pl-btn.pl-danger { color: #e39a9a; }
.pl-btn.pl-danger:hover { background: rgba(220,120,120,0.14); border-color: rgba(220,120,120,0.5); color: #e39a9a; }

/* plugin workspace (a plugin's own tabs, opened in-place from its card) */
#plugins-screen.pl-in-workspace > .screen-bar,
#plugins-screen.pl-in-workspace > .settings-note,
#plugins-screen.pl-in-workspace > .prem-lock-wrap { display: none; }
.pl-workspace { display: flex; flex-direction: column; margin: 0.2rem 1.5rem 2rem; }
.pl-workspace.hidden { display: none; }
/* header bar: prominent back button + plugin title, clearly separated from the content */
.pl-ws-bar { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 0.2rem 0 1rem; margin-bottom: 1.2rem; border-bottom: 1px solid var(--line); }
.pl-ws-back { display: inline-flex; align-items: center; gap: 0.45rem; font: inherit; font-size: 0.85rem;
  border: 1px solid var(--line); background: rgba(255,255,255,0.04); color: var(--text);
  padding: 0.5rem 0.9rem; border-radius: 8px; cursor: pointer; transition: background .12s, border-color .12s, color .12s; }
.pl-ws-back:hover { background: rgba(230,185,106,0.14); border-color: rgba(230,185,106,0.5); color: var(--amber); }
.pl-ws-arrow { font-size: 1.1em; line-height: 1; }
.pl-ws-title { font-family: var(--ui, inherit); font-weight: 600; font-size: 1.1rem; color: var(--text);
  display: inline-flex; align-items: center; gap: 0.5rem; }
.pl-ws-title::before { content: ""; width: 4px; height: 1.1em; border-radius: 2px; background: var(--amber); }
/* sub-nav of the plugin's own tabs */
.pl-ws-nav { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1.2rem; }
.pl-ws-tab { display: inline-flex; align-items: center; gap: 0.4rem; font: inherit; font-size: 0.85rem;
  border: 1px solid var(--line); background: rgba(255,255,255,0.03); color: var(--muted); padding: 0.45rem 0.9rem;
  border-radius: 8px; cursor: pointer; transition: background .12s, color .12s, border-color .12s; }
.pl-ws-tab:hover { color: var(--text); background: rgba(255,255,255,0.06); }
.pl-ws-tab.active { color: var(--on-amber); background: var(--amber); border-color: var(--amber); font-weight: 600; }
.pl-ws-tab .fic, .pl-ws-tab .ssa-ic { width: 16px; height: 16px; display: inline-flex; }
/* content surface: a plain container — the plugin supplies its own `.card` sections as the boxes,
   so we never double-frame. */
.pl-ws-body { min-width: 0; overflow: visible; }
.pl-ws-empty { color: var(--muted); padding: 1.5rem; }

/* config editor modal */
.pl-modal-ov { position: fixed; inset: 0; background: rgba(0,0,0,0.6); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; z-index: 200; padding: 1.5rem; }
.pl-modal { background: var(--panel, #1b1b1e); border: 1px solid var(--line); border-radius: 12px;
  width: min(720px, 100%); max-height: 88vh; display: flex; flex-direction: column; box-shadow: 0 20px 60px rgba(0,0,0,0.5); }
.pl-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.9rem 1.1rem; border-bottom: 1px solid var(--line); font-size: 0.9rem; }
.pl-modal-head code { color: var(--amber); font-size: 0.82rem; }
.pl-modal-x { border: 0; background: transparent; color: var(--muted); font-size: 1.4rem; line-height: 1; cursor: pointer; padding: 0 0.2rem; }
.pl-modal-x:hover { color: var(--text); }
.pl-modal-ta { margin: 0; border: 0; border-radius: 0; resize: none; flex: 1; min-height: 320px;
  background: #101012; color: #d7d7db; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.8rem;
  line-height: 1.5; padding: 0.9rem 1.1rem; outline: none; white-space: pre; overflow: auto; }
.pl-modal-err { color: #e39a9a; font-size: 0.76rem; min-height: 1rem; padding: 0 1.1rem; }
.pl-modal-err:not(:empty) { padding: 0.5rem 1.1rem; }
.pl-modal-foot { display: flex; justify-content: flex-end; gap: 0.6rem; padding: 0.8rem 1.1rem; border-top: 1px solid var(--line); }

/* trader-map editor (reuses .pl-modal shell) */
.pl-modal.trader-map { width: min(760px, 100%); }
.trmap-intro { margin: 0.8rem 1.1rem 0.4rem; }
.trmap-body { flex: 1; overflow: auto; padding: 0.4rem 1.1rem 0.8rem; }
.trmap-rows { display: flex; flex-direction: column; gap: 0.5rem; }
.trmap-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.55rem 0.7rem; border: 1px solid var(--line); border-radius: 8px; background: rgba(255,255,255,0.02); }
.trmap-meta { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; flex: 1; }
.trmap-idline { display: flex; align-items: baseline; gap: 0.7rem; flex-wrap: wrap; }
.trmap-id { color: var(--amber); font-weight: 600; font-size: 0.85rem; }
.trmap-guess { color: var(--muted); font-size: 0.74rem; }
.trmap-funds { color: var(--text); font-size: 0.74rem; font-family: var(--mono); }
.trmap-cur { color: var(--muted); }
/* Sample items wrap over a few lines (an identification aid) instead of truncating to one. */
.trmap-sells { color: var(--muted); font-size: 0.72rem; line-height: 1.4; max-height: 3.6em; overflow-y: auto; }
.trmap-nosell { color: var(--alarm); font-style: italic; }
.trmap-gactions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.trmap-applytypes { padding: 0.32rem 0.6rem; font-size: 0.76rem; border-radius: var(--radius); cursor: pointer; }
.trmap-inputs { display: flex; gap: 0.4rem; flex-shrink: 0; }
/* Match the admin settings-field controls (those styles are scoped to .settings-field, so the modal
   inputs need their own copy or they render as unstyled browser defaults). */
.trmap-type, .trmap-outpost { padding: 0.5rem 0.6rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--inset); color: var(--text); font-family: var(--mono); font-size: 0.9rem; }
.trmap-type { min-width: 150px; font-family: var(--ui); }
.trmap-outpost { min-width: 110px; font-family: var(--ui); }
.trmap-type:focus, .trmap-outpost:focus { outline: none; border-color: var(--amber); box-shadow: var(--focus-ring); }
/* Outpost groups: one card per auto-grouped outpost with a bulk "set all to" sector picker. */
.trmap-group { border: 1px solid var(--line); border-radius: 10px; margin-bottom: 0.8rem; overflow: hidden; }
/* Outpost gold block — same rows as the trader groups, with its own explanatory subtitle. */
.trmap-gold .trmap-ghead { align-items: flex-start; }
.trmap-ghint { flex-basis: 100%; font-size: 0.76rem; color: var(--muted); font-weight: 400; }
.trmap-goldrow .trmap-inputs { justify-content: flex-end; }
.trmap-ghead { display: flex; align-items: center; justify-content: space-between; gap: 0.8rem; flex-wrap: wrap;
  padding: 0.55rem 0.75rem; background: rgba(255, 255, 255, 0.03); border-bottom: 1px solid var(--line); }
.trmap-gtitle { color: var(--amber); font-weight: 700; font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.04em; }
.trmap-gcount { color: var(--muted); font-weight: 400; text-transform: none; }
.trmap-gset { display: flex; align-items: center; gap: 0.4rem; font-size: 0.78rem; color: var(--muted); }
.trmap-gsector { padding: 0.35rem 0.5rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--inset); color: var(--text); font-family: var(--ui); font-size: 0.85rem; }
.trmap-group .trmap-rows { display: flex; flex-direction: column; gap: 0.4rem; padding: 0.6rem 0.75rem; }
.trmap-foot { display: flex; align-items: center; justify-content: flex-end; gap: 0.6rem;
  padding: 0.8rem 1.1rem; border-top: 1px solid var(--line); }
.trmap-msg { margin-right: auto; font-size: 0.8rem; }
.trmap-msg.success { color: var(--online); }
.trmap-msg.error { color: var(--alarm); }
@media (max-width: 640px) {
  .trmap-row { flex-direction: column; align-items: stretch; }
  .trmap-inputs { justify-content: stretch; }
  .trmap-type { flex: 1; }
}

/* readme viewer (rendered HTML) */
.pl-modal.readme { width: min(820px, 100%); }
.pl-readme-body { flex: 1; overflow: auto; padding: 1.1rem 1.3rem; line-height: 1.6; font-size: 0.88rem; color: var(--text); }
.pl-readme-body h1 { font-size: 1.3rem; margin: 0.2rem 0 0.8rem; }
.pl-readme-body h2 { font-size: 1.08rem; margin: 1.4rem 0 0.5rem; padding-bottom: 0.3rem; border-bottom: 1px solid var(--line); }
.pl-readme-body h3 { font-size: 0.96rem; margin: 1.1rem 0 0.4rem; color: var(--amber); }
.pl-readme-body p { margin: 0.5rem 0; }
.pl-readme-body ul, .pl-readme-body ol { margin: 0.5rem 0; padding-left: 1.4rem; }
.pl-readme-body li { margin: 0.25rem 0; }
.pl-readme-body a { color: var(--amber); }
.pl-readme-body code { background: rgba(255,255,255,0.08); padding: 0.08rem 0.34rem; border-radius: 4px; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.84em; }
.pl-readme-body pre { background: #101012; border: 1px solid var(--line); border-radius: 8px; padding: 0.8rem 1rem; overflow: auto; margin: 0.6rem 0; }
.pl-readme-body pre code { background: none; padding: 0; }
.pl-readme-body table { border-collapse: collapse; width: 100%; margin: 0.6rem 0; font-size: 0.84rem; }
.pl-readme-body th, .pl-readme-body td { border: 1px solid var(--line); padding: 0.4rem 0.6rem; text-align: left; vertical-align: top; }
.pl-readme-body th { background: rgba(255,255,255,0.04); }
.pl-readme-body hr { border: 0; border-top: 1px solid var(--line); margin: 1.1rem 0; }
.pl-readme-body blockquote { margin: 0.6rem 0; padding: 0.4rem 0.9rem; border-left: 3px solid var(--amber); color: var(--muted); }

/* ── Overview admin console (SSA Bridge) ──────────────────────────────────── */
.cmd-console h2 { display: flex; align-items: center; gap: 0.5rem; }
/* the console is short, so keep the premium lock card near the top and compact */
.cmd-console .prem-lock-wrap { min-height: 0; }
.cmd-console .prem-lock-overlay { align-items: flex-start; padding: 0.5rem; }
.cmd-console .prem-lock-card { top: 0.4rem; max-width: 420px; padding: 1rem 1.2rem; }
.cmd-console .prem-lock-card .map-lock-ico { width: 26px; height: 26px; margin-bottom: 0.15rem; }
.cmd-console .prem-lock-card h3 { font-size: 0.92rem; margin-bottom: 0.35rem; }
.cmd-console .prem-lock-card p { font-size: 0.8rem; margin-bottom: 0.8rem; }
.cmd-state { margin-left: auto; font-size: 0.72rem; font-weight: 400; color: var(--muted);
  text-transform: none; letter-spacing: 0; border: 1px solid var(--line); border-radius: var(--pill); padding: 0.1rem 0.6rem; }
.cmd-state:empty { display: none; }
.cmd-state.ok { color: #8fe0a8; border-color: rgba(120,220,150,0.45); }
.cmd-state.warn { color: #e6b96a; border-color: rgba(230,185,106,0.45); }
.cmd-state.off { color: #e39a9a; border-color: rgba(220,120,120,0.45); }
.cmd-inner { display: flex; flex-direction: column; gap: 0.9rem; }

/* toolbar (chat-style) */
.cmd-bar { margin-bottom: 0; flex-wrap: wrap; }
.cmd-mode.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.cmd-mode-btn { border: 0; background: var(--inset); color: var(--muted); font-family: var(--ui); font-size: 0.85rem;
  padding: 0.5rem 0.95rem; cursor: pointer; }
.cmd-mode-btn + .cmd-mode-btn { border-left: 1px solid var(--line); }
.cmd-mode-btn.active { background: var(--amber); color: var(--on-amber); font-weight: 600; }
.cmd-inline { display: inline-flex; align-items: center; gap: 0.45rem; }
.cmd-exec-label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); }
.cmd-check { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--muted); font-size: 0.85rem; cursor: pointer; }
.cmd-check input { accent-color: var(--amber); }

.cmd-pane { display: flex; flex-direction: column; gap: 0.7rem; }
.cmd-row { display: flex; gap: 0.6rem; align-items: stretch; flex-wrap: wrap; }
.cmd-search { position: relative; flex: 1; min-width: 12rem; }
.cmd-search input { font-family: var(--mono); }
.cmd-send { display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; white-space: nowrap;
  background: var(--amber); border: 1px solid var(--amber); color: var(--on-amber); font-weight: 600;
  padding: 0.6rem 1.15rem; border-radius: var(--radius); cursor: pointer; }
.cmd-send:hover { filter: brightness(1.08); }
.cmd-send:disabled { opacity: 0.5; cursor: not-allowed; filter: none; }
.cmd-send .ico { width: 15px; height: 15px; }
/* Mobile: never let Send run off the box — the search takes the row, Send wraps to a full-width line below. */
@media (max-width: 640px) {
  .cmd-search { flex: 1 0 100%; min-width: 0; }
  .cmd-send { width: 100%; }
  .cmd-build-foot .cmd-preview { flex: 1 0 100%; }
}
/* The lock / bridge-offline overlay covers the WHOLE console box (header included), not just the inner
   content — so the section is the positioning context and keeps a fixed height while gated, so the
   overlay never spills over the live server log below it. */
.cmd-console { position: relative; }
.cmd-console.locked { min-height: 220px; }
.cmd-console.locked > h2 { opacity: 0; }               /* the overlay's card carries the title instead */
.cmd-console.locked .prem-lock-wrap .cmd-inner { min-height: 160px; }

/* autocomplete dropdown */
.cmd-suggest { position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; right: 0;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  box-shadow: 0 14px 34px rgba(0,0,0,0.45); max-height: 320px; overflow-y: auto; }
.cmd-sg-item { display: flex; align-items: baseline; gap: 0.5rem; padding: 0.5rem 0.75rem; cursor: pointer; }
.cmd-sg-item:hover, .cmd-sg-item.active { background: var(--hover-bg); color: var(--amber-hi); }
.cmd-sg-name { color: var(--amber); font-family: var(--mono); font-size: 0.82rem; }
.cmd-sg-args { color: var(--muted); font-size: 0.74rem; font-family: var(--mono); }
.cmd-sg-desc { color: var(--muted); font-size: 0.74rem; margin-left: auto; text-align: right; max-width: 45%; }
.cmd-sg-arg { gap: 0.55rem; }
.cmd-sg-img { width: 30px; height: 30px; flex: none; object-fit: contain; background: rgba(255,255,255,0.05); border-radius: 4px; }
.cmd-sg-arg .cmd-sg-name { font-family: var(--ui); color: var(--text); }
.cmd-sg-arg .cmd-sg-args { margin-left: auto; }

/* interactive builder */
/* searchable command picker — type-to-filter dropdown, alphabetical */
.cmd-cmdpick { position: relative; flex: 1; display: flex; align-items: center; }
.cmd-cmdpick-ico { position: absolute; left: 0.6rem; width: 15px; height: 15px; color: var(--muted); pointer-events: none; }
.cmd-cmdpick-q { width: 100%; padding: 0.5rem 0.75rem 0.5rem 2rem; background: var(--panel-2); border: 1px solid var(--line);
  color: var(--text); font-family: var(--ui); font-size: 0.85rem; border-radius: var(--radius-md); }
.cmd-cmdpick-q:hover, .cmd-cmdpick-q:focus { border-color: var(--line-amber); outline: none; }
.cmd-cmdpick-list { position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; right: 0;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden;
  box-shadow: 0 14px 34px rgba(0,0,0,0.45); max-height: 340px; overflow-y: auto; }
.cmd-cmdpick-item { display: flex; align-items: baseline; gap: 0.6rem; padding: 0.45rem 0.75rem; cursor: pointer; }
.cmd-cmdpick-item:hover, .cmd-cmdpick-item.active { background: var(--hover-bg); }
.cmd-cmdpick-n { color: var(--amber); font-family: var(--mono); font-size: 0.82rem; }
.cmd-cmdpick-cat { color: var(--muted); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.05em; margin-left: auto; }
.cmd-cmdpick-empty { padding: 0.6rem 0.75rem; color: var(--muted); font-size: 0.8rem; }
.cmd-params { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.7rem; }
.cmd-params:empty { display: none; }
.cmd-field { display: flex; flex-direction: column; gap: 0.3rem; }
.cmd-field label { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.cmd-field .req { color: var(--amber); }
.cmd-field input, .cmd-field select { padding: 0.5rem 0.6rem; font-family: var(--ui); font-size: 0.86rem;
  background: var(--inset); color: var(--text); border: 1px solid var(--line); border-radius: var(--radius); outline: none; }
.cmd-field input:focus, .cmd-field select:focus { border-color: var(--amber); }
.cmd-coords { display: flex; gap: 0.4rem; }
.cmd-coords input { width: 100%; }
.cmd-pick { display: flex; gap: 0.4rem; align-items: center; }
.cmd-pick input { flex: 1; }
.cmd-pick-btn { display: inline-flex; align-items: center; gap: 0.3rem; white-space: nowrap; border: 1px solid var(--line);
  background: var(--inset); color: var(--text); font-size: 0.8rem; padding: 0.45rem 0.7rem; border-radius: var(--radius); cursor: pointer; }
.cmd-pick-btn:hover { border-color: var(--line-amber); }
.cmd-pick-thumb { width: 26px; height: 26px; object-fit: contain; border-radius: 4px; background: rgba(255,255,255,0.05); flex: none; }
.cmd-build-foot { align-items: center; }
.cmd-preview { flex: 1; font-family: var(--mono); font-size: 0.82rem; color: var(--amber); background: var(--inset);
  border: 1px solid var(--line); border-radius: var(--radius); padding: 0.55rem 0.75rem; overflow-x: auto; white-space: nowrap; }
.cmd-preview:empty::before { content: '—'; color: var(--muted); }

/* output log */
.cmd-output { margin: 0; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 0.7rem 0.9rem; min-height: 2.4rem; max-height: 220px; overflow-y: auto;
  font-family: var(--mono); font-size: 0.78rem; line-height: 1.55; color: #cfcfd4;
  white-space: pre-wrap; word-break: break-word; }
.cmd-output:empty { display: none; }
.cmd-out-ok { color: #8fe0a8; }
.cmd-out-err { color: #e39a9a; }
.cmd-out-cmd { color: #e6b96a; }
.cmd-out-res { color: #cfd6e4; padding-left: 1.1rem; }
.cmd-out-note { color: var(--muted); padding-left: 1.1rem; font-style: italic; }
.cmd-out-t { color: var(--muted); }

/* item picker modal (interactive spawn) — reuses .pl-modal-ov shell */
.cmd-ip { width: min(680px, 100%); }
.cmd-ip-search { margin: 0.9rem 1.1rem 0; }
.cmd-ip-filters { display: flex; gap: 0.5rem; margin: 0.6rem 1.1rem 0; }
.cmd-ip-filters select { flex: 1; min-width: 0; padding: 0.4rem 0.5rem; border: 1px solid var(--line);
  border-radius: 7px; background: var(--inset); color: var(--text); font-size: 0.8rem; }
.cmd-ip-filters select:focus { border-color: var(--amber); outline: none; }
.cmd-ip-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.6rem;
  padding: 0.9rem 1.1rem; overflow-y: auto; }
/* Pager sits below the scrolling grid and stays put — the grid scrolls, the controls don't. */
.cmd-ip-pager { flex: none; margin: 0; padding: 0.6rem 1.1rem 0.9rem; border-top: 1px solid var(--line); }
.cmd-ip-card { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; text-align: center;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 0.6rem; cursor: pointer; background: var(--inset); }
.cmd-ip-card:hover { border-color: var(--amber); }
.cmd-ip-card img { width: 56px; height: 56px; object-fit: contain; }
.cmd-ip-ph { width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; color: var(--muted); }
.cmd-ip-ph .ico { width: 30px; height: 30px; }
.cmd-ip-card .n { font-size: 0.74rem; color: var(--text); line-height: 1.25; }
.cmd-ip-card .id { font-size: 0.66rem; color: var(--muted); font-family: var(--mono); word-break: break-all; }

/* count / amount picker (reuses .pl-modal shell) */
.cmd-count { width: min(360px, 100%); }
.cmd-count-body { padding: 1rem 1.1rem 1.2rem; display: flex; flex-direction: column; gap: 0.9rem; }
.cmd-count-chips { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
.cmd-count-chip { border: 1px solid var(--line); background: var(--inset); color: var(--text); font-size: 0.9rem;
  padding: 0.5rem 0; border-radius: 8px; cursor: pointer; font-family: var(--mono); }
.cmd-count-chip:hover { border-color: var(--amber); background: var(--amber); color: var(--on-amber); }
.cmd-count-row { display: flex; align-items: center; gap: 0.6rem; }
.cmd-count-row span { font-size: 0.78rem; color: var(--muted); flex: none; }
.cmd-count-in { flex: 1; padding: 0.45rem 0.6rem; border: 1px solid var(--line); border-radius: 7px;
  background: var(--inset); color: var(--text); font-size: 0.95rem; }
.cmd-count-go { width: 100%; justify-content: center; }

/* ── SSA Bridge admin actions (map info-card + player tools) ───────────────── */
.mp-acts { margin-top: 0.7rem; padding-top: 0.7rem; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; gap: 0.4rem; }
.mp-acts-h { flex-basis: 100%; font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); margin-bottom: 0.1rem; }
.mp-acts-lock .ico { width: 12px; height: 12px; color: var(--amber); vertical-align: middle; }
.mp-act { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.76rem; cursor: pointer;
  border: 1px solid var(--line); background: var(--inset); color: var(--text); padding: 0.35rem 0.6rem; border-radius: 7px; }
.mp-act:hover:not(:disabled) { border-color: var(--amber); background: var(--amber); color: var(--on-amber); }
.mp-act .ico { width: 14px; height: 14px; }
.mp-act.danger { color: #e39a9a; }
.mp-act.danger:hover:not(:disabled) { border-color: #d98a8a; background: #d98a8a; color: #1a0808; }
.mp-act:disabled { opacity: 0.45; cursor: not-allowed; }
.mp-actions-btn { width: 100%; justify-content: center; margin-top: 0.7rem; padding: 0.5rem; font-weight: 600; }
.mp-actions-btn .mp-acts-lock { width: 12px; height: 12px; }
.map-ctx-item:disabled, .map-ctx-item.locked { opacity: 0.45; cursor: not-allowed; }

/* online-player picker (teleport here, …) */
.pp-list { display: flex; flex-direction: column; gap: 0.3rem; padding: 0.8rem 1rem; max-height: 60vh; overflow-y: auto; }
.pp-row { display: flex; align-items: center; gap: 0.5rem; text-align: left; font-size: 0.86rem; cursor: pointer;
  border: 1px solid var(--line); background: var(--inset); color: var(--text); padding: 0.55rem 0.7rem; border-radius: 8px; }
.pp-row:hover { border-color: var(--amber); background: var(--amber); color: var(--on-amber); }
.pp-row .ico { width: 15px; height: 15px; }

/* hierarchical action menu (modal or cursor popover) */
.am-modal { width: min(460px, 100%); }
.am-anchor-ov { position: fixed; inset: 0; z-index: 210; }
.am-pop { position: fixed; width: 264px; max-width: calc(100vw - 16px); background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 16px 44px rgba(0,0,0,0.5); overflow: hidden; }
.am-head { display: flex; align-items: center; gap: 0.4rem; padding: 0.5rem 0.55rem; border-bottom: 1px solid var(--line); }
.am-title { flex: 1; font-size: 0.8rem; color: var(--muted); font-family: var(--mono); }
.am-back, .am-x { border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 1.15rem; line-height: 1; padding: 0 0.35rem; }
.am-back:hover, .am-x:hover { color: var(--text); }
.am-search { margin: 0.5rem 0.5rem 0; }
.am-search input { font-size: 0.84rem; }
.am-list { max-height: min(62vh, 430px); overflow-y: auto; padding: 0.35rem; }
.am-modal .am-list { max-height: min(70vh, 560px); }
.am-item { display: flex; align-items: center; gap: 0.55rem; width: 100%; text-align: left; cursor: pointer;
  border: 0; background: transparent; color: var(--text); padding: 0.55rem 0.6rem; border-radius: 7px; font-size: 0.86rem; }
.am-item:hover:not(:disabled) { background: var(--amber); color: var(--on-amber); }
.am-item:disabled { opacity: 0.45; cursor: not-allowed; }
.am-item .ico { width: 15px; height: 15px; flex: none; }
.am-l { flex: 1; }
.am-arrow { color: var(--muted); font-size: 1rem; }
.am-item:hover:not(:disabled) .am-arrow { color: #4a3a12; }
.am-item.danger { color: #e39a9a; }
.am-item.danger:hover:not(:disabled) { background: #d98a8a; color: #1a0808; }
#map-admin:disabled { opacity: 0.5; cursor: not-allowed; }
.map-updated-badge { position: absolute; right: 8px; top: 8px; z-index: 4; font-size: 0.72rem; font-family: var(--mono);
  color: var(--muted); background: rgba(10, 11, 8, 0.72); border: 1px solid var(--line); border-radius: 6px; padding: 0.15rem 0.5rem; pointer-events: none; }

/* unified action-feedback toast */
.bt-title { font-weight: 600; }
.bt-detail { margin-top: 0.25rem; font-family: var(--mono); font-size: 0.78rem; color: var(--muted); white-space: pre-wrap; max-height: 40vh; overflow-y: auto; }
.bridge-toast.ok .bt-title { color: #8fe0a8; }
.bridge-toast.err .bt-title { color: #f0a8a8; }
.bridge-toast.warn .bt-title { color: #f0cf8a; }

/* transient action toast */
.bridge-toast { position: fixed; left: 50%; bottom: 24px; transform: translate(-50%, 20px); z-index: 300;
  max-width: min(560px, 92vw); padding: 0.7rem 1.1rem; border-radius: 10px; font-size: 0.85rem;
  background: #1b1b1f; color: var(--text); border: 1px solid var(--line); box-shadow: 0 14px 40px rgba(0,0,0,0.5);
  opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s; white-space: pre-wrap; }
.bridge-toast.show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; cursor: pointer; }
.bridge-toast.ok { border-color: rgba(120,220,150,0.5); }
.bridge-toast.err { border-color: rgba(220,120,120,0.55); color: #f0c0c0; }
.bridge-toast.warn { border-color: rgba(230,200,120,0.6); color: #efdcae; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 1 (additive polish)
   Appended last so it LAYERS over the base without touching existing rules.
   Every selector targets ONLY classes/elements that already exist. Nothing is
   renamed, removed or restructured — this is pure visual polish + a11y.
   ════════════════════════════════════════════════════════════════════════ */
:root {
  /* Layered elevation for floating surfaces (subtle — preserves the flat tactical look). */
  --elev-1: 0 1px 2px rgba(0,0,0,0.4);
  --elev-2: 0 8px 24px -8px rgba(0,0,0,0.6), 0 2px 6px rgba(0,0,0,0.45);
  --elev-3: 0 22px 55px -14px rgba(0,0,0,0.72), 0 6px 16px rgba(0,0,0,0.5);
  /* Focus halo — was a 3px amber ring layered on top of a focused field's amber border, which read
     as a DOUBLE border on every text box. Neutralised: focused inputs now show only their single
     amber border, and buttons/links/tabs keep the 2px :focus-visible outline, so nothing loses its
     focus indicator. */
  --ring:   none;
}

/* Modern, consistent focus RING everywhere — keeps the high-contrast outline for
   a11y and adds a soft amber halo so focus reads as deliberate, not a default. */
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
a:focus-visible,
[tabindex]:focus-visible,
.gs-tab:focus-visible,
.anav-btn:focus-visible,
.tab:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 2px;
  box-shadow: var(--ring);
}

/* Button busy/loading affordance — OPT-IN via aria-busy / .loading, so it can
   never affect an existing button unless code sets that state. */
button[aria-busy="true"], button.loading {
  color: transparent !important;
  pointer-events: none;
  position: relative;
}
button[aria-busy="true"]::after, button.loading::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 1em; height: 1em; border-radius: 50%;
  border: 2px solid var(--on-amber); border-top-color: transparent;
  animation: ssa-spin 0.6s linear infinite;
}
button.secondary[aria-busy="true"]::after, button.secondary.loading::after,
button.danger[aria-busy="true"]::after, button.danger.loading::after { border-color: currentColor; border-top-color: transparent; }
@keyframes ssa-spin { to { transform: rotate(360deg); } }

/* Real elevation on floating surfaces — the Grafana/Proxmox "layer that lifts". */
.amodal-box { box-shadow: var(--elev-3); }
.cdd-menu, .roster-country-menu, .lang-dd-list { box-shadow: var(--elev-2); }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 2 — navigation interactivity
   Additive only; targets confirmed classes (.admin-nav / .anav-btn). The tab
   nav previously changed only text colour on hover — add a subtle hover fill +
   a faint underline hint + smooth transitions so tabs read as interactive
   (GitHub/Grafana style). Active tab stays amber, unchanged.
   ════════════════════════════════════════════════════════════════════════ */
.admin-nav { scrollbar-width: thin; scrollbar-color: var(--line-amber) transparent; }
.anav-btn {
  transition: color .14s ease, background .14s ease, border-color .14s ease;
  border-top-left-radius: var(--radius); border-top-right-radius: var(--radius);
}
.anav-btn:hover:not(.active) {
  color: var(--text);
  background: var(--hover-bg);
  border-bottom-color: var(--line-amber);
}

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 3 — data tables (roster & co.)
   Additive; targets the existing .roster-table. Adds a readable header, a clear
   row-hover surface (rows are clickable → open a player), and a whisper-subtle
   zebra for scannability. No columns/markup/behaviour touched.
   ════════════════════════════════════════════════════════════════════════ */
.roster-table thead th {
  background: var(--bg-2);
  color: var(--muted);
  border-bottom: 1px solid var(--line-amber);
  position: sticky; top: 0; z-index: 1;
}
.roster-table tbody tr { transition: background .12s ease; }
.roster-table tbody tr:nth-child(even) { background: rgba(255,255,255,0.014); }
.roster-table tbody tr:hover { background: var(--hover-bg); }
/* keep the action button readable on a hovered row */
.roster-table tbody tr:hover .rr-admin-btn { border-color: var(--line-amber); }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 4 — form-field clarity
   The settings inputs sat on --inset (≈ page black) with a 9% border, so they
   barely read as editable. Lift them with a whisper of fill + a clearer border
   + a hover cue + the modern focus halo. Same selectors as the base rule, so it
   overrides by source order; behaviour/markup untouched. Helps every settings
   screen AND the setup wizard read as "these are fields you can edit".
   ════════════════════════════════════════════════════════════════════════ */
:root { --input-bg: rgba(255,255,255,0.025); --input-line: rgba(228,226,214,0.18); }
.settings-field input[type="text"],
.settings-field input[type="number"],
.settings-field input[type="password"],
.settings-field textarea,
.settings-field select,
.setup-box .settings-field input {
  background: var(--input-bg);
  border-color: var(--input-line);
  transition: border-color .14s ease, box-shadow .14s ease, background .14s ease;
}
.settings-field input:hover:not(:focus),
.settings-field textarea:hover:not(:focus),
.settings-field select:hover:not(:focus),
.setup-box .settings-field input:hover:not(:focus) { border-color: var(--line-amber); }
.settings-field input:focus,
.settings-field textarea:focus,
.settings-field select:focus,
.setup-box .settings-field input:focus,
.login-box input:focus { border-color: var(--amber); box-shadow: var(--ring); outline: none; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 5 — modals & empty/loading/error states
   Additive; targets confirmed classes only. (a) Modal: dim+blur the backdrop so
   the dialog is the clear focus, and give the header (.amodal-box h2) a hairline
   divider so title/body read as distinct zones. (b) Empty/loading/error
   placeholders (.pl-empty / .rc-empty / .cmd-cmdpick-empty) get one consistent,
   calm, centred treatment instead of three slightly different looks. No markup,
   copy, sizing or behaviour touched.
   ════════════════════════════════════════════════════════════════════════ */
.amodal { background: rgba(0,0,0,0.62); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.amodal-box h2 {
  padding-bottom: 0.7rem;
  margin-bottom: 0.9rem;
  border-bottom: 1px solid var(--line);
  letter-spacing: 0.01em;
}
/* consistent, quiet placeholder for the three empty/loading/error slots */
.pl-empty, .rc-empty, .cmd-cmdpick-empty {
  color: var(--muted);
  text-align: center;
  letter-spacing: 0.01em;
}
.pl-empty { min-height: 4.5rem; display: flex; align-items: center; justify-content: center; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 6 — interactive card affordance
   The plugin cards already DECLARE a border/shadow transition but never had a
   :hover target, so they sat inert. Give them (and the clickable squad-member
   chips in the player detail) a real hover: amber-hinted border + a whisper of
   lift — the "cards that respond" feel. Purely visual; .pl-card.on already owns
   the amber border for active plugins, so this just adds the shadow on hover.
   ════════════════════════════════════════════════════════════════════════ */
.pl-card:hover { border-color: var(--line-amber); box-shadow: var(--elev-1); }
.pd-member { transition: border-color .14s ease, background .14s ease; }
.pd-member:hover { border-color: var(--line-amber); background: var(--hover-bg); }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 7 — cohesive themed scrollbars
   The one un-themed element left across the whole panel was the default chunky
   grey OS scrollbar (visible on the page, modals, textareas, the roster wrapper,
   dropdowns). Give every scroll area a thin, dark, amber-on-hover scrollbar so
   scrolling reads as part of the same tactical surface — the Grafana/Proxmox
   "custom scrollbars everywhere" cohesion. Firefox via scrollbar-*, Chrome (the
   primary target) via ::-webkit-scrollbar. Purely cosmetic; .admin-nav keeps its
   own amber track (more specific rule wins).
   ════════════════════════════════════════════════════════════════════════ */
* { scrollbar-width: thin; scrollbar-color: rgba(228,226,214,0.22) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(228,226,214,0.16);
  border-radius: 6px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
  background: rgba(240,130,12,0.5);
  background-clip: padding-box;
}
::-webkit-scrollbar-corner { background: transparent; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 8 — mobile header menu (hamburger)
   On phones/small tablets the header's manager buttons (Update/Restart/Shutdown
   + language + Field Console + Logout) wrapped onto multiple rows and ate a lot
   of vertical space. Collapse them behind a hamburger that opens a proper drawer
   under the header. Desktop is 100% unchanged (the hamburger is display:none and
   .header-actions keeps its normal inline flex row). Wired by a tiny isolated
   inline script (toggles header.menu-open); markup added: #mobile-menu-btn + an
   id on the existing .header-actions. No app.js/API/behaviour touched — the same
   buttons, just relocated into a drawer on small screens.
   ════════════════════════════════════════════════════════════════════════ */
.mobile-menu-btn { display: none; }              /* desktop: hidden */
.mobile-menu-btn .ico { width: 22px; height: 22px; }
.mobile-menu-btn .mm-close { display: none; }    /* show X only when open */

@media (max-width: 760px) {
  /* brand + hamburger share one row; the actions drop into an absolute drawer */
  header { flex-wrap: nowrap; position: relative; }
  .mobile-menu-btn {
    display: inline-flex; align-items: center; justify-content: center;
    flex: 0 0 auto; padding: 0.5rem; width: 42px; height: 42px;
  }
  header.menu-open .mobile-menu-btn { border-color: var(--line-amber); color: var(--amber-hi); }
  header.menu-open .mobile-menu-btn .mm-open { display: none; }
  header.menu-open .mobile-menu-btn .mm-close { display: inline-flex; }

  .header-actions {
    display: none;                 /* closed by default */
    position: absolute;
    top: calc(100% + 6px);
    right: 0.75rem; left: 0.75rem;
    flex-direction: column;
    align-items: stretch;
    gap: 0.45rem;
    padding: 0.7rem;
    background: var(--panel);
    border: 1px solid var(--line-amber);
    border-radius: var(--radius);
    box-shadow: var(--elev-3);
    z-index: 200;
  }
  header.menu-open .header-actions { display: flex; animation: modalIn 0.16s ease; }
  .header-actions > button,
  .header-actions > a.secondary {
    width: 100%; justify-content: flex-start;
    padding-top: 0.6rem; padding-bottom: 0.6rem;
  }
  /* the thin vertical divider becomes a horizontal rule when stacked */
  .header-actions .header-sep { width: 100%; height: 1px; align-self: auto; margin: 0.2rem 0; }
  /* language picker + its trigger fill the drawer width */
  #admin-lang-wrap, #admin-lang-wrap .cdd, #admin-lang-wrap .cdd-btn,
  #admin-lang-wrap .lang-dd, #admin-lang-wrap .lang-dd-btn { width: 100%; }
}

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 9 — styled toast notifications
   Replaces the ugly native browser alert() (the "Windows/Google" bar at the top
   of the page) with an on-brand toast that stacks top-right. Wired by overriding
   window.alert in the isolated inline script — every existing alert() call site
   is unchanged, they just render as a proper toast now. Error-ish messages get a
   red rail, notices get the amber rail. z-index above modals/dropdowns.
   ════════════════════════════════════════════════════════════════════════ */
.ssa-toast-wrap {
  position: fixed; top: 1rem; right: 1rem; z-index: 4000;
  display: flex; flex-direction: column; gap: 0.5rem;
  width: min(380px, calc(100vw - 2rem));
  pointer-events: none;
}
.ssa-toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: 0.6rem;
  background: var(--panel);
  border: 1px solid var(--line-amber);
  border-left: 3px solid var(--amber);
  border-radius: var(--radius);
  padding: 0.7rem 0.8rem;
  box-shadow: var(--elev-3);
  color: var(--text); font-size: 0.88rem; line-height: 1.45;
  animation: ssaToastIn 0.2s ease;
}
.ssa-toast.err { border-left-color: var(--alarm); }
.ssa-toast.err .ssa-toast-ic { color: var(--alarm); }
.ssa-toast.ok { border-left-color: var(--online); }
.ssa-toast.ok .ssa-toast-ic { color: var(--online); }
.ssa-toast-ic { flex: 0 0 auto; width: 18px; height: 18px; color: var(--amber); margin-top: 1px; }
.ssa-toast-msg { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; white-space: pre-wrap; }
.ssa-toast-x {
  flex: 0 0 auto; background: none; border: 0; color: var(--muted);
  cursor: pointer; font-size: 1.1rem; line-height: 1; padding: 0 0.1rem;
}
.ssa-toast-x:hover { color: var(--text); }
.ssa-toast.hide { animation: ssaToastOut 0.2s ease forwards; }
@keyframes ssaToastIn { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }
@keyframes ssaToastOut { to { opacity: 0; transform: translateX(18px); } }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 10 — Live Map marker hover
   The marker hover was a single hard 2px outline sitting right on the dot edge,
   with no transition — barely legible against the busy map and abrupt. Give it a
   floating ring (outline-offset) + a soft amber glow halo + a smooth transition,
   and a slightly larger hover hit-area, so a hovered marker clearly "lifts" off
   the map. Colours/positions/behaviour otherwise unchanged.
   ════════════════════════════════════════════════════════════════════════ */
.map-mk .mk-dot { transition: box-shadow .12s ease; }
.map-mk .mk-dot::before { inset: -10px; }            /* a touch more forgiving hover target */
.map-mk:hover, .map-mk.mk-selected { z-index: 6; }
/* Tight amber ring HUGGING the icon (no gap) + soft glow. !important so it wins over
   the per-status green/red rings (which have higher specificity). Applies on hover AND
   while selected — the clicked marker stays lit so you can see what the open popover is for. */
.map-mk:hover .mk-dot,
.map-mk.mk-selected .mk-dot {
  outline: none !important;
  box-shadow: 0 0 0 2px var(--amber-hi), 0 0 9px 2px rgba(240,130,12,0.6), 0 1px 4px rgba(0,0,0,0.7) !important;
}
/* keep the selected marker's name label visible while its popover is open */
.map-mk.mk-selected .mk-label { display: block; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 11 — Live Map LEFT SIDEBAR polish
   The layer cards + entity-list rows hovered to a flat, washed grey
   (rgba(255,255,255,.06)) with no accent — off-identity and bland against the
   amber tactical panel. Give every interactive sidebar row a crisp on-brand
   hover: an inset amber left-rail + the name going amber-hi + a smooth
   transition, so hovering reads clearly and matches the rest of the panel.
   Colours/counts/behaviour otherwise unchanged.
   ════════════════════════════════════════════════════════════════════════ */
.map-layer, .ml-row, .map-filters-head, .ml-sec-h {
  transition: background .12s ease, box-shadow .12s ease, color .12s ease;
}
.map-layer:hover, .ml-row:hover {
  background: var(--hover-bg);
  box-shadow: inset 2px 0 0 var(--amber);
}
.ml-row:hover .mlr-name { color: var(--amber-hi); }
.map-layer:hover .ml-name { color: var(--amber-hi); }
.map-filters-head:hover { color: var(--amber-hi); }
.map-filters-head:hover .ico { color: var(--amber-hi); }
/* offline rows still get the amber name on hover (override the muted default) */
.ml-row.off:hover .mlr-name { color: var(--amber); }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 12 — dropdown hover + collapsible map lists
   (a) .cdd-item hover was amber TEXT on a barely-lighter grey → low contrast,
   reads as muddy/"dark". Make it a clear solid-amber highlight bar with dark
   text, like a proper dropdown selection. Applies to every custom dropdown
   (map layer sub-filters, language, executor, country…) for consistency.
   (b) Live Map entity lists (Players/Vehicles/Chests/Storage/Bases) become
   collapsible by clicking their section header — same affordance as the
   "Layers & filters" panel. Chevron + hidden rows when collapsed; wired by the
   isolated inline script (state survives the map's periodic re-render).
   ════════════════════════════════════════════════════════════════════════ */
.cdd-item:hover, .rc-item:hover {
  background: var(--amber);
  color: var(--on-amber);
}

/* collapsible entity-list sections */
.ml-sec-h { cursor: pointer; user-select: none; }
.ml-sec-h::after {
  content: '▾'; display: inline-block; flex: none;
  margin-left: 0.5rem; color: var(--muted); font-size: 0.7rem;
  transition: transform .15s ease, color .12s ease;
}
.ml-sec-h:hover { color: var(--amber-hi); }
.ml-sec-h:hover::after, .ml-sec-h:hover .ico { color: var(--amber-hi); }
.ml-sec-h .ml-sec-n { margin-left: auto; }        /* keep count pinned right, chevron after it */
.ml-sec.collapsed .ml-sec-h::after { transform: rotate(-90deg); }
.ml-sec.collapsed .ml-row,
.ml-sec.collapsed .ml-empty { display: none; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 13 — custom-dropdown TRIGGER hover fix
   The global `button:hover` (amber bg + dark on-amber text) was hijacking the
   .cdd-btn dropdown triggers (e.g. the map layer "All (85)"). Context rules like
   `.map-layers .cdd-btn{background:panel-2}` kept the bg DARK but the dark text
   from button:hover still applied → dark-on-dark, unreadable on mere hover.
   Give .cdd triggers a proper dropdown hover instead: keep the dark surface,
   light label, amber border + amber caret as the cue. Fixes every custom
   dropdown trigger (map filters, language, executor, country…).
   ════════════════════════════════════════════════════════════════════════ */
.cdd-btn:hover {
  background: var(--panel-2);
  border-color: var(--line-amber);
  color: var(--text);
}
.cdd-btn:hover .dd-caret,
.cdd-btn:hover .cdd-lbl { color: var(--amber-hi); }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 14 — styled confirm / prompt dialogs
   Replaces the native browser confirm()/prompt() (the "ugly window" on header
   Restart/Shutdown and the player admin actions) with an on-brand modal. Driven
   by window.ssaConfirm()/ssaPrompt() (Promise-based) in the inline script; the
   app.js call sites are converted to `await` these. Reuses the existing button
   system (primary / .danger / .secondary) so it matches everything else.
   ════════════════════════════════════════════════════════════════════════ */
.ssa-dialog-back {
  position: fixed; inset: 0; z-index: 5000;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,0.62); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  padding: 1rem;
}
.ssa-dialog {
  width: min(440px, 100%);
  background: var(--panel); border: 1px solid var(--line-amber); border-radius: var(--radius);
  box-shadow: var(--elev-3); padding: 1.3rem 1.4rem; animation: modalIn 0.18s ease;
}
.ssa-dialog h3 {
  margin: 0 0 0.8rem; font-size: 1.05rem; color: var(--text); letter-spacing: 0.01em;
  padding-bottom: 0.7rem; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 0.5rem;
}
.ssa-dialog h3 .ico { width: 18px; height: 18px; color: var(--amber); flex: none; }
.ssa-dialog.danger h3 .ico { color: var(--alarm); }
.ssa-dialog-msg { margin: 0 0 1rem; color: var(--text); font-size: 0.9rem; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
.ssa-dialog-input {
  width: 100%; margin: 0 0 1rem; padding: 0.55rem 0.7rem; box-sizing: border-box;
  background: var(--input-bg, rgba(255,255,255,0.025)); border: 1px solid var(--input-line, rgba(228,226,214,0.18));
  border-radius: var(--radius); color: var(--text); font-family: var(--ui); font-size: 0.9rem;
}
.ssa-dialog-input:focus { border-color: var(--amber); box-shadow: var(--ring); outline: none; }
.ssa-dialog-btns { display: flex; justify-content: flex-end; gap: 0.5rem; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 15 — Plugins: search + restart clarity
   Adds a compact search box to the Plugins toolbar (reuses .player-search) and
   turns the section note into a scannable "what to restart" callout so it's
   obvious that UE4SS mods apply on a SERVER restart while manager plugins apply
   instantly (and why a just-disabled mod can still read as online).
   ════════════════════════════════════════════════════════════════════════ */
/* In the toolbar the search must not devour the row like it does on the roster
   bar — cap it, and let it collapse to full width only when the bar wraps. */
.pl-search { flex: 0 1 220px; min-width: 150px; padding: 0.4rem 0.6rem; transition: border-color 0.12s ease, box-shadow 0.12s ease; }
.pl-search input { font-size: 0.9rem; }
/* Focus the whole search pill — not the inner <input>. The global input:focus-visible rule
   otherwise paints a second amber frame INSIDE the pill (2px outline + a 3px --ring box-shadow
   halo) on top of the pill's own amber border — a double border. Kill BOTH on the inner input so
   only the single pill border shows. Applies to every .player-search box. */
.player-search:focus-within { border-color: var(--amber); box-shadow: var(--focus-ring); }
.player-search input:focus-visible { outline: none; box-shadow: none; }
/* The restart-guidance note reads as a proper callout box, not a bare rule. */
.pl-note {
  background: rgba(240, 130, 12, 0.06);
  border: 1px solid var(--line);
  border-left: 3px solid var(--amber);
  border-radius: var(--radius);
  padding: 0.75rem 0.95rem;
  line-height: 1.6;
}
.pl-note b { color: var(--text); font-weight: 600; }
@media (max-width: 720px) { .pl-search { flex-basis: 100%; } }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 17 — click-to-sort table headers
   Column headers on the Players / Chat / Game-log tables sort by that column
   (replacing the old "Sort" dropdowns). A faint ↕ marks a sortable column; the
   active one shows an amber ▲/▼.
   ════════════════════════════════════════════════════════════════════════ */
.data-table th.th-sort { cursor: pointer; user-select: none; transition: color 0.12s ease, background 0.12s ease; }
.th-sort .th-sort-in { display: inline-flex; align-items: center; gap: 0.3rem; }
.th-sort .th-arrow { font-size: 0.74em; line-height: 1; color: var(--amber); }
.data-table th.th-sort:not(.active) .th-arrow::after { content: '↕'; color: var(--muted); opacity: 0.4; }
.data-table th.th-sort:hover { color: var(--text); background: rgba(240, 130, 12, 0.06); }
.data-table th.th-sort:not(.active):hover .th-arrow::after { opacity: 0.75; }
.data-table th.th-sort.active { color: var(--amber-hi, var(--amber)); }
.data-table th.th-sort:focus-visible { outline: 2px solid var(--amber); outline-offset: -2px; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 18 — stable table columns
   Fixed layout so column widths stay put across sorting and paging (auto layout
   re-measured each page's content, which made columns jump/resize). Long cells
   truncate with an ellipsis; message/log cells wrap. Widths are scoped per table
   (roster / chat / game-log all share the .roster-table class).
   ════════════════════════════════════════════════════════════════════════ */
.data-table.roster-table { table-layout: fixed; width: 100%; }
.roster-table td { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.roster-table th { overflow: hidden; text-overflow: ellipsis; }
.roster-table td.chat-msg, .roster-table td.gamelog-line { white-space: normal; overflow: visible; text-overflow: clip; }

/* Players — widths by CLASS, never :nth-child. The old rules were positional, so each column kept
   the width of whatever used to sit in its slot once columns were inserted; that is how a
   three-digit ID ended up claiming 18% of the table.
   The layout is `fixed`, so content does not size anything: EVERY column must state a width, or it
   collapses to nothing while the rest divide the space up between them. The numbers below were
   measured in a browser against this server's real roster (longest name, longest squad, 17-digit
   Steam IDs, six-figure balances) rather than estimated. Squad / Discord / Name are the ones
   allowed to ellipsis — everything else fits its widest real value.
   Percentages, NOT rem: the panel scales its root font size (1rem measures ~19.8px here, not 16),
   so rem widths came out about a quarter too wide and pushed the table into a scrollbar. A
   percentage resolves against the table itself and is immune to that. */
/* Tighter cells than the other tables: at 0.7rem a side, padding alone ate 392px of a 1400px table
   across 14 columns — a quarter of the width before a single value was drawn. */
.roster-table:not(.chat-table) th,
.roster-table:not(.chat-table) td { padding-left: 0.45rem; padding-right: 0.45rem; }

.roster-table:not(.chat-table) th.rr-status-h { width: 1.9%; }   /* just a dot */
.roster-table:not(.chat-table) th.c-name     { width: 12.6%; }
.roster-table:not(.chat-table) th.c-uid      { width: 3.2%; }    /* in-game id: a few digits */
.roster-table:not(.chat-table) th.c-steam    { width: 12.1%; }   /* 17 digits, monospace — must not clip */
.roster-table:not(.chat-table) th.c-playtime { width: 7.1%; }
.roster-table:not(.chat-table) th.c-fame     { width: 4.9%; }
.roster-table:not(.chat-table) th.c-money    { width: 5.8%; }    /* "163,314" */
.roster-table:not(.chat-table) th.c-gold     { width: 4.9%; }
.roster-table:not(.chat-table) th.c-squad    { width: 7.9%; }    /* long names ellipsis */
.roster-table:not(.chat-table) th.c-ip       { width: 10.9%; }
.roster-table:not(.chat-table) th.c-discord  { width: 7.1%; }    /* long names ellipsis */
/* The admin-actions button inherits the generic button padding (~21px a side), which made it 44px
   wide inside a 41px cell — it overflowed and read as shoved off to the right. It is an icon
   button; size it like one. */
.roster-table td.rr-act .rr-admin-btn { padding: 0.25rem 0.35rem; min-width: 0; }
/* That cell holds a button, not text — the shared ellipsis rule was appending dots next to it. */
.roster-table td.rr-act { overflow: visible; text-overflow: clip; }
.roster-table:not(.chat-table) th.c-login    { width: 8.1%; }
.roster-table:not(.chat-table) th.c-logout   { width: 9.2%; }
.roster-table:not(.chat-table) th.rr-act-h   { width: 2.9%; }

/* Chat — 4 columns (Time, Channel, Player, Message) */
.chat-table:not(.gamelog-table) th:nth-child(1) { width: 11.5rem; }
.chat-table:not(.gamelog-table) th:nth-child(2) { width: 6.5rem; }
.chat-table:not(.gamelog-table) th:nth-child(3) { width: 18%; }

/* Game log — 3 columns (Time, Category, Log entry). Fit Time to its content (the full timestamp is
   only ~150px wide) and trim the oversized right padding, so Category sits right next to it instead
   of after a dead gap; the log entry then gets all the remaining room. */
.gamelog-table th:nth-child(1), .gamelog-table td:nth-child(1) { width: 174px; white-space: nowrap; padding-right: 0.35rem; }
.gamelog-table th:nth-child(2) { width: 8rem; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 19 — Log Viewer: raw-line reveal
   A per-entry "raw" toggle reveals the ORIGINAL log line (nothing is lost when
   the enriched view folds coordinates/blobs away), plus styling for the session
   picker. Used in the Log Viewer and the player card's Logs tab.
   ════════════════════════════════════════════════════════════════════════ */
.gl-raw-btn {
  font: inherit; font-size: 0.72em; cursor: pointer; margin-left: 0.4rem; vertical-align: middle;
  padding: 0.05rem 0.4rem; border-radius: 4px;
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.gl-raw-btn:hover, .gl-raw-btn.on { border-color: var(--line-amber); color: var(--amber); }
.gl-raw {
  margin-top: 0.35rem; padding: 0.45rem 0.6rem;
  background: #101012; border: 1px solid var(--line); border-radius: 6px;
  font-family: var(--mono); font-size: 0.8rem; color: var(--muted);
  white-space: pre-wrap; word-break: break-word;
}
/* Player card → Logs tab: a compact filter bar + a scrollable list, matching the Log Viewer. */
.pd-logs-body { min-height: 4rem; }
.pdl-bar { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.6rem; flex-wrap: wrap; }
.pdl-bar .pdl-search-wrap { flex: 1 1 180px; min-width: 140px; }
.pdl-bar .pdl-count { margin-left: auto; color: var(--muted); font-size: 0.82rem; white-space: nowrap; }
.pdl-list { max-height: 46vh; overflow: auto; }
.pdl-list .table-wrap { margin-top: 0; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 20 — Log Viewer: entity icons + item
   preview. Small SVG markers show WHAT each clickable thing is (user / location
   / weapon / box / vehicle) without recolouring the line, and item/vehicle codes
   open a game-DB preview (icon + name). Also fixes the player-card Logs table so
   its time column isn't collapsed.
   ════════════════════════════════════════════════════════════════════════ */
.gl-ic { width: 0.95em; height: 0.95em; vertical-align: -0.14em; margin-right: 0.22rem; color: var(--muted); opacity: 0.7; flex: none; }
.gl-player:hover .gl-ic, .gl-loc:hover .gl-ic, .gl-item:hover .gl-ic { color: var(--amber); opacity: 1; }
/* clickable item/vehicle/weapon code → dashed underline (distinct from players' solid) */
.gl-item { color: inherit; cursor: pointer; text-decoration: underline dashed; text-decoration-color: rgba(240, 130, 12, 0.4); text-underline-offset: 2px; }
.gl-item:hover { color: var(--amber-hi); text-decoration-color: var(--amber); }
/* item preview popover */
.gl-preview { position: absolute; z-index: 5000; max-width: 250px; padding: 0.6rem 0.7rem;
  background: var(--panel); border: 1px solid var(--line-amber); border-radius: 8px; box-shadow: var(--elev-3); }
.gl-preview-body { display: flex; gap: 0.65rem; align-items: center; }
.gl-preview img { width: 56px; height: 56px; object-fit: contain; background: var(--inset); border-radius: 6px; flex: none; }
.gl-preview-t { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.gl-preview-t b { color: var(--text); font-size: 0.9rem; }
.gl-preview-t .mono { font-size: 0.72rem; word-break: break-all; }
/* player-card Logs tab: content-sized columns so the time isn't crushed to 10px */
.pdl-list .data-table { table-layout: auto; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 21 — Log Viewer + player modal polish
   Fixes: icons were too dark to see; Steam IDs rendered a size smaller than the
   rest of the line; the item preview was cramped/dark; the player modal was
   tight for reading the Logs tab.
   ════════════════════════════════════════════════════════════════════════ */
/* Entity icons — bright enough to read, on-brand amber; shape signals the type. */
.gl-ic { width: 0.92em; height: 0.92em; vertical-align: -0.13em; margin-right: 0.26rem; color: var(--amber); opacity: 0.95; flex: none; }
/* a touch more breathing room between log rows so the icons + text don't feel cramped */
.gamelog-line { padding-top: 0.5rem; padding-bottom: 0.5rem; line-height: 1.5; }
.gl-player:hover .gl-ic, .gl-loc:hover .gl-ic, .gl-item:hover .gl-ic { color: var(--amber-hi); opacity: 1; }
/* One consistent type size across the whole log line — no shrunk Steam IDs. */
.gamelog-line, .gamelog-line a, .gamelog-line .gl-sid { font-size: 0.85rem; }
.gl-sid { font-size: inherit; }
/* Item preview — larger image on a light plate, clearer text. */
.gl-preview { max-width: 290px; padding: 0.85rem 0.9rem; }
.gl-preview-body { gap: 0.85rem; }
.gl-preview img { width: 84px; height: 84px; padding: 5px; background: rgba(255, 255, 255, 0.07); border: 1px solid var(--line); }
.gl-preview-t b { font-size: 1rem; line-height: 1.2; }
.gl-preview-t .mono { font-size: 0.74rem; }
/* Player modal — bigger, and the Logs list gets real room to read. */
.amodal.wide .amodal-box { max-width: 1120px; max-height: 92vh; }
.pdl-list { max-height: 58vh; }
.pdl-bar { margin-bottom: 0.7rem; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 22 — Log Viewer: per-type category chip
   Every row's category chip carries its log-type icon (skull=kills, coins=economy,
   shield=raid, car=vehicles, lock=bunkers…) + a friendly label / sub-category, so
   each category reads at a glance in the viewer and the player card's Logs tab.
   ════════════════════════════════════════════════════════════════════════ */
.gl-cat { display: inline-flex; align-items: center; gap: 0.3rem; max-width: 100%; vertical-align: middle; }
.gl-type-ic { width: 0.95em; height: 0.95em; flex: none; color: currentColor; opacity: 0.9; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 23 — Log Viewer: category never overflows
   The category column is a fixed 9rem; long tags (VehicleInactiveTimerReached,
   OutOfInteractionRange…) must ellipsize inside the pill, not spill into the entry
   column. Full text stays available via the cell's title tooltip.
   ════════════════════════════════════════════════════════════════════════ */
.gamelog-table td:nth-child(2), .pdl-list .data-table td:nth-child(1) { overflow: hidden; }
.gl-cat-t { display: inline-block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
/* Unify category casing — every tag reads with a capital first letter (login → Login,
   out of range → Out of range) while leaving command / UE-category camel case intact. */
.gl-cat-t::first-letter { text-transform: uppercase; }
/* The player-card Logs table is auto-layout, so cap its category so a long label
   ("Vehicle Destruction") can't crowd out the message. */
.pdl-list .data-table td:nth-child(1) { max-width: 12rem; }

/* ════════════════════════════════════════════════════════════════════════
   DESIGN-SYSTEM REFINEMENTS · increment 24 — Live Map: location ping
   Clicking a log location opens the map centred on the spot AND drops a pulsing
   pin there, so the admin sees exactly where the event happened. Lives inside the
   transformed #map-canvas and counter-scales (--mz) so it stays a constant size.
   ════════════════════════════════════════════════════════════════════════ */
.map-ping { position: absolute; z-index: 30; pointer-events: none; }
.map-ping.hidden { display: none; }
/* Bold target marker centred ON the spot: a bright ring + an X, with a dark halo so it reads on any
   terrain, plus an expanding pulse to catch the eye. All three counter-scale (--mz) to a constant
   on-screen size regardless of map zoom. */
.map-ping-ring, .map-ping-x, .map-ping-pulse {
  position: absolute; left: 0; top: 0; transform-origin: center;
}
.map-ping-ring {
  width: 38px; height: 38px; border-radius: 50%;
  border: 3px solid var(--amber-hi); background: rgba(240, 130, 12, 0.14);
  transform: translate(-50%, -50%) scale(var(--mz, 1));
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.75), 0 0 10px 2px rgba(240, 130, 12, 0.55), inset 0 0 6px rgba(0, 0, 0, 0.5);
}
.map-ping-x { width: 20px; height: 20px; transform: translate(-50%, -50%) scale(var(--mz, 1)); }
.map-ping-x::before, .map-ping-x::after {
  content: ''; position: absolute; left: 50%; top: 0; width: 3px; height: 100%;
  background: var(--amber-hi); border-radius: 2px;
  box-shadow: 0 0 0 1.5px rgba(0, 0, 0, 0.7);
}
.map-ping-x::before { transform: translateX(-50%) rotate(45deg); }
.map-ping-x::after { transform: translateX(-50%) rotate(-45deg); }
.map-ping-pulse {
  width: 38px; height: 38px; border-radius: 50%;
  transform: translate(-50%, -50%) scale(var(--mz, 1));
}
.map-ping.ping-anim .map-ping-pulse { animation: mapPingPulse 1.5s ease-out infinite; }
.map-ping.ping-anim .map-ping-ring { animation: mapPingPop 0.4s cubic-bezier(0.2, 0.8, 0.3, 1.5); }
@keyframes mapPingPulse {
  0% { box-shadow: 0 0 0 0 rgba(240, 130, 12, 0.55); }
  70% { box-shadow: 0 0 0 calc(26px * var(--mz, 1)) rgba(240, 130, 12, 0); }
  100% { box-shadow: 0 0 0 0 rgba(240, 130, 12, 0); }
}
@keyframes mapPingPop {
  0% { transform: translate(-50%, -50%) scale(calc(var(--mz, 1) * 2.2)); opacity: 0; }
  100% { transform: translate(-50%, -50%) scale(var(--mz, 1)); opacity: 1; }
}

/* Numbered pages in the native table pager (same shape as the Field Console). */
.roster-pager-nums { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.roster-pager .pg-n { min-width: 2rem; padding: .3rem .5rem; font-variant-numeric: tabular-nums; }
.roster-pager .pg-n.cur { border-color: var(--accent, var(--amber, #ff6a1a)); color: var(--accent, var(--amber, #ff6a1a)); cursor: default; }
.roster-pager-gap { color: var(--muted, #8b9099); padding: 0 2px; user-select: none; }

/* Table pagination on a phone: drop the outer page numbers, keep Prev/Next, first, last and the
   pages next to the current one. The row also wraps instead of pushing the table sideways. */
.roster-pager { flex-wrap: wrap; }
@media (max-width: 560px) {
  .roster-pager .pg-far { display: none; }
  .roster-pager .pg-n { min-width: 1.8rem; padding: .3rem .4rem; }
}

/* Fullscreen: the whole widget, side panel included. `position: fixed` covers the browser
   window when the Fullscreen API is unavailable; under the real API the element already fills
   the screen and these values are harmless.

   The panel and the viewport are sized `height: 72vh` for the normal in-page layout — which in
   fullscreen left the bottom ~28% of the screen empty black. Both have to be released to 100%
   of the (now full-screen) wrapper, and `height`, not `max-height`, is what actually pins them. */
.map-wrap.map-fs {
  position: fixed; inset: 0; z-index: 4000; width: 100vw; height: 100vh; max-height: none;
  border-radius: 0; margin: 0;
}
.map-wrap:fullscreen { width: 100vw; height: 100vh; max-height: none; border-radius: 0; margin: 0; }
.map-wrap.map-fs .map-side, .map-wrap:fullscreen .map-side,
.map-wrap.map-fs .map-viewport, .map-wrap:fullscreen .map-viewport {
  height: 100%; max-height: none; min-height: 0;
}
.map-fs-b .ico { width: 14px; height: 14px; }

/* ── roster: numeric columns + in-game id ────────────────────────────────────
   Playtime / Fame / Money / Gold read as a column of figures, so they are right-aligned with
   tabular numerals — proportional digits make columns of numbers impossible to compare. */
.roster-table td.num, .roster-table th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.roster-table th.num .th-sort-in { justify-content: flex-end; }
/* The in-game profile id, now its own column instead of a suffix on the Steam ID. */
.roster-table td.rr-uid-col { color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }

/* Country filter items are multi-select, so they carry the same tick box as every other
   checkable menu (.cdd-check) rather than looking like single-choice rows. */
.rc-item.rc-check .cdd-box {
  flex: none; width: 14px; height: 14px; border-radius: 3px;
  border: 1px solid var(--line-amber, var(--line)); background: var(--inset);
}
.rc-item.rc-check.on { background: none; color: var(--amber-hi); }
.rc-item.rc-check.on .cdd-box {
  background: var(--amber); border-color: var(--amber);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%230d0e0a' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12.5l4.5 4.5L19 7.5'/></svg>");
  background-size: 12px 12px; background-position: center; background-repeat: no-repeat;
}

/* ── admin audit trail ───────────────────────────────────────────────────────
   Built to match the Players roster, because it is the same kind of object — a long list of rows
   scanned top to bottom — and two tables in one panel that behave differently read as a bug.
   It used to be a bare .data-table: auto layout, so the columns were sized by whatever happened to
   be in them and the table ran to the edges of the page; no zebra, no sticky header, no hover.

   Same rules as .roster-table: layout is FIXED, so every column must state a width or it collapses
   while the others divide the space. Percentages, not rem — the panel scales its root font size,
   and a rem width comes out about a quarter too wide against it. */
.data-table.audit-table { table-layout: fixed; width: 100%; }
.audit-table th, .audit-table td { padding-left: 0.5rem; padding-right: 0.5rem; }
.audit-table td { vertical-align: top; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.audit-table th { overflow: hidden; text-overflow: ellipsis; }

.audit-table th.c-when   { width: 12%; }
.audit-table th.c-who    { width: 13%; }
.audit-table th.c-action { width: 16%; }   /* "players.ban", "control.schedule" */
.audit-table th.c-target { width: 15%; }
.audit-table th.c-status { width: 6%; }
.audit-table th.c-ip     { width: 11%; }
.audit-table th.c-details{ width: 24%; }   /* a preview — the full body is in the expanded row */
.audit-table th.c-exp    { width: 2.4%; }  /* just the chevron */

/* Readable header + scannable rows, the same treatment increment 3 gave the roster. */
.audit-table thead th {
  background: var(--bg-2);
  border-bottom: 1px solid var(--line-amber);
  position: sticky; top: 0; z-index: 1;
}
.audit-table tbody tr.audit-row { transition: background .12s ease; cursor: pointer; }
.audit-table tbody tr.audit-row:nth-of-type(4n+3) { background: rgba(255, 255, 255, 0.014); }
.audit-table tbody tr.audit-row:hover { background: var(--hover-bg); }
.audit-table tbody tr.audit-row:focus-visible { outline: 2px solid var(--amber); outline-offset: -2px; }
/* A failed action is the one worth spotting, so it is marked rather than just listed. It has to
   win over the zebra and the hover, hence the later position and the explicit hover rule. */
.audit-table tbody tr.audit-row.audit-bad,
.audit-table tbody tr.audit-row.audit-bad:nth-of-type(4n+3) { background: rgba(229, 68, 63, 0.07); }
.audit-table tbody tr.audit-row.audit-bad:hover { background: rgba(229, 68, 63, 0.12); }
.audit-status-bad { color: #ff8b80; }
.audit-table code { font-family: var(--mono); font-size: 0.78rem; color: var(--amber-hi, var(--amber)); }
.audit-details { font-family: var(--mono); font-size: 0.75rem; color: var(--muted); }
.audit-table td.c-exp { position: relative; overflow: visible; }

/* The chevron is drawn, not fetched: the panel's sprite has no chevron symbol, and the alternative
   is adding one to the sheet for a single 6px mark. */
.audit-chev {
  position: absolute; right: 0.35rem; top: 50%;
  width: 0.42em; height: 0.42em; margin-top: -0.3em;
  border-right: 1.5px solid var(--muted); border-bottom: 1.5px solid var(--muted);
  transform: rotate(45deg); transform-origin: center;
  transition: transform .15s ease, border-color .15s ease;
}
.audit-row:hover .audit-chev { border-color: var(--amber); }
.audit-row.audit-open .audit-chev { transform: rotate(-135deg); margin-top: -0.12em; }
.audit-table tbody tr.audit-row.audit-open { background: var(--hover-bg); }

/* Shown only when the recorded IP cannot be the admin's own — a permanent hint is a hint nobody
   reads. Amber, not red: nothing is broken, the value just isn't what it looks like. */
.audit-ip-hint {
  border-left: 2px solid var(--amber);
  padding-left: 0.7rem;
  color: var(--text);
}

/* ── the expanded row ──────────────────────────────────────────────────────
   The details column used to be the whole recorded body truncated to 70 characters, with the rest
   only in a `title` tooltip — unreadable for JSON and impossible to copy. */
.audit-detail-row > td {
  white-space: normal;
  background: var(--inset, rgba(0, 0, 0, 0.18));
  border-bottom: 1px solid var(--line-amber);
  padding: 0.85rem 1rem 1rem;
}
.audit-dd-grid {
  display: grid; gap: 0.5rem 1.4rem;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  margin-bottom: 0.75rem;
}
.audit-dd-f { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.audit-dd-k {
  font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--muted); font-weight: 600;
}
.audit-dd-v { font-size: 0.84rem; color: var(--text); word-break: break-word; }
.audit-dd-v.mono { font-family: var(--mono); font-size: 0.78rem; }
.audit-dd-body { margin-top: 0.2rem; }
.audit-json {
  margin: 0.3rem 0 0; padding: 0.6rem 0.75rem; max-height: 18rem; overflow: auto;
  background: var(--bg-2); border: 1px solid var(--line); border-radius: calc(var(--radius) / 2);
  font-family: var(--mono); font-size: 0.76rem; line-height: 1.5; color: var(--text);
  white-space: pre-wrap; word-break: break-word;
}

/* Narrow screens drop columns rather than squeezing them — the same order Players uses, least
   useful first. Nothing is lost: every dropped value is in the expanded row. */
@media (max-width: 1100px) {
  .audit-table th.c-ip, .audit-table td.c-ip { display: none; }
  .audit-table th.c-details { width: 35%; }
}
@media (max-width: 820px) {
  .audit-table th.c-target, .audit-table td.c-target { display: none; }
  .audit-table th.c-details, .audit-table td.c-details { display: none; }
  .audit-table th.c-when { width: 24%; }
  .audit-table th.c-who { width: 28%; }
  .audit-table th.c-action { width: 30%; }
  .audit-table th.c-status { width: 12%; }
  .audit-table th.c-exp { width: 6%; }
}
