/* host4k v0.5 — Glasmorphism */
* { box-sizing: border-box; margin: 0; padding: 0; }

/* Custom Scrollbars */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.18);
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.32); }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-button { display: none; width: 0; height: 0; }

:root {
  --glass-bg: rgba(255, 255, 255, 0.07);
  --glass-border: rgba(255, 255, 255, 0.14);
  --text: #e8ecf4;
  --text-dim: #9aa3b5;
  --accent: #6ee7a0;
  --danger: #f87171;
  --radius: 18px;
}

body {
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  background: linear-gradient(135deg, #0d1020 0%, #141a33 50%, #0e1a26 100%);
  color: var(--text);
  min-height: 100vh;
  overflow-x: hidden;
}

/* Die Orb-Farben gehen seit v0.16 über var(--orb-N) — applySkin() setzt die
   Variablen inline auf <body>. Der zweite Wert ist der Rückfall: Ohne Skin
   steht dort exakt das, was bis v0.15.6 fest verdrahtet war. Deshalb müssen
   auch die Theme-Regeln weiter unten die Variable benutzen; täten sie es nicht,
   würden sie den Inline-Wert per höherer Spezifität wieder überstimmen (die
   Variable kaskadiert von <body>, die Regel trifft das Kind). */
.bg-orbs { position: fixed; inset: 0; z-index: -1; filter: blur(90px); }
.orb { position: absolute; border-radius: 50%; opacity: 0.35; animation: drift 24s ease-in-out infinite alternate; }
.orb-1 { width: 45vw; height: 45vw; background: var(--orb-1, #2b4a8f); top: -12%; left: -8%; }
.orb-2 { width: 38vw; height: 38vw; background: var(--orb-2, #1f6b4a); bottom: -14%; right: -6%; animation-delay: -8s; }
.orb-3 { width: 26vw; height: 26vw; background: var(--orb-3, #5a3a8f); top: 42%; left: 55%; animation-delay: -16s; }
@keyframes drift { to { transform: translate(6vw, -4vh) scale(1.12); } }

/* Animierte Canvas-Hintergründe (v0.15.4) --------------------------------------
   Ist einer aktiv, fliegen die CSS-Orbs raus (sonst zwei Ebenen übereinander)
   und die Glas-Karten werden etwas kräftiger: Der Canvas ist stellenweise hell
   und unruhig, mit den Standardwerten (7 % Weiß) würde Text darauf schwimmen.
   Der Kontrast bleibt so überall lesbar, der Glas-Look erhalten. */
body.has-bg-canvas .bg-orbs { display: none; }
body.has-bg-canvas .glass {
  background: color-mix(in srgb, var(--glass-bg) 45%, rgba(6, 8, 16, 0.62));
  border-color: color-mix(in srgb, var(--glass-border) 70%, rgba(255, 255, 255, 0.1));
  backdrop-filter: blur(18px) saturate(1.15);
  -webkit-backdrop-filter: blur(18px) saturate(1.15);
  box-shadow: 0 10px 38px rgba(0, 0, 0, 0.42);
}
/* Header und Versions-Badge stehen frei auf dem Bild → leichter Schattenrand */
body.has-bg-canvas header,
body.has-bg-canvas .version-tag { text-shadow: 0 1px 10px rgba(0, 0, 0, 0.65); }

header { display: flex; align-items: center; gap: 12px; padding: 26px 34px; }
header h1 { font-size: 1.5rem; font-weight: 650; letter-spacing: 0.02em; }
/* Versions-Badge (v0.14.7): raus aus dem Header, dezent unten rechts.
   Halbtransparent, wird beim Drüberfahren lesbar. Klick-durchlässig, damit es
   nie etwas blockiert. Die Toasts sitzen darüber (siehe #toasts bottom). */
.version-tag {
  position: fixed; bottom: 10px; right: 14px; z-index: 5;
  font-size: 0.68rem; letter-spacing: 0.03em;
  padding: 2px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--glass-bg) 60%, transparent);
  border: 1px solid color-mix(in srgb, var(--glass-border) 55%, transparent);
  color: var(--text-dim);
  opacity: 0.32;
  pointer-events: none;
  backdrop-filter: blur(4px);
  transition: opacity 0.15s ease;
}
body:hover .version-tag { opacity: 0.6; }
.docker-status { font-size: 0.82rem; color: var(--text-dim); }
.docker-status.ok { color: var(--accent); }
.docker-status.bad { color: var(--danger); }

main { max-width: 1080px; margin: 0 auto; padding: 0 24px 64px; display: grid; gap: 22px; }

.glass {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
  padding: 22px 24px;
}

.panel-create h2, .glass h2 { font-size: 1.05rem; margin-bottom: 16px; font-weight: 600; }
.form-row { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 14px; margin-bottom: 14px; }
label { display: flex; flex-direction: column; gap: 6px; font-size: 0.8rem; color: var(--text-dim); }
input[type="text"], input[type="password"], input[type="number"], select {
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--glass-border);
  border-radius: 10px;
  color: var(--text);
  padding: 9px 12px;
  font-size: 0.9rem;
  outline: none;
}
input:focus, select:focus { border-color: var(--accent); }
.eula-row { flex-direction: row; align-items: center; gap: 8px; margin-bottom: 16px; font-size: 0.85rem; }
.eula-row a { color: var(--accent); }

.btn {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: 10px;
  color: var(--text);
  padding: 9px 18px;
  font-size: 0.88rem;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
}
.btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.14); }
.btn:active:not(:disabled) { transform: scale(0.97); }
.btn:disabled { opacity: 0.35; cursor: not-allowed; }
.btn-primary { background: color-mix(in srgb, var(--accent) 16%, transparent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.btn-danger { border-color: rgba(248, 113, 113, 0.4); color: var(--danger); }
.error-msg { margin-left: 12px; color: var(--danger); font-size: 0.82rem; }

/* server cards */
.server-list { display: grid; gap: 16px; }
.card-head { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 14px; }
.s-name { font-size: 1.1rem; font-weight: 600; }
.s-meta { font-size: 0.78rem; color: var(--text-dim); }
.s-address {
  font-size: 0.85rem; color: var(--text-dim); margin-bottom: 12px;
  font-family: ui-monospace, monospace;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.btn-copy { padding: 4px 10px; font-size: 0.74rem; }

.state-badge {
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.04em;
  padding: 4px 11px; border-radius: 999px;
  border: 1px solid var(--glass-border);
  text-transform: uppercase;
}
.state-badge[data-state="running"],
.state-badge[data-state="online"] { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 50%, transparent); }
.state-badge[data-state="offline"], .state-badge[data-state="created"] { color: var(--text-dim); }
.state-badge[data-state="parked"] { color: #93c5fd; border-color: rgba(147, 197, 253, 0.45); }
/* Node im Standby (v0.15.1): eigenes Blau — Stromsparen ist kein Ausfall und
   darf deshalb nicht wie das rote/graue "offline" aussehen. */
.state-badge[data-state="sleeping"] {
  color: #7dd3fc; border-color: rgba(125, 211, 252, 0.5);
  box-shadow: 0 0 10px rgba(125, 211, 252, 0.15);
  text-transform: none; letter-spacing: 0.02em;
}
.state-badge[data-state="starting"], .state-badge[data-state="installing"],
.state-badge[data-state="stopping"], .state-badge[data-state="deleting"],
.state-badge[data-state="migrating"] {
  color: #fbbf24; border-color: rgba(251, 191, 36, 0.5);
  animation: pulse 1.2s ease-in-out infinite;
}
.state-badge[data-state="crashed"], .state-badge[data-state="install_failed"] {
  color: var(--danger); border-color: rgba(248, 113, 113, 0.5);
}
@keyframes pulse { 50% { opacity: 0.45; } }

.card-actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* console */
.console-wrap { margin-top: 16px; }
.console-out {
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--glass-border);
  border-radius: 10px;
  padding: 12px 14px;
  height: 260px;
  overflow-y: auto;
  font-family: ui-monospace, "Cascadia Mono", monospace;
  font-size: 0.76rem;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-all;
  color: #c7d0e0;
}
.console-form { display: flex; gap: 10px; margin-top: 10px; }
.console-form input { flex: 1; }

.hidden { display: none !important; }
.hint { font-size: 0.8rem; color: var(--text-dim); }
.hint code { color: var(--accent); word-break: break-all; }

/* header nav */
nav { display: flex; gap: 8px; margin-left: 20px; }
.btn-nav.active { background: rgba(255, 255, 255, 0.16); border-color: var(--accent); }
.header-right { margin-left: auto; display: flex; align-items: center; gap: 14px; }
.whoami { font-size: 0.85rem; color: var(--text-dim); }

/* auth */
.auth-main { display: flex; justify-content: center; padding-top: 8vh; }
.auth-card { width: min(380px, 92vw); }
.auth-card h2 { margin-bottom: 18px; }
.auth-card form { display: grid; gap: 14px; }
.auth-switch { margin-top: 16px; font-size: 0.85rem; color: var(--text-dim); }
.auth-switch a { color: var(--accent); }
#first-user-hint { margin-top: 10px; }

/* settings */
.settings-wrap { margin-top: 16px; border-top: 1px solid var(--glass-border); padding-top: 16px; }
.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}
.settings-actions { display: flex; align-items: center; gap: 12px; }
.settings-msg.ok { color: var(--accent); font-size: 0.82rem; }

/* subusers */
.subusers-wrap { margin-top: 16px; border-top: 1px solid var(--glass-border); padding-top: 16px; }
.subuser-row {
  display: flex; align-items: center; gap: 14px;
  padding: 8px 0; border-bottom: 1px solid var(--glass-border);
  font-size: 0.88rem;
}
.subuser-row .btn { margin-left: auto; padding: 5px 12px; font-size: 0.78rem; }
.subusers-form {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 14px;
}
.subusers-form .su-username { width: 160px; }
.su-perm {
  flex-direction: row; align-items: center; gap: 6px;
  font-size: 0.82rem; color: var(--text-dim);
}
.su-msg { font-size: 0.82rem; }
.su-msg.ok { color: var(--accent); }

/* admin tabs */
.admin-tabs { display: flex; gap: 8px; flex-wrap: wrap; }
.btn-atab { padding: 8px 16px; font-size: 0.84rem; }
.btn-atab.active { background: rgba(255, 255, 255, 0.16); border-color: var(--accent); }

/* admin tables */
/* DER GRUND, WARUM DER ADMIN-BEREICH AUF DEM HANDY GERUCKELT HAT (v0.18.1):
   Die Ansichten sind Grid-Container, und ein Grid-Item hat standardmäßig
   `min-width: auto` — es schrumpft also NICHT unter die Breite seines Inhalts.
   Eine 890 px breite Tabelle hat damit die ganze Section auf 918 px aufgeblasen
   und das Dokument auf 932 px, bei 375 px Bildschirmbreite.

   Das Tückische: `.table-wrap` mit `overflow-x: auto` sah nach der richtigen
   Lösung aus, konnte aber nichts tun — wenn der Container selbst mitwächst,
   läuft nichts über, und es gibt nichts zu scrollen. Und `body { overflow-x:
   hidden }` verdeckte den Rest: Man konnte nicht hinscrollen, aber der Browser
   hat die überbreite Seite trotzdem gelayoutet und gezeichnet.

   `min-width: 0` nimmt den Grid-Items diese Sperre. Erst dadurch wird die
   Section 375 px schmal, der Wrapper bekommt einen echten Überlauf, und die
   Tabelle scrollt für sich allein — so wie es immer gemeint war.

   Merke: Bei Flex- und Grid-Kindern ist `min-width: 0` fast immer nötig, sobald
   etwas Breites darin liegt (Tabellen, <pre>, lange Wörter). */
#view-panel > *,
#view-admin > *,
#view-features > * { min-width: 0; }

.table-wrap { overflow-x: auto; max-width: 100%; }
table { width: 100%; border-collapse: collapse; font-size: 0.86rem; }
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--glass-border); }
th { color: var(--text-dim); font-weight: 500; font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.05em; }
td input[type="number"] { width: 90px; padding: 6px 8px; }
td input[type="text"] { width: 150px; padding: 6px 8px; }
td select { padding: 6px 8px; }
td .btn { padding: 6px 12px; font-size: 0.8rem; }
.migrate-cell { white-space: nowrap; }
.migrate-cell select { max-width: 130px; }

/* node create + token box */
.node-create { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.node-create input { flex: 1; min-width: 160px; }
.token-box {
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: 10px;
  padding: 14px 16px;
  margin-bottom: 16px;
  font-size: 0.85rem;
}
.token-box code {
  display: block;
  margin: 8px 0;
  padding: 8px 10px;
  background: rgba(0, 0, 0, 0.35);
  border-radius: 8px;
  font-family: ui-monospace, monospace;
  font-size: 0.78rem;
  word-break: break-all;
  color: var(--accent);
}

/* template editor */
.template-editor { margin-top: 18px; }
.template-editor h3 { font-size: 0.95rem; margin-bottom: 8px; }
.template-editor textarea {
  width: 100%;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--glass-border);
  border-radius: 10px;
  color: #c7d0e0;
  font-family: ui-monospace, monospace;
  font-size: 0.78rem;
  padding: 12px;
  margin-bottom: 10px;
  resize: vertical;
}

@media (max-width: 720px) {
  .form-row { grid-template-columns: 1fr 1fr; }
  header { flex-wrap: wrap; }
}

/* v0.6 — Mobile-Basics */
@media (max-width: 720px) {
  main { padding: 0 12px 48px; }
  header { padding: 20px 14px; gap: 8px; }
  .glass { padding: 16px 14px; }
  .card-actions .btn { padding: 7px 12px; font-size: 0.8rem; }
  .header-right { gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
  .whoami { display: none; }
  /* Auf 375 px zählt jeder Pixel in der Kopfzeile: Mit "🎨 Skin" ausgeschrieben
     sind die vier Bedienelemente zusammen 344 px breit und passen nicht in die
     347 px der Zeile — "Logout" rutscht in eine dritte Zeile und der Header
     wird 164 statt 128 px hoch. Nur das Emoji spart die nötigen 38 px.
     Beschriftung bleibt über title/aria-label erhalten. */
  #btn-skin { padding: 7px 10px; }
  .btn-skin-label { display: none; }
}

/* v0.7 — Bot-Panel */
.bot-wrap { margin-top: 16px; border-top: 1px solid var(--glass-border); padding-top: 16px; display: grid; gap: 12px; }
.bot-wrap textarea {
  width: 100%; background: rgba(0,0,0,0.25); border: 1px solid var(--glass-border);
  border-radius: 10px; color: var(--text); font-size: 0.88rem; padding: 10px 12px; resize: vertical;
}
.bot-wrap textarea:focus { border-color: var(--accent); }

/* v0.8 — Mod-Browser */
.mods-wrap { margin-top: 16px; border-top: 1px solid var(--glass-border); padding-top: 16px; }
.mods-search-form { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.mods-search-form input { flex: 1; min-width: 200px; }
.mods-results, .mods-installed { display: grid; gap: 6px; }
.mods-installed-title { font-size: 0.9rem; margin: 14px 0 8px; }
.mod-row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 10px; border: 1px solid var(--glass-border); border-radius: 10px;
  font-size: 0.86rem; background: rgba(0, 0, 0, 0.15);
}
.mod-icon { width: 32px; height: 32px; border-radius: 6px; flex-shrink: 0; object-fit: cover; }
.mod-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.mod-text .hint { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mod-name { font-weight: 600; }
.mod-row .btn { padding: 6px 12px; font-size: 0.78rem; flex-shrink: 0; }

/* ============================================================
   v0.8.1 — Polish-Layer: schnell & lebendig, nie blockierend.
   Alle Transitions ≤ 180ms, Animationen nur EINMALIG (Entrance),
   nichts loopt, nichts lässt warten.
   ============================================================ */

/* Buttons: knackiges Feedback */
.btn {
  transition: background 0.12s ease, border-color 0.12s ease,
              transform 0.08s ease, box-shadow 0.12s ease;
}
.btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25);
}
.btn:active:not(:disabled) { transform: translateY(0) scale(0.97); box-shadow: none; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn-primary {
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 22%, transparent), color-mix(in srgb, var(--accent) 10%, transparent));
}
.btn-primary:hover:not(:disabled) {
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 32%, transparent), color-mix(in srgb, var(--accent) 16%, transparent));
  border-color: color-mix(in srgb, var(--accent) 60%, transparent);
}

