:root {
  --bg: #f4f5f7;
  --panel: #ffffff;
  --ink: #1c2024;
  --muted: #6b7280;
  --line: #e3e5e9;
  --accent: #2f6f4e;
  --accent-ink: #ffffff;
  --danger: #a4302a;
  --ok: #2e9e5b;
  --warn: #b7791f;
  --radius: 10px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16181c;
    --panel: #1e2126;
    --ink: #e8eaed;
    --muted: #9aa1ac;
    --line: #2c3037;
    --accent: #4f9e75;
    --accent-ink: #0e1114;
    --danger: #e0736c;
    --ok: #55c98a;
    --warn: #d9a441;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

body.centered {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 1rem;
}

/* --- Kopfleiste --- */

.topbar {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0 1.5rem;
  height: 56px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 10;
}

.brand {
  font-weight: 650;
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--ink);
}
.brand span { color: var(--accent); }

.topbar nav { display: flex; gap: 1.25rem; margin-right: auto; }
.topbar nav a {
  text-decoration: none;
  color: var(--muted);
  padding: 0.35rem 0;
  border-bottom: 2px solid transparent;
}
.topbar nav a:hover { color: var(--ink); }
.topbar nav a.on { color: var(--ink); border-bottom-color: var(--accent); }

main {
  max-width: 1000px;
  margin: 0 auto;
  padding: 1.75rem 1.5rem 4rem;
}

.pagehead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.25rem;
  flex-wrap: wrap;
}
.pagehead h1 { margin: 0; }
.actions { display: flex; gap: 0.5rem; align-items: center; }

h1 { font-size: 1.5rem; font-weight: 650; letter-spacing: -0.015em; }
h2 { font-size: 1rem; font-weight: 650; margin: 0 0 0.75rem; }

/* --- Karten --- */

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin-bottom: 1.25rem;
}
.card.danger { border-color: color-mix(in srgb, var(--danger) 35%, var(--line)); }

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
  margin-bottom: 1.5rem;
}
.cards .card { margin: 0; }

.stat .label {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 0.4rem;
}
.stat .value { font-size: 1.2rem; font-weight: 600; }

.split {
  display: grid;
  grid-template-columns: minmax(320px, 380px) 1fr;
  gap: 1.25rem;
  align-items: start;
}
@media (max-width: 800px) { .split { grid-template-columns: 1fr; } }
.stack > .card:last-child { margin-bottom: 1.25rem; }

/* --- Formulare --- */

label {
  display: block;
  margin-bottom: 1rem;
  font-weight: 550;
  font-size: 0.9rem;
}
label small {
  display: block;
  font-weight: 400;
  color: var(--muted);
  margin-top: 0.3rem;
  font-size: 0.82rem;
}
label.check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 400;
}

input[type=text], input[type=password], input[type=number], select, textarea {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--bg);
  color: var(--ink);
  font: inherit;
}
label.check input { margin: 0; width: auto; }

textarea {
  font-family: var(--mono);
  font-size: 0.88rem;
  resize: vertical;
  min-height: 3.5rem;
}
select { cursor: pointer; }
input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

/* Passwortfeld mit Augenschaltfläche.
   Die Schaltfläche sitzt im Feld; der rechte Innenabstand hält den Text
   von ihr weg, sonst läuft ein langes Passwort darunter. */
.pw { position: relative; }
.pw input { padding-right: 2.6rem; }
.pw .eye {
  position: absolute;
  right: 1px;
  top: 0.35rem;
  bottom: 1px;
  width: 2.4rem;
  display: grid;
  place-items: center;
  padding: 0;
  border: none;
  border-radius: 0 6px 6px 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.pw .eye:hover { color: var(--ink); }
.pw .eye[aria-pressed="true"] { color: var(--accent); }
.pw .eye:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
/* Sichtbar ist genau ein Symbol - welches, sagt aria-pressed. Beide
   liegen übereinander im selben Rasterfeld, damit das Umschalten die
   Schaltfläche nicht in der Größe springen lässt. */
.pw .eye svg { grid-area: 1 / 1; }
.pw .eye .zu { display: none; }
.pw .eye[aria-pressed="true"] .offen { display: none; }
.pw .eye[aria-pressed="true"] .zu { display: block; }

.inline-form {
  display: flex;
  gap: 1rem;
  align-items: flex-end;
  flex-wrap: wrap;
}
.inline-form label { margin-bottom: 0; }
.inline-form .grow { flex: 1 1 240px; }

button, .button {
  display: inline-block;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--panel);
  color: var(--ink);
  font: inherit;
  font-weight: 550;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}
