/* Vyshka panel. One stylesheet, no build step, no external fonts: the
   Content-Security-Policy the hub sends allows nothing off this origin. */

:root {
  color-scheme: light dark;
  --bg: #f6f7f4;
  --panel: #ffffff;
  --ink: #1d2320;
  --muted: #5d665f;
  --line: #d8ddd6;
  --accent: #2f6b4f;
  --accent-ink: #ffffff;
  --warn: #9a6400;
  --warn-bg: #fff4dc;
  --danger: #a3302b;
  --danger-bg: #fde8e6;
  --ok: #2f6b4f;
  --ok-bg: #e3f1e8;
  --code-bg: #eef1ec;
  --radius: 6px;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #161917;
    --panel: #1f2320;
    --ink: #e7ebe6;
    --muted: #9ba59d;
    --line: #353b36;
    --accent: #6fb58f;
    --accent-ink: #10201a;
    --warn: #e0a83a;
    --warn-bg: #2f2716;
    --danger: #e07b74;
    --danger-bg: #3a1f1e;
    --ok: #6fb58f;
    --ok-bg: #1d2f25;
    --code-bg: #262b27;
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.5 var(--sans);
}

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

code, pre, .mono {
  font-family: var(--mono);
  font-size: 0.92em;
}

pre {
  background: var(--code-bg);
  border-radius: var(--radius);
  padding: 0.75rem;
  overflow: auto;
  margin: 0;
  max-height: 24rem;
}

.topbar {
  padding: 0.6rem 1.25rem 0;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}