/* Inputs: sanfter Fokus */
input, select, textarea { transition: border-color 0.12s ease, box-shadow 0.12s ease; }
input:focus, select:focus, textarea:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 12%, transparent);
}

/* Server-Cards: Hover-Lift + EINMALIGE Entrance (nur beim Einfügen) */
.server-card {
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
  animation: card-rise 0.18s ease both;
}
.server-card:hover {
  transform: translateY(-2px);
  border-color: rgba(255, 255, 255, 0.24);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.32);
}
@keyframes card-rise {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Laufender Server / wache Node: dezenter Glow am Badge (statisch, kein Loop) */
.state-badge[data-state="running"],
.state-badge[data-state="online"] { box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 25%, transparent); }

/* Logo (v0.14.7): fester Rot→Blau-Marken-Gradient statt blassem Accent-Verlauf.
   Bewusst themen-unabhängig — "Host4000" sieht in jedem Theme gleich aus.
   Dezenter Glow drunter, damit es auf dunklen Themes nicht tot wirkt. */
header h1 {
  font-size: 1.6rem;
  font-weight: 750;
  letter-spacing: -0.01em;
  background: linear-gradient(100deg, #ff5a6e 0%, #c05cf0 48%, #4f9dff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 2px 10px rgba(150, 90, 220, 0.28));
}
/* Logo verlinkt auf die Hauptseite — erbt den Gradient, kein Link-Look */
.brand-link { color: inherit; text-decoration: none; display: inline-flex; align-items: center; }
.brand-link:hover { filter: brightness(1.15); }

/* Hochgeladenes Logo (v0.15.5) statt Schriftzug. Höhe fix, Breite nach
   Seitenverhältnis — der Header darf davon nicht wachsen. */
.brand-logo {
  height: 34px;
  width: auto;
  max-width: min(340px, 44vw);
  object-fit: contain;
  display: block;
}
/* Mobil kleiner. MUSS nach der Basisregel stehen — gleiche Spezifität, sonst
   gewinnt die spätere Regel und die Anpassung wäre wirkungslos. */
@media (max-width: 720px) {
  .brand-logo { height: 28px; max-width: 46vw; }
}
/* Vorschau im Admin-Panel: heller Karo-Grund, damit man Transparenz sieht */
.logo-slot { display: inline-flex; align-items: center; min-width: 120px; }
.logo-preview {
  height: 30px; width: auto; max-width: 220px; object-fit: contain;
  border-radius: 6px; padding: 3px 6px;
  background:
    linear-gradient(45deg, rgba(255,255,255,0.06) 25%, transparent 25%, transparent 75%, rgba(255,255,255,0.06) 75%) 0 0/12px 12px,
    linear-gradient(45deg, rgba(255,255,255,0.06) 25%, transparent 25%, transparent 75%, rgba(255,255,255,0.06) 75%) 6px 6px/12px 12px,
    rgba(0, 0, 0, 0.25);
  border: 1px solid var(--glass-border);
}

/* Panels (Settings/Bot/Mods/Subuser/Console): schnelles Aufklappen */
.settings-wrap, .subusers-wrap, .bot-wrap, .mods-wrap, .console-wrap {
  animation: card-rise 0.15s ease both;
}

/* Tabellen-Zeilen: Hover-Hint */
tbody tr { transition: background 0.1s ease; }
tbody tr:hover { background: rgba(255, 255, 255, 0.04); }

/* Toasts: unten rechts, nicht blockierend */
#toasts {
  position: fixed; bottom: 38px; right: 20px; z-index: 999; /* über dem Versions-Badge */
  display: flex; flex-direction: column; gap: 8px; max-width: min(380px, 90vw);
}
.toast {
  background: rgba(20, 26, 51, 0.92);
  border: 1px solid var(--glass-border);
  border-left: 3px solid var(--danger);
  border-radius: 12px;
  padding: 11px 16px;
  font-size: 0.86rem;
  color: var(--text);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(12px);
  opacity: 0; transform: translateX(12px);
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.toast.show { opacity: 1; transform: translateX(0); }
.toast.ok { border-left-color: var(--accent); }

/* ===== v0.17 — Benachrichtigungen bleiben stehen ============================
   Sie verschwinden nicht mehr von allein, brauchen also ein Schließkreuz und
   müssen mehr Text tragen können (Titel, Notiz, Fortschritt). Die Liste wird
   von unten aufgebaut und darf nie den halben Bildschirm füllen — daher der
   Scrollbereich und "Alle schließen" ab drei Meldungen. */
#toasts { max-height: min(70vh, 640px); overflow-y: auto; padding-right: 2px; }
.toast { position: relative; padding-right: 34px; }
.toast.info { border-left-color: var(--text-dim); }
.toast-x {
  position: absolute; top: 6px; right: 8px;
  background: none; border: 0; padding: 2px 6px;
  color: var(--text-dim); font-size: 1.05rem; line-height: 1;
  cursor: pointer; border-radius: 6px;
}
.toast-x:hover { color: var(--text); background: rgba(255, 255, 255, 0.09); }
.toast-title {
  font-weight: 620; font-size: 0.8rem; letter-spacing: 0.01em;
  margin-bottom: 2px; color: var(--text);
}
.toast-msg { word-break: break-word; }
.toast-note { font-size: 0.74rem; margin-top: 3px; }
.toast-bar {
  height: 6px; margin-top: 8px; border-radius: 999px; overflow: hidden;
  background: rgba(255, 255, 255, 0.08);
}
.toast-fill {
  height: 100%; width: 0%; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), rgba(255, 255, 255, 0.5));
  transition: width 0.3s ease;
}
.toast-fill.indet {
  width: 100% !important;
  animation: indet-pulse 1.4s ease-in-out infinite;
}
.toasts-clear {
  align-self: flex-end;
  background: rgba(20, 26, 51, 0.92);
  border: 1px solid var(--glass-border);
  color: var(--text-dim);
  font-size: 0.74rem; padding: 4px 10px; border-radius: 999px;
  cursor: pointer; backdrop-filter: blur(12px);
}
.toasts-clear:hover { color: var(--text); }