button:hover, .button:hover { border-color: var(--muted); }
button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
button.destructive {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}
button.small, .button.small { padding: 0.3rem 0.6rem; font-size: 0.85rem; }
button.link {
  border: 0;
  background: none;
  color: var(--muted);
  padding: 0;
  font-weight: 400;
}
button.link:hover { color: var(--ink); text-decoration: underline; }

/* --- Tabellen --- */

table {
  width: 100%;
  border-collapse: collapse;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 1.25rem;
}
th, td {
  text-align: left;
  padding: 0.65rem 0.9rem;
  border-bottom: 1px solid var(--line);
}
th {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 600;
}
tbody tr:last-child td { border-bottom: 0; }
tr.disabled td { opacity: 0.55; }
.num { text-align: right; }
td a { color: var(--ink); font-weight: 550; }

dl.kv { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 0.4rem 1rem; }
dl.kv dt { color: var(--muted); font-size: 0.88rem; }
dl.kv dd { margin: 0; }

ul.plain { list-style: none; padding: 0; margin: 0; }
ul.plain li { padding: 0.15rem 0; }

/* --- Bausteine --- */

.dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  margin-right: 0.45rem;
  vertical-align: baseline;
  background: var(--muted);
}
.dot.on { background: var(--ok); }
.dot.off { background: var(--danger); }
.dot.unknown { background: var(--warn); }

/* Ein aktiver Peer pulsiert. Nur bei Peers, nicht beim Interface-Punkt:
   dass wg0 läuft, ändert sich selten, und ein dauerpulsierendes Feld
   oben auf der Seite wäre reine Unruhe.

   Der Ring ist ein eigenes Element hinter dem Punkt. Den Punkt selbst zu
   skalieren würde die Textzeile daneben verschieben. */
.peerstate .dot.on { position: relative; }
.peerstate .dot.on::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--ok);
  animation: peerpuls 1.8s ease-out infinite;
  pointer-events: none;
}
@keyframes peerpuls {
  0%   { transform: scale(1);   opacity: 0.55; }
  70%  { transform: scale(2.8); opacity: 0; }
  100% { transform: scale(2.8); opacity: 0; }
}
/* Wer Bewegung abbestellt hat, bekommt den Punkt ohne Puls. Die Aussage
   steht ohnehin als Text daneben, es geht also nichts verloren. */
@media (prefers-reduced-motion: reduce) {
  .peerstate .dot.on::after { animation: none; display: none; }
}

/* Bricht das Nachziehen ab, wird der Hinweis darunter blass - damit
   niemand veraltete Zahlen für aktuelle hält. */
.hint.stale { opacity: 0.45; }

.tag {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  border-radius: 4px;
  background: var(--bg);
  border: 1px solid var(--line);
  font-size: 0.75rem;
  color: var(--muted);
  font-weight: 500;
}

.alert {
  padding: 0.75rem 1rem;
  border-radius: var(--radius);
  margin-bottom: 1.25rem;
  border: 1px solid;
}
.alert.error {
  background: color-mix(in srgb, var(--danger) 10%, var(--panel));
  border-color: color-mix(in srgb, var(--danger) 35%, var(--line));
}
.alert.notice {
  background: color-mix(in srgb, var(--warn) 12%, var(--panel));
  border-color: color-mix(in srgb, var(--warn) 35%, var(--line));
}

.hint { color: var(--muted); font-size: 0.88rem; margin: 0 0 0.9rem; }
.hint.warn { color: var(--warn); }
.muted { color: var(--muted); }
.empty { color: var(--muted); padding: 1.5rem 0; }

.mono { font-family: var(--mono); font-size: 0.88em; }
.break { word-break: break-all; }

pre.conf {
  font-family: var(--mono);
  font-size: 0.85rem;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  overflow-x: auto;
  margin: 0 0 1rem;
}