.topbar-row {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.mainnav {
  display: flex;
  gap: 0.25rem;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}

.mainnav a {
  padding: 0.35rem 0.8rem;
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
  text-decoration: none;
  color: var(--muted);
  font-size: 0.93em;
}

.mainnav a:hover { color: var(--ink); background: var(--code-bg); }

.mainnav a[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
  border-color: var(--line);
  background: var(--bg);
  margin-bottom: -1px;
}

.brand {
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
}

.crumbs {
  flex: 1;
  color: var(--muted);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.crumbs a { text-decoration: none; }
.crumbs .sep { margin: 0 0.4rem; }

.session {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--muted);
  font-size: 0.9em;
}

main {
  max-width: 64rem;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 4rem;
}

h1 { font-size: 1.4rem; margin: 0 0 1rem; }
h2 { font-size: 1.1rem; margin: 1.5rem 0 0.5rem; }
h3 { font-size: 1rem; margin: 1rem 0 0.4rem; }

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

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

.notice {
  border-left: 3px solid var(--accent);
  padding: 0.5rem 0.9rem;
  background: var(--panel);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.error {
  border-left: 3px solid var(--danger);
  background: var(--danger-bg);
  color: var(--ink);
  padding: 0.5rem 0.9rem;
  border-radius: 0 var(--radius) var(--radius) 0;
  margin: 0.75rem 0;
}

.error ul { margin: 0.25rem 0 0; padding-left: 1.2rem; }

button, .button {
  font: inherit;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--ink);
  border-radius: var(--radius);
  padding: 0.45rem 0.9rem;
  cursor: pointer;
}

button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

button:disabled { opacity: 0.55; cursor: default; }

button.small { padding: 0.2rem 0.6rem; font-size: 0.88em; }

/* Forms */

form.stack { display: grid; gap: 0.9rem; }
.card.stack { display: grid; gap: 0.75rem; }

label.field {
  display: grid;
  gap: 0.25rem;
}

label.field > span.name {
  font-weight: 600;
  font-size: 0.93em;
}

label.field > span.name .req {
  color: var(--danger);
  margin-left: 0.2rem;
}

label.field > span.hint {
  color: var(--muted);
  font-size: 0.85em;
}

label.field.inline {
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 0.25rem 0.6rem;
}

label.field.inline > input[type="checkbox"] { margin: 0; justify-self: start; }
label.field.inline > span.hint, label.field.inline > span.field-error { grid-column: 1 / -1; }

input[type="text"], input[type="number"], input[type="password"], input[type="url"],
select, textarea {
  font: inherit;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.4rem 0.6rem;
  width: 100%;
  max-width: 32rem;
}

textarea { font-family: var(--mono); min-height: 5rem; }

input:invalid, .field.invalid input, .field.invalid select, .field.invalid textarea {
  border-color: var(--danger);
}

.field-error {
  color: var(--danger);
  font-size: 0.85em;
}

fieldset {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin: 0;
  display: grid;
  gap: 0.75rem;
}

legend { font-weight: 600; padding: 0 0.3rem; }
legend .include input { margin: 0 0.2rem 0 0; vertical-align: middle; }
legend .hint { font-weight: 400; color: var(--muted); font-size: 0.85em; }

.vector { display: flex; gap: 0.5rem; max-width: 32rem; }
.vector input { min-width: 0; }

.actions-row { display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; }

/* Tables and badges */

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

th, td {
  text-align: left;
  padding: 0.55rem 0.8rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

th { font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
tr:last-child td { border-bottom: 0; }
tr.row-link { cursor: pointer; }
tr.row-link:hover td { background: var(--code-bg); }

.badge {
  display: inline-block;
  padding: 0.05rem 0.5rem;
  border-radius: 999px;
  font-size: 0.8em;
  font-weight: 600;
  border: 1px solid var(--line);
  color: var(--muted);
  white-space: nowrap;
}

.badge.up, .badge.completed, .badge.enrolled { background: var(--ok-bg); color: var(--ok); border-color: transparent; }
.badge.down, .badge.failed, .badge.revoked { background: var(--danger-bg); color: var(--danger); border-color: transparent; }
.badge.warning, .badge.expired, .badge.pending { background: var(--warn-bg); color: var(--warn); border-color: transparent; }
.badge.destructive { background: var(--danger-bg); color: var(--danger); border-color: transparent; }
.badge.core { background: var(--code-bg); border-color: transparent; }
.badge.custom { background: var(--warn-bg); color: var(--warn); border-color: transparent; }

/* Server page links to the other views */

.view-links { display: flex; gap: 0.75rem; margin: 0 0 1rem; }
.view-links .button { text-decoration: none; }

/* Event feed */

.title-tail { font-weight: 400; font-size: 0.8em; }

.feed-controls { display: grid; gap: 0.75rem; }
.filter-row { display: flex; gap: 0.5rem; align-items: center; max-width: 40rem; }
.filter-row input { flex: 1; min-width: 0; max-width: none; font-family: var(--mono); }

#events td.when { white-space: nowrap; color: var(--muted); font-size: 0.92em; }
#events .type { overflow-wrap: anywhere; }
#events td.data { width: 55%; }
#events td.data details > summary { cursor: pointer; word-break: break-word; }
#events td.data details > pre { margin-top: 0.5rem; }

@keyframes feed-flash {
  from { background: var(--ok-bg); }
  to { background: transparent; }
}

#events tr.new td { animation: feed-flash 3s ease-out; }

/* Live map */

.map-controls { display: grid; gap: 0.75rem; }
.map-controls select { max-width: 24rem; }

.notice.target { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: baseline; }

.map {
  position: relative;
  height: min(70vh, 720px);
  min-height: 320px;
  margin: 0 0 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: #121513;
}

.map-stage {
  position: absolute;
  inset: 0;
  cursor: grab;
  touch-action: none;
  outline: none;
}

.map-stage:focus-visible { box-shadow: inset 0 0 0 2px var(--accent); }
.map-stage.dragging { cursor: grabbing; }

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

.map-markers { position: absolute; inset: 0; pointer-events: none; }

/* The button is the dot: 14 px square, pulled back by half of that so the
   transform the widget sets puts the dot's centre exactly on the position.
   The label hangs off its right edge without taking part in its box. */
.map-marker {
  position: absolute;
  left: 0;
  top: 0;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  padding: 0;
  border: 0;
  background: none;
  color: #fff;
  font: inherit;
  pointer-events: auto;
  cursor: pointer;
}

.map-marker-dot {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #ffd166;
  border: 2px solid #1d2320;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.8);
  box-sizing: border-box;
}

.map-marker-label {
  position: absolute;
  left: 100%;
  top: 50%;
  transform: translateY(-50%);
  margin-left: 5px;
  padding: 0.05rem 0.4rem;
  border-radius: 3px;
  background: rgba(10, 14, 11, 0.85);
  font-size: 0.8em;
  line-height: 1.4;
  white-space: nowrap;
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A vehicle is a square where a player is a round dot, in a colour of its
   own, so the two read apart at a glance and in a printed screenshot. */
.map-marker-vehicle .map-marker-dot {
  border-radius: 2px;
  background: #6bd1ff;
}

/* An entity (anything a mod put on the map that is neither a player nor a
   vehicle) is a diamond in a colour of its own, so all three read apart. */
.map-marker-entity .map-marker-dot {
  border-radius: 2px;
  background: #b48bff;
  transform: rotate(45deg);
}

.map-marker:hover .map-marker-dot, .map-marker.highlighted .map-marker-dot, .map-marker:focus-visible .map-marker-dot {
  background: #ff6b6b;
  box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.45);
}

.map-marker:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.map-hud {
  position: absolute;
  right: 0.6rem;
  bottom: 0.6rem;
  display: grid;
  gap: 0.3rem;
  justify-items: end;
  padding: 0.4rem 0.5rem;
  border-radius: var(--radius);
  background: rgba(10, 14, 11, 0.8);
  color: #eef2ec;
  font-size: 0.8em;
  font-family: var(--mono);
}

.map-hud-row { display: flex; gap: 0.3rem; align-items: center; }
.map-hud button { color: #eef2ec; background: #2b372e; border-color: #465249; }
.map-scale-bar { display: block; height: 0.4rem; border: solid #eef2ec; border-width: 0 2px 2px; }
.map-cursor { min-height: 1.2em; }
.map-tiles { color: #b8c2ba; }

#players td.position { white-space: nowrap; }
#players td.data { width: 40%; word-break: break-word; }
#players td.row-actions { white-space: nowrap; }
#players .button.small { text-decoration: none; }

/* Management views */

button.danger {
  border-color: var(--danger);
  color: var(--danger);
  font-weight: 600;
}

.badges { display: inline-flex; flex-wrap: wrap; gap: 0.25rem; }

tr.dim td { opacity: 0.6; }

.notice.danger { border-left-color: var(--danger); background: var(--danger-bg); }

.secret { border-color: var(--accent); }
.secret-row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; margin: 0.5rem 0; }
.secret-value {
  background: var(--code-bg);
  border-radius: var(--radius);
  padding: 0.4rem 0.6rem;
  word-break: break-all;
  user-select: all;
}
.copy-state { display: block; font-size: 0.88em; }

/* The tray of secrets whose own page had gone before the hub answered. */
#held-secrets { display: grid; gap: 0.5rem; margin-bottom: 1rem; }
#held-secrets .held-secret { display: grid; gap: 0.3rem; }

.checklist { display: grid; gap: 0.2rem; max-height: 14rem; overflow: auto; }
.checklist .check { display: flex; gap: 0.4rem; align-items: baseline; }

.filter-grid {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}

.revoke-cell { display: inline-flex; gap: 0.3rem; }

#tokens td, #audit td, #deliveries td, #webhooks td { font-size: 0.95em; }
#audit td.when, #deliveries td { white-space: nowrap; }
#tokens td.mono { word-break: break-all; }
#audit td.data { width: 35%; white-space: normal; }
#audit td.data details > summary { cursor: pointer; word-break: break-word; }
#audit td.data details > pre { margin-top: 0.5rem; }
#deliveries td.last-result { white-space: normal; }
#kv-keys td { word-break: break-all; }
table.bans td { font-size: 0.95em; }
table.bans td.reason { width: 30%; word-break: break-word; }
table.bans td.row-actions { white-space: nowrap; }

/* Action list */

.action-list { display: grid; gap: 0.5rem; }

.action-row { display: flex; gap: 0.5rem; align-items: stretch; }
.action-row > .action-item { flex: 1; }
.action-row > button.pin { align-self: stretch; }
.action-row.missing .action-item { border-style: dashed; }
button.pin[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); font-weight: 600; }

.action-item {
  display: flex;
  gap: 0.75rem;
  align-items: baseline;
  padding: 0.6rem 0.9rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
}

.action-item:hover { border-color: var(--accent); }
.action-item .name { font-weight: 600; }
.action-item .code { color: var(--muted); }
.action-item .spacer { flex: 1; }

/* Dispatch timeline */

.timeline {
  display: flex;
  gap: 0;
  margin: 0.75rem 0 1rem;
  padding: 0;
  list-style: none;
  flex-wrap: wrap;
}

.timeline li {
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--line);
  margin-right: -1px;
  color: var(--muted);
  font-size: 0.9em;
}

.timeline li:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.timeline li:last-child { border-radius: 0 var(--radius) var(--radius) 0; }
.timeline li.reached { background: var(--ok-bg); color: var(--ok); border-color: var(--ok); }
.timeline li.current { font-weight: 700; }
.timeline li.bad { background: var(--danger-bg); color: var(--danger); border-color: var(--danger); }

dl.kv {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.25rem 1rem;
  margin: 0.5rem 0;
}

dl.kv dt { color: var(--muted); }
dl.kv dd { margin: 0; word-break: break-all; }

.login {
  max-width: 28rem;
  margin: 3rem auto;
}

/* Player profiles (protocol section 8.6): the identities an event names,
   linked to their profiles, and the notes operators keep on one. */
.identities { display: flex; flex-wrap: wrap; gap: 0.25rem 0.75rem; margin-top: 0.25rem; font-size: 0.9em; }
#player-events td.data, #player-actions td.data { width: 45%; word-break: break-word; }
#player-events td.data details > summary, #player-actions td.data details > summary { cursor: pointer; }
.notes { list-style: none; padding: 0; margin: 0.5rem 0; }
.note { border-top: 1px solid var(--line); padding: 0.5rem 0; }
.note:first-child { border-top: none; }
.note-text { margin: 0; white-space: pre-wrap; word-break: break-word; }
.note-meta { margin: 0.25rem 0 0; font-size: 0.85em; }
.note-meta .field.inline { display: inline-flex; margin: 0; }