/* ===== v0.14.7 — Panel-Kopf: "Deine Server" + Anlegen-Button ================
   Das Erstell-Formular ist nicht mehr dauerhaft aufgeklappt, sondern liegt
   hinter diesem Button — das Panel startet damit direkt bei den Servern. */
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: -6px;
}
.panel-title {
  font-size: 1.15rem; font-weight: 620; letter-spacing: 0.01em;
  color: var(--text);
}
.btn-new { display: inline-flex; align-items: center; gap: 7px; }
.btn-new-icon {
  font-size: 1.05rem; line-height: 1; font-weight: 500;
  display: inline-block; transition: transform 0.18s ease;
}
.btn-new.is-open .btn-new-icon { transform: rotate(45deg); } /* + wird zum × */

.panel-create { animation: card-rise 0.16s ease both; }
.create-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Empty-State */
.empty-state {
  text-align: center; padding: 44px 24px; color: var(--text-dim);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.empty-emoji { font-size: 2rem; }
.empty-emoji svg { display: block; filter: drop-shadow(0 0 12px rgba(62, 230, 196, 0.35)); }

/* Barrierefreiheit: wer keine Bewegung will, bekommt keine */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
  .orb { animation: none !important; }
}

/* v0.9 — File-Manager */
.fm-wrap { margin-top: 16px; border-top: 1px solid var(--glass-border); padding-top: 16px; display: grid; gap: 10px; }
.fm-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.fm-crumbs { flex: 1; font-size: 0.88rem; font-family: ui-monospace, monospace; }
.fm-crumbs a { color: var(--accent); text-decoration: none; }
.fm-crumbs a:hover { text-decoration: underline; }
.fm-list { display: grid; gap: 6px; max-height: 320px; overflow-y: auto; }
.fm-row { padding: 6px 10px; }
.fm-icon { flex-shrink: 0; }
.fm-name { flex: 1; color: var(--text); text-decoration: none; cursor: pointer; }
.fm-name:hover { color: var(--accent); }
.fm-editor { display: grid; gap: 10px; }
.fm-content {
  width: 100%; background: rgba(0, 0, 0, 0.35); border: 1px solid var(--glass-border);
  border-radius: 10px; color: #c7d0e0; font-family: ui-monospace, monospace;
  font-size: 0.8rem; padding: 12px; resize: vertical;
}