.tabs {
  display: flex;
  gap: 0.25rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--line);
}
.tab {
  padding: 0.4rem 0.75rem;
  text-decoration: none;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-size: 0.9rem;
  font-weight: 550;
}
.tab:hover { color: var(--ink); }
.tab.on { color: var(--ink); border-bottom-color: var(--accent); }

.notice-inline {
  background: color-mix(in srgb, var(--warn) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--warn) 30%, var(--line));
  border-radius: 7px;
  padding: 0.6rem 0.75rem;
  text-align: left;
}

.qr { text-align: center; }
.qr img {
  width: 320px;
  height: 320px;
  max-width: 100%;
  background: #fff;
  padding: 12px;
  border-radius: 8px;
  border: 1px solid var(--line);
}

/* --- Anmeldung --- */

.login { width: min(360px, 100%); margin: 0; }
.login h1 { margin: 0 0 1.25rem; font-size: 1.35rem; }
.login h1 span { color: var(--accent); }
.login button { width: 100%; }

/* --- Schlüsselanzeige --- */

.keyrow {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.4rem 0.6rem;
  align-items: center;
  margin-bottom: 0.5rem;
}
.keyrow .keylabel {
  grid-column: 1 / -1;
  font-size: 0.88rem;
  color: var(--muted);
}
.keyrow code {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.4rem 0.55rem;
  font-size: 0.82rem;
  user-select: all;
}

/* --- Verbrauchsdiagramm --------------------------------------------
   Zwei Serien aus den ersten beiden Kategorienplätzen einer geprüften
   Palette. Die Trennung liegt in beiden Modi weit über dem Zielwert für
   Farbfehlsichtigkeit; Identität hängt zusätzlich an Legende und
   Tabellenansicht, nie an der Farbe allein. */

:root {
  --series-rx: #2a78d6;
  --series-tx: #eb6834;
}
@media (prefers-color-scheme: dark) {
  :root {
    --series-rx: #3987e5;
    --series-tx: #d95926;
  }
}

.legend { display: flex; gap: 1.25rem; flex-wrap: wrap; margin-bottom: 0.9rem; font-size: 0.88rem; }
.legend .key { display: flex; align-items: center; gap: 0.4rem; color: var(--ink); }
.legend .swatch { width: 10px; height: 10px; border-radius: 2px; }
.legend .swatch.s1 { background: var(--series-rx); }
.legend .swatch.s2 { background: var(--series-tx); }

.chartwrap { position: relative; margin-bottom: 1rem; }
.chartwrap .ymax {
  position: absolute; top: 0; right: 0;
  font-size: 0.75rem; color: var(--muted);
  background: var(--panel); padding-left: 0.4rem;
}
.chart { display: block; overflow: visible; }
.chart .axis { stroke: var(--line); stroke-width: 1; }
/* 2px Fugen zwischen den gestapelten Flächen: sonst verschmelzen sie. */
.chart .bar-rx { fill: var(--series-rx); stroke: var(--panel); stroke-width: 2; }
.chart .bar-tx { fill: var(--series-tx); stroke: var(--panel); stroke-width: 2; }
.chart .bar-empty { fill: var(--line); }
.chart g:hover .bar-rx, .chart g:hover .bar-tx { opacity: 0.75; }
.chart .tick { fill: var(--muted); font-size: 9px; font-family: inherit; }

.table-view summary { cursor: pointer; color: var(--muted); font-size: 0.88rem; }
.table-view table { margin-top: 0.75rem; }
form.spaced { margin-top: 0.75rem; }

/* --- Benutzerverwaltung --- */

/* Aufgeklappt wird die Zeile hoch. Ohne diese Zeile stünde der
   Benutzername mittig neben einem 600 Pixel hohen Formular. */
.konten td { vertical-align: top; }

.inline-actions { display: inline-block; text-align: left; }
.inline-actions summary { list-style: none; display: inline-block; }
.inline-actions summary::-webkit-details-marker { display: none; }
.card.nested {
  margin-top: 0.6rem;
  padding: 0.9rem;
  min-width: 260px;
  /* Sonst zieht sich das Formular über die ganze Tabellenbreite, und ein
     Passwortfeld ist dann 700 Pixel breit. */
  max-width: 28rem;
  background: var(--bg);
}
.card.nested label { margin-bottom: 0.6rem; }