/* v0.9 — Card-Tabs (GUI-Großputz) */
.actions-spacer { flex: 1; }
.card-tabs {
  display: flex; gap: 6px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--glass-border);
}
.ptab {
  padding: 6px 13px; font-size: 0.8rem;
  background: transparent; border-color: transparent;
  color: var(--text-dim);
}
.ptab:hover:not(:disabled) { color: var(--text); background: var(--glass-bg); transform: none; box-shadow: none; }
.ptab.active {
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-color: color-mix(in srgb, var(--accent) 35%, transparent);
}
.backups-wrap { margin-top: 14px; display: grid; gap: 10px; }

/* ============================================================
   v0.10 — Themes, Modals, Dropdowns, Login
   ============================================================ */

/* --- Themes (body[data-theme], Wahl im Header, localStorage) --- */

/* Fusion (v0.14.7) — Rot/Blau, neuer Default. Die beiden Farben stehen sich
   in den Orbs gegenüber, Violett bildet die Brücke → lebendig, aber ruhig. */
body[data-theme="fusion"] {
  --accent: #7cb3ff;
  --text: #ecf0fb;
  --text-dim: #9aa4c2;
  background: linear-gradient(135deg, #0c0e1e 0%, #17122c 52%, #1c1020 100%);
}
body[data-theme="fusion"] .orb-1 { background: var(--orb-1, #3457c4); } /* blau  */
body[data-theme="fusion"] .orb-2 { background: var(--orb-2, #c0324f); } /* rot   */
body[data-theme="fusion"] .orb-3 { background: var(--orb-3, #7b3ac4); } /* violett */

body[data-theme="ember"] {
  --accent: #fbbf6e;
  background: linear-gradient(135deg, #1a0d0d 0%, #2b1a10 50%, #26120e 100%);
}
body[data-theme="ember"] .orb-1 { background: var(--orb-1, #8f4a2b); }
body[data-theme="ember"] .orb-2 { background: var(--orb-2, #6b3a1f); }
body[data-theme="ember"] .orb-3 { background: var(--orb-3, #8f2b2b); }

body[data-theme="ocean"] {
  --accent: #6ec6e7;
  background: linear-gradient(135deg, #0a1420 0%, #0e2233 50%, #0a1c2e 100%);
}
body[data-theme="ocean"] .orb-1 { background: var(--orb-1, #1f4a6b); }
body[data-theme="ocean"] .orb-2 { background: var(--orb-2, #1f6b6b); }
body[data-theme="ocean"] .orb-3 { background: var(--orb-3, #2b3a8f); }

body[data-theme="matrix"] {
  --accent: #4ade80;
  --text: #d8f5e0;
  --text-dim: #7aa88a;
  background: linear-gradient(135deg, #050b06 0%, #0a1a0d 50%, #071408 100%);
}
body[data-theme="matrix"] .orb-1 { background: var(--orb-1, #14532d); }
body[data-theme="matrix"] .orb-2 { background: var(--orb-2, #166534); }
body[data-theme="matrix"] .orb-3 { background: var(--orb-3, #052e16); }

/* Theme-Picker klein & dezent */
#theme-picker,
#bg-picker { padding: 5px 26px 5px 9px; font-size: 0.78rem; }

/* --- Dropdowns: eigene Optik statt OS-Grau --- */
select {
  appearance: none;
  -webkit-appearance: none;
  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' stroke='%239aa3b5' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 28px;
  cursor: pointer;
}
select:hover:not(:disabled) { border-color: rgba(255, 255, 255, 0.3); }
select option, select optgroup {
  background: #141a33;
  color: var(--text);
}
body[data-theme="ember"] select option { background: #2b1a10; }
body[data-theme="ocean"] select option { background: #0e2233; }
body[data-theme="matrix"] select option { background: #0a1a0d; }

/* --- Modals --- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 998;
  background: rgba(5, 8, 18, 0.6);
  backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transition: opacity 0.15s ease;
}
.modal-overlay.show { opacity: 1; }
.modal {
  width: min(460px, 92vw);
  padding: 24px 26px;
  transform: translateY(10px) scale(0.98);
  transition: transform 0.15s ease;
}
.modal-overlay.show .modal { transform: translateY(0) scale(1); }
.modal h3 { font-size: 1.05rem; margin-bottom: 12px; }
.modal-body { font-size: 0.9rem; color: var(--text-dim); margin-bottom: 14px; }
.modal-checks { display: grid; gap: 4px; margin-bottom: 16px; }
.modal-check { margin-bottom: 0 !important; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; }

/* ============================================================
   v0.16 — Skin-Editor
   ============================================================ */

#btn-skin { padding: 7px 14px; font-size: 0.8rem; }

/* Das Overlay ist breiter als die Bestätigungs-Modals und scrollt INNEN:
   Auf einem 375×667-Handy passen die drei Blöcke sonst nicht, und ein
   scrollendes Overlay über einer scrollenden Seite ist unbedienbar. */
.skin-modal {
  width: min(680px, 94vw);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
}
.skin-body { overflow-y: auto; margin: 0 -4px 14px; padding: 0 4px; display: grid; gap: 18px; }
.skin-block { display: grid; gap: 10px; }
.skin-block h4 {
  font-size: 0.78rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-dim);
}

/* Block 1 — Hintergrund-Kacheln mit laufender Vorschau */
.skin-bgs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.skin-bg-tile {
  display: grid; gap: 6px; padding: 6px;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  color: var(--text-dim);
  font-size: 0.72rem;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.skin-bg-tile:hover { border-color: rgba(255, 255, 255, 0.3); }
.skin-bg-tile.active {
  border-color: var(--accent);
  color: var(--text);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
}
.skin-bg-prev {
  display: block; position: relative; overflow: hidden;
  height: 56px; border-radius: 8px;
}
/* Orbs hat keinen Canvas — die Vorschau wird direkt aus den Farben gemalt. */
.skin-bg-prev .prev-orb { position: absolute; border-radius: 50%; filter: blur(12px); opacity: 0.55; }

/* Block 2 — Presets, Farbfelder, Glas */
.skin-presets { display: flex; flex-wrap: wrap; gap: 6px; }
.skin-preset {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; font-size: 0.74rem;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--glass-border);
  border-radius: 999px; color: var(--text-dim); cursor: pointer;
}
.skin-preset:hover { border-color: rgba(255, 255, 255, 0.3); color: var(--text); }
.skin-preset.active { border-color: var(--accent); color: var(--text); }
.skin-swatch { width: 11px; height: 11px; border-radius: 50%; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35); }

.skin-fields { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; }
.skin-field { display: grid; gap: 5px; font-size: 0.74rem; color: var(--text-dim); }
.skin-field input[type="color"] {
  width: 54px; height: 30px; padding: 2px;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--glass-border);
  border-radius: 8px; cursor: pointer;
}
.skin-range { display: grid; gap: 5px; font-size: 0.74rem; color: var(--text-dim); flex: 1 1 150px; }
.skin-range input[type="range"] { accent-color: var(--accent); width: 100%; }

/* Kontrastanzeige — Ampel, kein Diagramm: Es geht nur um "reicht das?". */
.skin-contrast {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  font-size: 0.72rem; color: var(--text-dim);
  padding: 8px 10px; border-radius: 10px;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--glass-border);
}
.skin-contrast b { font-weight: 600; }
.skin-contrast .c-aaa { color: var(--accent); }
.skin-contrast .c-aa { color: #fbbf24; }
.skin-contrast .c-bad { color: var(--danger); }
.skin-contrast .c-note { flex-basis: 100%; opacity: 0.75; }

/* Block 3 — Hintergrundfarben */
.skin-seg { display: inline-flex; border: 1px solid var(--glass-border); border-radius: 10px; overflow: hidden; }
.skin-seg button {
  background: transparent; border: 0; color: var(--text-dim);
  padding: 6px 14px; font-size: 0.76rem; cursor: pointer;
}
.skin-seg button.active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--text); }
.skin-bgcolors { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }

/* Block 0 — Meine Presets (v0.18.2).
   Dieselben Chips wie die sechs eingebauten Presets: Sie tun dasselbe (einen
   Skin als Startpunkt setzen), also sollen sie auch gleich aussehen. */
.skin-mypresets { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.skin-mypresets .hint { font-size: 0.74rem; }
/* Ein Name darf höchstens 40 Zeichen haben (LIMITS.name) — das passt bei 375 px
   noch in eine Chip-Zeile. max-width als Fangnetz, damit ein Chip die Leiste
   auch dann nicht sprengt, wenn das Limit später steigt. */
.skin-mypreset { max-width: 100%; min-width: 0; text-align: left; }

.skin-pactions {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  font-size: 0.74rem; color: var(--text-dim);
}
.skin-pname { font-weight: 600; color: var(--text); }
.skin-pgroup { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.skin-pactions .btn { padding: 5px 11px; font-size: 0.74rem; }

/* Teilen — Codefeld + zwei Knöpfe */
.skin-share { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.skin-code {
  flex: 1 1 260px;
  min-width: 0;               /* sonst drückt der Code die Zeile auf */
  padding: 7px 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.76rem;
  color: var(--text);
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--glass-border);
  border-radius: 9px;
}
.skin-code:focus { outline: none; border-color: var(--accent); }
.skin-share .btn { padding: 7px 13px; font-size: 0.76rem; white-space: nowrap; }
.skin-share-hint { font-size: 0.72rem; margin: 0; opacity: 0.8; }

.skin-actions { flex-wrap: wrap; gap: 8px; }
.skin-actions .btn { font-size: 0.82rem; padding: 8px 14px; }
.skin-admin-actions { display: flex; gap: 8px; margin-right: auto; flex-wrap: wrap; }

/* Admin → Aussehen: Zustand der beiden Vorgaben */
.skin-admin { display: grid; gap: 6px; margin-bottom: 8px; }
.skin-admin-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 0.85rem; }
.skin-admin-label { min-width: 140px; }
.skin-admin-row .btn { padding: 5px 12px; font-size: 0.76rem; }

/* Mobil: Kacheln 2×2 statt 1×4, sonst sind sie 70 px breit und nichts erkennbar.
   MUSS nach den Basisregeln stehen (gleiche Spezifität → die spätere gewinnt);
   in v0.15.4 und v0.15.5 ist genau das je einmal schiefgegangen. */
@media (max-width: 720px) {
  .skin-bgs { grid-template-columns: repeat(2, 1fr); }
  .skin-modal { width: 94vw; padding: 18px 16px; }
  .skin-admin-label { min-width: 0; }
  .skin-actions .btn { flex: 1 1 auto; }
}

/* --- Login: epischer --- */
.auth-main { padding-top: 10vh; }
.auth-card {
  position: relative;
  box-shadow: 0 0 60px color-mix(in srgb, var(--accent) 10%, transparent), 0 8px 32px rgba(0, 0, 0, 0.35);
  border-color: rgba(255, 255, 255, 0.18);
  animation: card-rise 0.3s ease both;
}
.auth-card::before {
  content: 'host4k';
  position: absolute;
  top: -74px; left: 50%; transform: translateX(-50%);
  font-size: 2.6rem; font-weight: 800; letter-spacing: 0.04em;
  background: linear-gradient(120deg, var(--text) 20%, var(--accent) 80%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 4px 24px color-mix(in srgb, var(--accent) 25%, transparent));
}
.auth-card h2 { text-align: center; }
.auth-card .btn-primary { width: 100%; padding: 11px; font-size: 0.95rem; }
body[data-theme="ember"] .auth-card { box-shadow: 0 0 60px rgba(251, 191, 110, 0.10), 0 8px 32px rgba(0,0,0,0.35); }
body[data-theme="ocean"] .auth-card { box-shadow: 0 0 60px rgba(110, 198, 231, 0.10), 0 8px 32px rgba(0,0,0,0.35); }
body[data-theme="matrix"] .auth-card { box-shadow: 0 0 60px rgba(74, 222, 128, 0.12), 0 8px 32px rgba(0,0,0,0.35); }

/* v0.11 — Node-Cards, Bars, Pills, Sleep-Badge, Mods-Subtabs */
.nodes-cards { display: grid; gap: 14px; }
.node-card {
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.15);
  padding: 16px 18px;
  display: grid; gap: 12px;
}
.node-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pill {
  font-size: 0.7rem; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--glass-border);
}
.pill.ok { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.pill.bad { color: var(--danger); border-color: rgba(248, 113, 113, 0.4); }
.node-bars { display: grid; gap: 8px; }
.bar-row { display: grid; grid-template-columns: 82px 1fr auto; align-items: center; gap: 10px; font-size: 0.78rem; }
.bar-label { color: var(--text-dim); }
.bar {
  height: 8px; border-radius: 999px; overflow: hidden;
  background: rgba(255, 255, 255, 0.08);
}
.bar-fill {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 60%, transparent));
  transition: width 0.3s ease;
}
.bar-fill.hot { background: linear-gradient(90deg, #fbbf24, var(--danger)); }
.bar-val { color: var(--text-dim); white-space: nowrap; }
.node-edit { display: flex; gap: 10px; flex-wrap: wrap; }
.node-edit input[type="text"] { flex: 1; min-width: 140px; }
.node-edit input[type="number"] { width: 170px; }
.node-edit input.n-mac { flex: 0 1 190px; min-width: 170px; font-family: ui-monospace, monospace; }
/* WOL-Checkboxen an der Node-Karte (v0.15.1) */
.node-flag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.78rem; color: var(--text-dim); white-space: nowrap;
}

/* Schlafende Server: lila statt grau */
.state-badge[data-sleep="1"] {
  color: #c4b5fd; border-color: rgba(196, 181, 253, 0.45);
  box-shadow: 0 0 10px rgba(167, 139, 250, 0.15);
}

/* Mods-Subtabs etwas abgesetzt */
.mods-subtabs { margin-top: 0; padding-top: 0; border-top: none; margin-bottom: 10px; }

/* v0.13 — Upload-Progress + Void-Theme */
.up-progress { display: grid; gap: 6px; }
.up-bar {
  height: 10px; border-radius: 999px; overflow: hidden;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid var(--glass-border);
}
.up-fill {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--accent), rgba(255, 255, 255, 0.5));
  border-radius: 999px;
  transition: width 0.2s ease;
}
/* Unbestimmte Phase (Entpacken auf der Node / Proxy ohne Progress-Events):
   voller Balken, der ruhig pulsiert — KEIN laufender Streifen, der wie ein
   Zurückspringen aussieht. */
.up-fill.indet {
  width: 100% !important;
  background: linear-gradient(90deg, var(--accent), rgba(255, 255, 255, 0.5));
  animation: indet-pulse 1.4s ease-in-out infinite;
}
@keyframes indet-pulse { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }

/* ===== v0.17 ================================================================ */

/* Subuser: ein Recht je Tab → das Raster muss viele Haken tragen können, ohne
   die Karte zu sprengen. Feste Mindestbreite statt Umbruch mitten im Label. */
.su-perm-grid {
  display: grid; gap: 4px 14px;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  margin: 6px 0;
}
.su-new-head { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.subuser-row {
  border: 1px solid var(--glass-border); border-radius: 10px;
  padding: 8px 12px; margin-bottom: 8px;
}
.subuser-head { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.subuser-head .su-summary { flex: 1 1 200px; }
.su-editor { border-top: 1px solid var(--glass-border); margin-top: 8px; padding-top: 8px; }

/* Aufklappbare Blöcke im Settings-Tab (Welt & Generierung, Neustarts) */
.settings-block {
  border: 1px solid var(--glass-border); border-radius: 10px;
  padding: 8px 12px; margin: 12px 0;
}
.settings-block > summary {
  cursor: pointer; font-weight: 600; padding: 2px 0;
  list-style: none;
}
.settings-block > summary::-webkit-details-marker { display: none; }
.settings-block > summary::before { content: '▸ '; color: var(--text-dim); }
.settings-block[open] > summary::before { content: '▾ '; }
.world-reset-row {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  border-top: 1px solid var(--glass-border); margin-top: 10px; padding-top: 10px;
}
.world-reset-row .hint { flex: 1 1 240px; }
.rs-days { display: flex; gap: 10px; flex-wrap: wrap; margin: 6px 0; }
.rs-day { display: inline-flex; gap: 4px; align-items: center; font-size: 0.85rem; }
.modal-field { display: block; margin-top: 10px; font-size: 0.85rem; }
.modal-field input { width: 100%; margin-top: 4px; }

/* Node-Karte: Klartext-Zeilen unter dem Kopf (Standby-Restzeit, Blocker,
   offene Aufräum-Aufträge). Farbe trägt die Bedeutung, nicht nur der Text. */
.node-notes { display: grid; gap: 2px; margin: 4px 0 2px; }
.node-note { font-size: 0.78rem; color: var(--text-dim); }
.node-note.ok { color: var(--accent); }
.node-note.warn { color: #fbbf24; }
.node-note.bad { color: var(--danger); }

/* Monitoring */
.monitor-bar { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.mon-summary {
  display: grid; gap: 8px; margin-bottom: 12px;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}
.mon-stat {
  border: 1px solid var(--glass-border); border-radius: 10px;
  padding: 6px 10px; display: grid; gap: 2px;
}
.mon-stat span { font-size: 0.72rem; color: var(--text-dim); }
.mon-stat strong { font-size: 1.02rem; }
.mon-chart { margin-bottom: 14px; }
.mon-chart-head { display: flex; gap: 10px; align-items: baseline; margin-bottom: 2px; }
/* Die Zeichenfläche gibt nur die Breite vor — das SVG bekommt seine Maße in
   echten Pixeln von drawChart(). Kein width:100% am SVG: Das würde es wieder
   strecken, und genau davon wollten wir weg (verzerrte Schrift, ovale Punkte). */
.mon-canvas { width: 100%; line-height: 0; }
.mon-chart svg { display: block; max-width: 100%; }
.mon-axis { font-size: 9px; fill: var(--text-dim); }
.mon-chart-hint { margin: 2px 0 0; }
/* Der Zeitzeiger sitzt im SVG und wird nur ein-/ausgeblendet, nicht neu
   gezeichnet — bei jeder Mausbewegung ein SVG zu bauen wäre Verschwendung. */
.mon-cursor { pointer-events: none; }
/* Bezugsrahmen für den Tooltip weiter unten. */
.monitor-wrap { position: relative; }
.mon-tip {
  position: absolute; z-index: 5;
  /* Ohne das flieht der Tooltip vor dem eigenen Mauszeiger: Er läge unter dem
     Zeiger, würde pointerleave am Diagramm auslösen und sich selbst schließen. */
  pointer-events: none;
  min-width: 132px; padding: 7px 9px;
  border: 1px solid var(--glass-border); border-radius: 10px;
  background: color-mix(in srgb, var(--glass-bg) 55%, rgba(6, 8, 16, 0.93));
  backdrop-filter: blur(8px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.38);
  font-size: 0.78rem; line-height: 1.4;
}
.mon-tip-time { color: var(--text-dim); font-size: 0.72rem; margin-bottom: 4px; }
.mon-tip-row { display: flex; justify-content: space-between; gap: 14px; }
.mon-tip-row span { color: var(--text-dim); }

/* Versionsauswahl (v0.17.4): das Feld fuer eine eigene Eingabe steht unter
   der Auswahl und erscheint nur, wenn man "Eigene Eingabe…" waehlt. */
.version-custom { margin-top: 4px; width: 100%; }

/* Pregen */
.pregen-status { margin-bottom: 10px; }
.pg-status-head { display: flex; gap: 10px; align-items: baseline; margin-bottom: 6px; }
.pg-line {
  margin: 6px 0 0; padding: 6px 8px; border-radius: 8px;
  background: rgba(0, 0, 0, 0.28); font-size: 0.74rem;
  white-space: pre-wrap; word-break: break-word; color: var(--text-dim);
}
.glass-inner {
  border: 1px solid var(--glass-border); border-radius: 10px; padding: 10px 12px;
}

/* Einstellungsblock, dessen Schalter gerade aus ist: sichtbar, aber erkennbar
   wirkungslos — besser als ihn zu verstecken (dann fragt man sich, wo er hin ist). */
.disabled-block { opacity: 0.45; }
.disabled-block input { cursor: not-allowed; }

/* Audit-Log */
.log-filter { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 10px; }
.log-filter input[type="text"] { min-width: 220px; flex: 1 1 220px; }
#log-table td { vertical-align: top; font-size: 0.8rem; }
.log-time { white-space: nowrap; color: var(--text-dim); }
.log-detail { max-width: 460px; word-break: break-word; color: var(--text-dim); }
.log-failed td { background: color-mix(in srgb, var(--danger) 12%, transparent); }
.log-more { display: flex; gap: 12px; align-items: center; margin-top: 10px; }

/* Startsperre am Status-Badge (TK-Punkt 0) — bewusst NICHT rot: Das ist ein
   gewollter Zustand, kein Fehler. */
.state-badge[data-blocked="1"] {
  background: color-mix(in srgb, #fbbf24 22%, transparent);
  border-color: color-mix(in srgb, #fbbf24 50%, transparent);
  color: #fbbf24;
}

/* v0.14.4 — Mod-Detailansicht (Overlay) */
.mod-detail-backdrop {
  position: fixed; inset: 0; z-index: 900;
  background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(4px);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.mod-detail {
  position: relative; width: min(760px, 94vw); max-height: 86vh;
  overflow-y: auto; padding: 22px;
}
.mod-detail-close { position: absolute; top: 12px; right: 12px; padding: 4px 10px; }
.mod-detail-head { display: flex; gap: 16px; align-items: flex-start; margin-bottom: 12px; }
.mod-detail-icon { width: 72px; height: 72px; border-radius: 12px; flex-shrink: 0; object-fit: cover; }
.mod-detail-head h3 { margin: 0 0 4px; }
.mod-detail-stats { margin: 6px 0 0; }
.mod-detail-links { margin: 6px 0 0; font-size: 0.85rem; }
.mod-detail-links a { color: var(--accent); }
.mod-detail-gallery {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 8px; margin: 10px 0 14px;
}
.mod-detail-gallery img { width: 100%; border-radius: 8px; }
.mod-detail-body { font-size: 0.88rem; line-height: 1.55; color: var(--text-dim); }
.mod-detail-body h3, .mod-detail-body h4 { color: var(--text); margin: 14px 0 6px; }
.mod-detail-body p { margin: 8px 0; }
.mod-detail-body a { color: var(--accent); }
.mod-detail-body code { background: rgba(255,255,255,0.08); padding: 1px 5px; border-radius: 5px; }
.mod-detail-body .md-img { max-width: 100%; border-radius: 8px; margin: 6px 0; }
.mod-clickable { cursor: pointer; }
.mod-clickable:hover .mod-name, .mod-name.mod-clickable:hover { color: var(--accent); text-decoration: underline; }

/* v0.14.4 — Modpack-Import-Zeile */
.mods-pack-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 10px 0; }

/* v0.14.5 — deaktivierte Mods + Suchen */
.mod-disabled-row { opacity: 0.55; }
.mod-off-tag { color: #fbbf24; flex-shrink: 0; }
.mods-installed-search { margin: 0 0 10px; width: min(340px, 100%); }
.admin-server-filter { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.admin-server-filter input { width: min(280px, 100%); }

/* v0.14.3 — Passwort anzeigen/verbergen (Login) */
.pw-wrap { position: relative; display: block; }
.pw-wrap input { width: 100%; padding-right: 40px; }
.pw-toggle {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  background: none; border: none; cursor: pointer;
  font-size: 1rem; line-height: 1; padding: 4px 6px;
  opacity: 0.55; transition: opacity 0.15s ease;
}
.pw-toggle:hover { opacity: 1; }
.pw-toggle.active { opacity: 1; filter: drop-shadow(0 0 4px var(--accent)); }

/* v0.14.3 — Admin-Tabelle: Server-Karte ausklappen */
.srv-expand { padding: 2px 9px; font-size: 0.75rem; margin-right: 6px; }
.admin-card-row > td { padding: 10px 4px 16px; }
.admin-card-row .server-card { margin: 0; }

/* v0.14.3 — "Neustart übernimmt Änderungen"-Badge */
.pending-restart-badge {
  padding: 4px 10px; border-radius: 999px; font-size: 0.74rem; font-weight: 600;
  color: #fbbf24; border: 1px solid rgba(251, 191, 36, 0.45);
  background: rgba(251, 191, 36, 0.12);
  white-space: nowrap; cursor: help; margin-left: auto; margin-right: 8px;
  animation: pending-pulse 2.4s ease-in-out infinite;
}
@keyframes pending-pulse { 0%, 100% { opacity: 0.75; } 50% { opacity: 1; } }

/* v0.14.2 — Server-Icon-Box (Settings-Tab) */
.icon-box {
  display: flex; align-items: center; gap: 14px; margin-bottom: 16px;
  padding: 12px; border: 1px solid var(--glass-border); border-radius: 12px;
  background: rgba(0, 0, 0, 0.15);
}
.server-icon-preview, .server-icon-placeholder {
  width: 64px; height: 64px; flex-shrink: 0; border-radius: 8px;
  border: 1px solid var(--glass-border); image-rendering: pixelated;
}
.server-icon-placeholder {
  display: flex; align-items: center; justify-content: center;
  font-size: 0.7rem; color: var(--muted, #8a95a5); background: rgba(255, 255, 255, 0.04);
}
.icon-box-side { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.icon-box-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.icon-box-actions .btn { padding: 6px 12px; font-size: 0.8rem; }

/* v0.14.2 — Backup-Snapshot-Liste */
.backups-snaps { display: grid; gap: 6px; margin-top: 12px; max-height: 320px; overflow-y: auto; }
.backup-row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 10px; border: 1px solid var(--glass-border); border-radius: 10px;
  font-size: 0.86rem; background: rgba(0, 0, 0, 0.15);
}
.backup-when { font-weight: 600; }
.backup-label { color: var(--accent); }
/* Der Auslöser steht als ruhige Pille neben der Uhrzeit: Er beantwortet die
   Frage "warum gibt es diesen Snapshot?", soll aber nicht mit dem Zeitpunkt
   um Aufmerksamkeit konkurrieren. */
.backup-origin {
  font-weight: 400; font-size: 0.72rem; color: var(--text-dim);
  border: 1px solid var(--glass-border); border-radius: 999px;
  padding: 1px 8px; margin-left: 6px; white-space: nowrap;
}
.backup-size { margin-left: auto; }
.backup-row .btn { padding: 6px 12px; font-size: 0.78rem; flex-shrink: 0; }
.backup-rename { padding: 4px 8px !important; }
.backup-keep-label {
  display: inline-flex; align-items: center; gap: 5px;
  white-space: nowrap; cursor: pointer; flex-shrink: 0;
}
.backup-keep-label input { accent-color: var(--accent); }

/* v0.14.7 — Kopfzeile (Anzahl + Aufräumen) und "Mehr laden" der Snapshot-Liste */
.backups-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 4px 2px 6px;
  /* .backups-snaps scrollt — die Kopfzeile bleibt oben stehen */
  position: sticky; top: 0; z-index: 1;
  background: var(--glass-bg, rgba(0, 0, 0, 0.35));
  backdrop-filter: blur(6px);
}
.backups-count { font-weight: 600; }
.backups-head .btn { padding: 6px 12px; font-size: 0.78rem; margin-left: auto; }
.backups-head .btn + .btn { margin-left: 0; }
.backups-rows { display: grid; gap: 6px; }
.backups-more { display: flex; justify-content: center; padding: 8px 0 2px; }
.backups-more .btn { padding: 6px 14px; font-size: 0.78rem; }

/* Void — das richtig dunkle Theme (OLED-schwarz, ruhig, präzise) */
body[data-theme="void"] {
  --accent: #7dd3fc;
  --glass-bg: rgba(255, 255, 255, 0.045);
  --glass-border: rgba(255, 255, 255, 0.09);
  --text: #e6e9ef;
  --text-dim: #8b93a3;
  background: linear-gradient(160deg, #050608 0%, #08090c 55%, #060709 100%);
}
body[data-theme="void"] .orb { opacity: 0.14; }
body[data-theme="void"] .orb-1 { background: var(--orb-1, #1e293b); }
body[data-theme="void"] .orb-2 { background: var(--orb-2, #0f2c33); }
body[data-theme="void"] .orb-3 { background: var(--orb-3, #171b30); }
body[data-theme="void"] .glass {
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(18px);
}
body[data-theme="void"] select option { background: #0a0b0e; }
body[data-theme="void"] .console-out { background: rgba(0, 0, 0, 0.7); }
body[data-theme="void"] .btn-primary {
  background: linear-gradient(135deg, rgba(125, 211, 252, 0.20), rgba(125, 211, 252, 0.08));
  border-color: rgba(125, 211, 252, 0.4);
}
body[data-theme="void"] .state-badge[data-state="running"],
body[data-theme="void"] .state-badge[data-state="online"] {
  color: #7dd3fc; border-color: rgba(125, 211, 252, 0.5);
  box-shadow: 0 0 12px rgba(125, 211, 252, 0.2);
}
/* void ist selbst blau — Standby dort violett, damit es unterscheidbar bleibt */
body[data-theme="void"] .state-badge[data-state="sleeping"] {
  color: #c4b5fd; border-color: rgba(196, 181, 253, 0.5);
  box-shadow: 0 0 10px rgba(167, 139, 250, 0.18);
}
body[data-theme="void"] .auth-card { box-shadow: 0 0 70px rgba(125, 211, 252, 0.08), 0 8px 32px rgba(0,0,0,0.5); }
body[data-theme="void"] .bar-fill { background: linear-gradient(90deg, #7dd3fc, rgba(125, 211, 252, 0.5)); }

/* Ideen & Feature-Requests (v0.18) */
.feat-head { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 4px; }
.feat-head h2 { margin: 0; font-size: 1.15rem; }
#feat-intro { margin: 0 0 12px; max-width: 62ch; }

#feature-form { margin-bottom: 16px; display: grid; gap: 10px; }
#feature-form textarea { width: 100%; resize: vertical; }

.feat-bar {
  display: flex; gap: 16px; align-items: center; flex-wrap: wrap;
  margin: 4px 0 12px; padding-bottom: 10px;
  border-bottom: 1px solid var(--glass-border);
}

.feat-card {
  display: flex; gap: 14px; align-items: flex-start;
  border: 1px solid var(--glass-border); border-radius: 14px;
  padding: 12px 14px; margin-bottom: 10px;
  background: color-mix(in srgb, var(--glass-bg) 45%, transparent);
}
.feat-main { flex: 1; min-width: 0; } /* min-width: 0 → lange Wörter sprengen die Karte nicht */

/* Der Stimmknopf ist die Hauptaktion und steht deshalb links, wo das Auge
   zuerst hinfällt — und er zeigt den eigenen Zustand, nicht nur die Zahl. */
.feat-vote {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  min-width: 52px; padding: 6px 4px;
  border: 1px solid var(--glass-border); border-radius: 10px;
  background: transparent; color: var(--text-dim);
  cursor: pointer; font: inherit; line-height: 1.1;
  transition: border-color .15s, color .15s, background .15s;
}
.feat-vote:hover { color: var(--text); border-color: color-mix(in srgb, var(--accent) 50%, transparent); }
.feat-vote.voted {
  color: var(--accent);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.feat-vote-arrow { font-size: 0.7rem; }
.feat-vote-n { font-size: 1.02rem; font-weight: 600; }

.feat-title-row { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.feat-title { font-size: 1rem; }
.feat-body { margin: 4px 0 2px; white-space: pre-wrap; overflow-wrap: anywhere; }
.feat-meta { margin-top: 2px; }

.feat-status {
  font-size: 0.7rem; padding: 1px 9px; border-radius: 999px;
  border: 1px solid var(--glass-border); color: var(--text-dim); white-space: nowrap;
}
.feat-st-geplant { color: #7cc5ff; border-color: color-mix(in srgb, #7cc5ff 45%, transparent); }
.feat-st-umgesetzt { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.feat-st-abgelehnt { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }

.feat-note {
  margin: 6px 0 2px; padding: 7px 10px;
  border-left: 3px solid var(--accent); border-radius: 0 8px 8px 0;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  font-size: 0.85rem;
}

.feat-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.feat-actions .btn { padding: 5px 11px; font-size: 0.76rem; }

.feat-comments { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--glass-border); }
.feat-comment { margin-bottom: 9px; }
.feat-comment-head { display: flex; align-items: center; gap: 6px; }
.feat-comment-body { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 0.88rem; }
.feat-comment-del {
  background: none; border: none; color: var(--text-dim);
  cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 2px;
}
.feat-comment-del:hover { color: var(--danger); }
.feat-comment-form { display: flex; gap: 8px; align-items: flex-start; margin-top: 8px; }
.feat-comment-form textarea { flex: 1; resize: vertical; }

/* Auf dem Handy wandert der Stimmknopf nach oben neben den Titel — sonst
   bliebe für den Text eine Spalte von wenigen Zentimetern. */
@media (max-width: 560px) {
  .feat-card { gap: 10px; padding: 10px 11px; }
  .feat-vote { min-width: 44px; flex-direction: row; gap: 5px; padding: 4px 8px; }
  .feat-comment-form { flex-direction: column; }
  .feat-comment-form .btn { align-self: flex-end; }
}
