/* ===========================================================================
   ManiaMods Portal, Oberflaeche
   ---------------------------------------------------------------------------
   Dunkel ist der einzige Modus, es gibt keinen Hell-Umschalter.

   Farbaufbau: neutrales Anthrazit als Grund, Bernstein als einziger
   Markenakzent, dazu drei Bedeutungsfarben (gut, Warnung, Gefahr). Die Marke
   traegt die Farbe, die Flaechen bleiben ruhig.

   Schrift: IBM Plex, mitgeliefert unter portal/fonts. Vorher lief alles auf
   Systemschriften, die Wortmarke also auf Palatino unter Windows und auf
   Georgia unter iOS: die Marke sah auf jedem Geraet anders aus. Plex bringt
   Sans, Mono und Serif aus einer Hand, hat saubere Umlaute und echte
   Tabellenziffern, und die Dateien liegen lokal, damit die Seite auch ohne
   Internet richtig aussieht. Nur der lateinische Zeichenbereich, 168 KB.
   =========================================================================== */

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/portal/static/fonts/plex-sans-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/portal/static/fonts/plex-sans-500.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/portal/static/fonts/plex-sans-600.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/portal/static/fonts/plex-mono-400.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Serif";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/portal/static/fonts/plex-serif-600.woff2") format("woff2");
}

:root {
  color-scheme: dark;

  /* Flaechen, von unten nach oben.
     Alle neutralen Toene sind leicht warm gehalten, Rot >= Gruen >= Blau. Ein
     kuehles Grau kippt neben gesaettigtem Gruen oder Rot im Auge ins Violette;
     genau das war neben der Statuslampe der Serverseite als lila Schimmer zu
     sehen. Warm gehaltene Neutraltoene koennen das nicht, und sie passen
     besser zum bernsteinfarbenen Markenakzent. */
  --bg: #100f0e;
  --surface: #191817;
  --surface-2: #201f1d;
  --surface-3: #282623;
  --line: #302d29;
  --line-soft: #252320;

  /* Schrift */
  --ink: #efeeeb;
  --muted: #a5a099;
  /* Der leiseste Textton muss auf der hellsten Flaeche (--surface-2, #201f1d)
     noch 4,5:1 erreichen, geprueft im Browser ueber tests/test_kontrast.py. */
  --faint: #948e86;

  /* Marke und Bedeutung */
  --accent: #e0a94a;
  --accent-soft: #8a6a2c;
  --accent-ink: #191204;
  --good: #6fbf8f;
  --warn: #e0a94a;
  --danger: #e2604a;
  --info: #6aa6d8;

  /* Masse */
  --r-sm: 5px;
  --r: 8px;
  --r-lg: 12px;
  --gap: 1rem;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.28);

  --sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --serif: "IBM Plex Serif", "Palatino Linotype", Georgia, serif;
  --mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  color: var(--ink);
  background: var(--bg);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  overscroll-behavior-y: contain;
  /* Nichts darf die Seite seitlich verschieben. Wo etwas breiter ist als der
     Bildschirm, scrollt es in seinem eigenen Kasten (Tabellen, Leisten). */
  overflow-x: hidden;
}

body {
  /* Die Seite fuellt die Fensterhoehe, damit die Fusszeile unten sitzt und
     nicht auf halber Strecke in einer leeren Flaeche haengt. */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background-image:
    radial-gradient(900px 500px at 85% -10%, rgba(224, 169, 74, 0.06), transparent 60%),
    radial-gradient(700px 420px at 0% 100%, rgba(111, 191, 143, 0.04), transparent 55%);
  background-attachment: fixed;
}

a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
::selection { background: rgba(224, 169, 74, 0.28); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.hidden { display: none !important; }
/* Das hidden-Attribut ist nur eine Browservorgabe und verliert gegen jede
   Klassenregel mit eigener display-Angabe. Auf der Startseite blieb dadurch
   der Hub-Link sichtbar, obwohl das Skript ihn versteckt hatte. */
[hidden] { display: none !important; }
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------- Kopfzeile

   Drei Bereiche mit klarer Aufgabe: links die Marke mit dem Namen der Seite,
   in der Mitte die Navigation, rechts das Konto. Vorher stand alles in einer
   Reihe mit gleichem Abstand, dadurch las sich der Nutzername wie ein weiterer
   Menuepunkt. Eine feine Linie trennt Navigation und Konto.

   Alle Bedienelemente im Kopf sind 34 Pixel hoch. Vorher war der Sprachschalter
   28 und der Abmeldeknopf 40 Pixel hoch, das war die Unruhe in der Zeile.
   --------------------------------------------------------------------------- */
.site-top {
  position: sticky;
  top: 0;
  z-index: 20;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  padding: 0.8rem clamp(1rem, 3vw, 2rem);
  padding-top: calc(0.8rem + env(safe-area-inset-top));
  padding-left: calc(clamp(1rem, 3vw, 2rem) + env(safe-area-inset-left));
  padding-right: calc(clamp(1rem, 3vw, 2rem) + env(safe-area-inset-right));
  background: rgba(16, 15, 14, 0.86);
  backdrop-filter: blur(14px) saturate(1.2);
  border-bottom: 1px solid var(--line-soft);
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
}
.brand-logo {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  display: block;
  flex-shrink: 0;
  object-fit: cover;
  background: #0b0b0c;
}
.brand-mark {
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--accent);
  white-space: nowrap;
}
.brand-sub {
  padding-left: 0.75rem;
  border-left: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.site-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.15rem;
  min-width: 0;
}
/* Knoepfe in der Kopfzeile sind ausgenommen: sonst gewinnt die Farbe des
   Navigationslinks gegen .btn-primary, und der Knopf steht hell auf hell. */
.site-nav > a:not(.btn) {
  display: inline-flex;
  align-items: center;
  height: 34px;
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 500;
  padding: 0 0.85rem;
  border-radius: 999px;
  white-space: nowrap;
  transition: color 0.14s ease, background 0.14s ease;
}
.site-nav > a:not(.btn):hover { color: var(--ink); background: var(--surface-2); }
.site-nav > a.is-active {
  color: var(--accent);
  background: rgba(224, 169, 74, 0.12);
}

.site-account {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding-left: clamp(0.8rem, 2vw, 1.3rem);
  border-left: 1px solid var(--line-soft);
  min-width: 0;
}
.user-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 500;
  max-width: 18ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Ein kleiner Kreis macht aus dem blossen Namen sichtbar ein Konto. */
.user-chip::before {
  content: "";
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: linear-gradient(140deg, var(--accent) 0%, var(--accent-soft) 100%);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35);
}
.site-account .btn {
  height: 34px;
  padding: 0 0.95rem;
  border-radius: 999px;
}

/* Sprachumschalter */
.lang-switch {
  display: inline-flex;
  align-items: stretch;
  height: 34px;
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
}
.lang-btn {
  display: inline-flex;
  align-items: center;
  background: transparent;
  border: 0;
  /* --faint kam hier nur auf 3,75:1, gemessen im Browser. */
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  padding: 0 0.7rem;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.14s ease, background 0.14s ease;
}
.lang-btn:hover { color: var(--ink); background: var(--surface-2); }
.lang-btn.is-active { background: var(--accent); color: var(--accent-ink); }

/* ------------------------------------------------------------------ Knoepfe */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--ink);
  padding: 0.5rem 0.9rem;
  border-radius: var(--r-sm);
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.btn:hover { background: var(--surface-3); }
.btn:active { transform: translateY(1px); }
.btn[disabled] { opacity: 0.4; cursor: default; pointer-events: none; }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 650;
}
.btn-primary:hover { background: #edb659; border-color: #edb659; }

.btn-ghost { background: transparent; color: var(--muted); }
.btn-ghost:hover { background: var(--surface-2); color: var(--ink); }

.btn-danger { border-color: rgba(226, 96, 74, 0.5); color: #f0a596; background: transparent; }
.btn-danger:hover { background: rgba(226, 96, 74, 0.16); border-color: var(--danger); color: #ffd2c8; }

.btn-go { border-color: rgba(111, 191, 143, 0.5); color: #a6dcc0; background: transparent; }
.btn-go:hover { background: rgba(111, 191, 143, 0.16); border-color: var(--good); }

.btn-stop { border-color: rgba(226, 96, 74, 0.5); color: #f0a596; background: transparent; }
.btn-stop:hover { background: rgba(226, 96, 74, 0.16); border-color: var(--danger); }

.btn-update { border-color: var(--accent-soft); color: var(--accent); background: transparent; }
.btn-update:hover { background: rgba(224, 169, 74, 0.14); border-color: var(--accent); }

/* ------------------------------------------------------------- Seitenaufbau */
.hub, .admin {
  flex: 1 0 auto;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  padding: clamp(1.5rem, 4vw, 2.5rem) clamp(1rem, 3vw, 2rem) 4rem;
  padding-left: calc(clamp(1rem, 3vw, 2rem) + env(safe-area-inset-left));
  padding-right: calc(clamp(1rem, 3vw, 2rem) + env(safe-area-inset-right));
  padding-bottom: calc(4rem + env(safe-area-inset-bottom));
}
.admin-wide { max-width: 1320px; }
/* Die ATLAS-AI-Brain-Ansicht bekommt einen eigenen Bereich statt eines Reiters
   unter Server, damit ihr die volle Breite bleibt: eine Karte, die man abfliegt,
   lebt vom Bild und nicht vom Rand daneben. */
/* Der Bereich fuellt genau das Fenster: Kopfleiste und Bereichsleiste stehen
   darueber, alles andere gehoert dem Bild. Als Spalte gebaut statt mit einer
   ausgerechneten Hoehe, damit Ueberschrift und Tastenzeile ihren Platz selbst
   nehmen und die Buehne den Rest bekommt, egal wie hoch das Fenster ist. */
.admin-voll {
  max-width: none;
  padding: 14px 16px 16px;
  height: calc(100vh - 113px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.hub-intro-schmal { margin-bottom: 10px; flex: 0 0 auto; }
.hub-intro-schmal h1 { margin-bottom: 0; }

.hub-intro { margin: 0 0 1.6rem; }
.hub-intro h1 {
  font-size: clamp(1.6rem, 3vw, 2.1rem);
  font-weight: 620;
  letter-spacing: -0.02em;
  margin: 0 0 0.3rem;
  text-wrap: balance;
}
.hub-intro p, .status-line, .lede, .section-lede {
  color: var(--muted);
  margin: 0;
  max-width: 68ch;
}
.status-line { font-size: 0.9rem; margin: 0.9rem 0 1.2rem; }

/* Unternavigation als Pillenleiste */
.admin-subnav {
  position: sticky;
  top: 57px;
  z-index: 15;
  display: flex;
  gap: 0.25rem;
  padding: 0.5rem clamp(1rem, 3vw, 2rem);
  padding-left: calc(clamp(1rem, 3vw, 2rem) + env(safe-area-inset-left));
  padding-right: calc(clamp(1rem, 3vw, 2rem) + env(safe-area-inset-right));
  background: rgba(16, 15, 14, 0.82);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line-soft);
  overflow-x: auto;
  scrollbar-width: none;
}
.admin-subnav::-webkit-scrollbar { display: none; }
.admin-subnav a {
  color: var(--muted);
  font-size: 0.9rem;
  padding: 0.4rem 0.75rem;
  border-radius: 999px;
  white-space: nowrap;
  touch-action: manipulation;
}
.admin-subnav a:hover { color: var(--ink); background: var(--surface-2); }
.admin-subnav a.is-active {
  color: var(--accent-ink);
  background: var(--accent);
  font-weight: 600;
}

/* -------------------------------------------------------------------- Karten */
.hub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--gap);
}
.hub-card {
  display: grid;
  align-content: start;
  gap: 0.4rem;
  padding: 1.3rem 1.2rem 1.4rem;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  min-height: 168px;
  transition: border-color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.hub-card:hover {
  border-color: var(--accent-soft);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}
.hub-card-kicker {
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}
.hub-card strong { font-size: 1.25rem; font-weight: 620; letter-spacing: -0.01em; }
.hub-card span:last-child { color: var(--muted); font-size: 0.92rem; }
.hub-card-muted { opacity: 1; }
.hub-card-locked { opacity: 0.6; cursor: not-allowed; border-style: dashed; }
.hub-card-locked:hover { transform: none; border-color: var(--line); box-shadow: none; }
.hub-card-locked strong::after {
  content: " VIP";
  color: var(--accent);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  vertical-align: super;
}

/* ------------------------------------------------------------------ Tabellen */
.table-wrap {
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  background: var(--surface);
}
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}
.data-table th, .data-table td {
  text-align: left;
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--line-soft);
  vertical-align: middle;
}
.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-2);
  /* Spaltenkoepfe sind klein und gesperrt gesetzt, --faint lag bei 3,29:1. */
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  border-bottom: 1px solid var(--line);
}
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr:hover td { background: rgba(255, 255, 255, 0.025); }
.data-table td small { color: var(--faint); font-size: 0.78rem; }

.th-sort {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.th-sort:hover { color: var(--accent); }
.th-sort.is-sorted { color: var(--accent); }
.th-sort.is-sorted::after { content: "\25B2"; font-size: 0.55em; }
.th-sort.is-sorted[data-dir="desc"]::after { content: "\25BC"; }

/* Wichtig: in einer Tabelle bleibt die Aktionsspalte eine echte Zelle.
   `display: flex` nimmt sie aus dem Tabellenmodell heraus, sie richtet sich
   dann nicht mehr nach der Zeilenhoehe und der eingefaerbte Grund gebannter
   Zeilen brach mit einer sichtbaren Kante ab. Auf dem Telefon wird die Zelle
   ohnehin zum Block, dort greift die Regel weiter unten. */
.data-table td.actions {
  text-align: right;
  white-space: nowrap;
  vertical-align: middle;
}
.actions .btn { padding: 0.32rem 0.6rem; font-size: 0.82rem; }
/* Gleiche Breite fuer alle Knoepfe der Zeile: sonst schiebt das laengere Wort
   "Entbannen" die Knoepfe daneben nach links, und die Spalte steht schief. */
.data-table td.actions .btn {
  min-width: 5.8rem;
  margin-left: 0.3rem;
}
.data-table td.actions .btn:first-child { margin-left: 0; }

.ok { color: var(--good); }
.no { color: var(--faint); }
.muted { color: var(--muted); }
.meta { color: var(--faint); font-size: 0.8rem; }

.ban-badge {
  display: inline-block;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: rgba(226, 96, 74, 0.16);
  border: 1px solid rgba(226, 96, 74, 0.45);
  color: #f2b0a2;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  font-weight: 650;
}
.row-banned td { background: rgba(226, 96, 74, 0.05); }

/* --------------------------------------------------- Filterleiste und Seiten */
.list-filter, .garage-filter {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  margin: 0 0 0.8rem;
}
.list-filter-search, .garage-filter-search { flex: 1 1 260px; max-width: 420px; display: block; }
.list-filter-search input, .garage-filter-search input,
.assign-form input, .assign-form select,
.srv-fields input, .srv-fields select, .srv-fields textarea,
.garage-form input, .garage-form select, .garage-form textarea {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 0.5rem 0.65rem;
  color: var(--ink);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.list-filter-search input::placeholder, .garage-filter-search input::placeholder { color: var(--faint); }
input:focus-visible, select:focus-visible, textarea:focus-visible {
  border-color: var(--accent);
  outline: 2px solid rgba(224, 169, 74, 0.3);
  outline-offset: 0;
}
.list-filter-chips { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.list-filter-chips .btn { padding: 0.4rem 0.75rem; font-size: 0.85rem; border-radius: 999px; }
.list-filter-chips .btn.is-active {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(224, 169, 74, 0.12);
}

.list-pager {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  justify-content: center;
  margin: 1rem 0 0;
  flex-wrap: wrap;
}
.list-pager .status-line { margin: 0; font-variant-numeric: tabular-nums; }
#garage-count { margin: 0; white-space: nowrap; font-size: 0.85rem; }

/* ------------------------------------------------------------------ Formulare */
.assign-form, .garage-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0.8rem;
  align-items: end;
  padding: 1.1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.assign-form label, .garage-form label, .srv-fields label {
  display: grid;
  gap: 0.3rem;
  font-size: 0.8rem;
  color: var(--muted);
}
.form-actions, .ai-form-actions, .srv-check-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
}
.check, .srv-check, .toggle {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9rem;
  color: var(--ink);
}
.check input, .srv-check input { width: 1rem; height: 1rem; accent-color: var(--accent); }

.admin-panel h2 {
  font-size: 1.05rem;
  font-weight: 620;
  letter-spacing: -0.01em;
  margin: 1.8rem 0 0.7rem;
}
.admin-panel h2:first-child { margin-top: 0; }

.inline-role { color: var(--accent); font-weight: 600; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  font-size: 0.78rem;
  color: var(--muted);
}
.chip-row { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.chip-row-inline { display: inline-flex; flex-wrap: wrap; gap: 0.3rem; }

/* --------------------------------------------------------------- Startseite */
/* Held, Abschnitte und Fusszeile teilen sich eine Spalte von 1100 px und
   damit dieselbe linke Kante. Vorher stand der Held am Seitenrand bei 64 px,
   die Abschnitte darunter zentriert bei 423 px: vier verschiedene Kanten auf
   einer Seite. Die Randflaechen kommen aus der Polsterung, damit farbige
   Abschnitte weiterhin ueber die volle Breite laufen. */
.page-home .hero,
.page-home .section,
.page-home .site-foot {
  /* 1180 px: der Satz im Zugangsband braucht neben dem Knopf 1118 px, mit
     1100 px brach er auf zwei Zeilen um. Gemessen im Browser. */
  padding-left: max(clamp(1.25rem, 5vw, 4rem), calc((100% - 1180px) / 2));
  padding-right: max(clamp(1.25rem, 5vw, 4rem), calc((100% - 1180px) / 2));
}
.page-home .section {
  max-width: none;
  margin: 0;
}
/* Die Startseite soll ohne Scrollen lesbar sein. Alle Hoehen und Abstaende
   haengen deshalb an der Fensterhoehe (vh) und schrumpfen auf flachen
   Bildschirmen mit. Gemessen bei 1718x1312: vorher 1675 px Gesamthoehe bei
   1312 px Fenster, also 363 px zu viel. */
.page-home .hero {
  min-height: min(38vh, 420px);
  min-height: min(38dvh, 420px);
  /* Auf hohen Bildschirmen bleibt Platz uebrig, weil die Fusszeile unten
     klebt. Den bekommt der Held, sonst stand zwischen Zugangsband und
     Fusszeile eine leere Flaeche von rund 380 px. */
  flex: 1 1 auto;
  display: grid;
  align-items: center;
  padding-top: clamp(0.75rem, 2.5vh, 2rem);
  padding-bottom: clamp(0.75rem, 2.5vh, 2rem);
}
.page-home .brand-hero-logo {
  width: clamp(5.5rem, 12vw, 8rem);
  height: clamp(5.5rem, 12vw, 8rem);
  border-radius: 50%;
  display: block;
  margin: 0 0 0.7rem;
  object-fit: cover;
  background: #0b0b0c;
}
.page-home .hero h1 {
  font-size: clamp(1.35rem, 2.6vw, 2rem);
  margin: 0 0 0.5rem;
}
.page-home .lede { font-size: 1rem; margin: 0 0 0.9rem; }
.page-home .section {
  padding-top: clamp(0.9rem, 3vh, 2.25rem);
  padding-bottom: clamp(0.9rem, 3vh, 2.25rem);
}
.page-home .section h2 { margin-top: 0; }
/* Voller Zeilenlauf: mit der engen Lesebreite brach die Zeile um und kostete
   eine ganze Textzeile Hoehe, ohne dass es der Lesbarkeit half. */
.page-home .section-lede { margin-bottom: 0.8rem; max-width: none; }
/* Zwei Spalten statt vier Balken untereinander. Bewusst genau zwei und nicht
   auto-fit: bei drei Spalten stand das vierte Merkmal allein in der zweiten
   Reihe. Vier Eintraege gehen in zwei Spalten immer glatt auf. */
.page-home .feature-list {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
}
@media (max-width: 720px) {
  .page-home .feature-list { grid-template-columns: 1fr; }
}
.page-home .feature-list li { padding: 0.65rem 0.85rem; }
/* Der Zugang war ein eigener Block mit Ueberschrift, Fliesstext und Knopf und
   wiederholte damit nur den Aufruf aus dem Held. Als Zeile kostet er statt
   225 px noch rund 90 px, ohne dass Inhalt verlorengeht. */
.page-home .access-band {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem 2rem;
  flex-wrap: wrap;
}
.page-home .access-band .section-lede { margin: 0; color: var(--ink); }
.page-home .access-copy { min-width: 0; flex: 1 1 22rem; }
.page-home .site-foot { padding-top: 1rem; padding-bottom: 1rem; }
/* Auf flachen Bildschirmen schrumpft der Held weiter mit. */
.page-home .hero { min-height: min(34dvh, 420px); }
.hero-copy { max-width: 62ch; }
.brand-hero {
  font-family: var(--serif);
  font-size: clamp(3rem, 11vw, 6.5rem);
  line-height: 0.95;
  letter-spacing: 0.16em;
  color: var(--accent);
  margin: 0 0 1rem;
}
.hero h1 {
  font-size: clamp(1.5rem, 3.4vw, 2.4rem);
  font-weight: 620;
  letter-spacing: -0.02em;
  margin: 0 0 0.8rem;
  text-wrap: balance;
}
.lede { font-size: 1.05rem; margin: 0 0 1.6rem; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 0.7rem; }

.section {
  padding: clamp(2.5rem, 7vh, 4rem) clamp(1.25rem, 5vw, 4rem);
  /* width 100% ist noetig: der Rumpf ist ein Flex-Container, und `margin: 0 auto`
     auf einem Flex-Kind schaltet das Dehnen ab. Ohne diese Zeile ist der Kasten
     nur so breit wie sein Inhalt, die Seite wechselt also die Breite, sobald sich
     ein Text darin aendert. */
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
}
.section-alt {
  background: var(--surface);
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  max-width: none;
}
.section h2 { font-size: 1.5rem; font-weight: 620; letter-spacing: -0.015em; margin: 0 0 0.5rem; }
.section-lede { margin: 0 0 1.4rem; }
.feature-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.7rem; }
.feature-list li {
  padding: 0.9rem 1rem;
  background: var(--surface-2);
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  color: var(--muted);
}
.feature-list strong { color: var(--ink); margin-right: 0.4rem; }

.foot-credit { color: inherit; }
.foot-credit:hover { color: var(--accent); }
.foot-credit:hover span { text-decoration: underline; text-underline-offset: 2px; }

.site-foot {
  margin-top: auto;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1.4rem clamp(1.25rem, 5vw, 4rem);
  padding-bottom: calc(1.4rem + env(safe-area-inset-bottom));
  color: var(--faint);
  font-size: 0.82rem;
  border-top: 1px solid var(--line-soft);
}

/* --------------------------------------------------------------- Serverseite */
.srv-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 1rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  margin: 0 0 1rem;
}
.srv-banner-main { display: flex; align-items: center; gap: 0.9rem; min-width: 0; }
.srv-banner-text { display: grid; gap: 0.1rem; min-width: 0; }
.srv-banner-kicker {
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}
.srv-banner-title { font-size: 1.15rem; font-weight: 620; letter-spacing: -0.01em; }
.srv-banner-sub { color: var(--muted); font-size: 0.86rem; }
.srv-banner-side { display: flex; align-items: center; gap: 0.6rem; }
.srv-lamp {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--faint);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.04);
  flex: none;
}
.srv-pill {
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  font-weight: 650;
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--muted);
}
.srv-banner.is-running { border-color: rgba(111, 191, 143, 0.35); }
.srv-banner.is-running .srv-lamp { background: var(--good); box-shadow: 0 0 0 4px rgba(111, 191, 143, 0.14); }
.srv-banner.is-running .srv-pill { color: var(--good); border-color: rgba(111, 191, 143, 0.4); }
.srv-banner.is-stopped .srv-lamp { background: var(--danger); box-shadow: 0 0 0 4px rgba(226, 96, 74, 0.14); }
.srv-banner.is-stopped .srv-pill { color: #f0a596; border-color: rgba(226, 96, 74, 0.4); }
.srv-banner.is-busy .srv-lamp { background: var(--accent); box-shadow: 0 0 0 4px rgba(224, 169, 74, 0.16); }
.srv-banner.is-busy .srv-pill { color: var(--accent); border-color: var(--accent-soft); }
.srv-banner.is-unknown .srv-lamp { background: var(--faint); }

.srv-tabs {
  display: flex;
  gap: 0.25rem;
  padding: 0.3rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  margin: 0 0 1rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.srv-tabs::-webkit-scrollbar { display: none; }
.srv-tab {
  background: transparent;
  border: 0;
  color: var(--muted);
  padding: 0.45rem 0.9rem;
  border-radius: var(--r-sm);
  cursor: pointer;
  white-space: nowrap;
  font-size: 0.9rem;
  touch-action: manipulation;
}
.srv-tab:hover { color: var(--ink); background: var(--surface-2); }
.srv-tab.is-active { background: var(--accent); color: var(--accent-ink); font-weight: 600; }

.srv-savebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin: 0 0 1.2rem;
  padding: 0.7rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
}
.srv-savebar:has(#save-hint.is-dirty) {
  border-color: var(--accent-soft);
  background: rgba(224, 169, 74, 0.07);
}
#save-hint { font-size: 0.88rem; color: var(--muted); }
#save-hint.is-dirty { color: var(--accent); font-weight: 600; }
.srv-savebar-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }

.srv-grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--gap); }
.srv-card {
  padding: 1.1rem 1.2rem 1.2rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.srv-card h2 { margin: 0 0 0.3rem; font-size: 1rem; font-weight: 620; }
.srv-card-lead { color: var(--muted); font-size: 0.88rem; margin: 0 0 0.9rem; }
.srv-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin: 0 0 0.9rem; }
/* --faint lag hier bei 3,50:1, gemessen im Browser. */
.srv-notes { margin: 0; padding-left: 1.1rem; color: var(--muted); font-size: 0.82rem; }
.srv-notes li { margin: 0.2rem 0; }

.srv-meta { margin: 0; display: grid; gap: 0; }
.srv-meta > div {
  display: grid;
  grid-template-columns: minmax(90px, 32%) 1fr;
  gap: 0.6rem;
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--line-soft);
}
.srv-meta > div:last-child { border-bottom: 0; }
.srv-meta dt {
  color: var(--faint);
  font-size: 0.7rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.srv-meta dd { margin: 0; font-size: 0.88rem; overflow-wrap: anywhere; }

.srv-form { display: grid; gap: var(--gap); }
.srv-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 0.8rem; }
.srv-fields-stack { display: grid; gap: 0.8rem; }
.srv-checkgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 0.3rem 0.8rem;
  max-height: 320px;
  overflow: auto;
  padding: 0.6rem;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  background: var(--bg);
}
.srv-log {
  margin: 1rem 0 0;
  padding: 0.8rem;
  background: var(--bg);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--muted);
  max-height: 320px;
  overflow: auto;
  white-space: pre-wrap;
}

/* Geaenderte, noch nicht uebernommene Felder */
.srv-form .is-changed { color: var(--accent); }
.srv-form label.is-changed > input,
.srv-form label.is-changed > select,
.srv-form label.is-changed > textarea,
.srv-form input.is-changed, .srv-form select.is-changed, .srv-form textarea.is-changed {
  border-color: var(--accent);
  box-shadow: inset 2px 0 0 var(--accent);
}
.srv-form label.is-changed::after {
  content: "geändert";
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
}
html[lang="en"] .srv-form label.is-changed::after { content: "changed"; }

/* ------------------------------------------------------------- KI-Steuerung */
.page-ai-control {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  height: 100dvh;
  overflow: hidden;
}
.page-ai-control .site-top, .page-ai-control .admin-subnav { flex: 0 0 auto; position: static; }
.ai-shell {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr) 300px;
  background: var(--bg);
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}
.ai-palette, .ai-inspector {
  background: var(--surface);
  border-right: 1px solid var(--line-soft);
  padding: 1rem 0.9rem;
  padding-bottom: calc(1rem + env(safe-area-inset-bottom));
  overflow: auto;
  min-height: 0;
  -webkit-overflow-scrolling: touch;
}
.ai-inspector { border-right: 0; border-left: 1px solid var(--line-soft); }
.ai-palette h1, .ai-inspector h1 {
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  margin: 0 0 0.7rem;
  font-weight: 600;
}
.ai-panel-sub { margin-top: 1.2rem; }
.ai-hint, .ai-map-status, .ai-rule-note { color: var(--faint); font-size: 0.8rem; line-height: 1.45; }
.ai-palette-groups { display: grid; gap: 0.9rem; }
.ai-palette-group h2 {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 0.4rem;
}
.ai-chip-row { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.ai-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-2);
  font-size: 0.78rem;
  cursor: grab;
  user-select: none;
}
.ai-chip:hover { border-color: var(--accent-soft); }
.ai-chip:active { cursor: grabbing; }
.ai-chip.is-selected { border-color: var(--accent); color: var(--accent); background: rgba(224, 169, 74, 0.12); }
.ai-chip img { width: 16px; height: 16px; }
.ai-stage { position: relative; overflow: hidden; background: var(--bg); }
.ai-stage canvas { width: 100%; height: 100%; display: block; }
.ai-stage-credit { position: absolute; left: 0.8rem; bottom: 0.7rem; font-size: 0.74rem; color: var(--faint); }
.ai-stage-credit a { color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }
.ai-tooltip {
  position: absolute;
  z-index: 5;
  pointer-events: none;
  padding: 0.3rem 0.5rem;
  background: rgba(20, 20, 24, 0.95);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: 0.78rem;
  white-space: nowrap;
}
.ai-rule-form { display: grid; gap: 0.6rem; }
.ai-rule-form label { display: grid; gap: 0.25rem; font-size: 0.78rem; color: var(--muted); }
.ai-rule-form input, .ai-rule-form select, .ai-rule-form textarea {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 0.4rem 0.55rem;
}
.ai-coords { font-family: var(--mono); font-size: 0.76rem; color: var(--faint); }
.ai-check { display: flex; align-items: center; gap: 0.45rem; font-size: 0.85rem; }
.ai-rule-list { display: grid; gap: 0.4rem; margin-top: 0.6rem; }
.ai-rule-body {
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  cursor: pointer;
}
.ai-rule-body:hover { border-color: var(--accent-soft); }
.ai-rule-top { display: flex; justify-content: space-between; gap: 0.5rem; align-items: baseline; }
.ai-rule-name { font-size: 0.88rem; font-weight: 600; }

/* ------------------------------------------------------------- Skin Creator */
.skin-page {
  /* width 100% ist noetig: der Rumpf ist ein Flex-Container, und `margin: 0 auto`
     auf einem Flex-Kind schaltet das Dehnen ab. Ohne diese Zeile ist der Kasten
     nur so breit wie sein Inhalt, die Seite wechselt also die Breite, sobald sich
     ein Text darin aendert. */
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(1.2rem, 3vw, 2rem) clamp(1rem, 3vw, 2rem) 4rem;
}
.skin-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.9rem 1.1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  margin: 0 0 1rem;
}
.skin-toolbar-title { font-size: 1.15rem; font-weight: 620; margin: 0; }
.skin-toolbar-meta { display: flex; gap: 1rem; flex-wrap: wrap; color: var(--muted); font-size: 0.86rem; }
.skin-sync-line, .skin-result-line { color: var(--faint); font-size: 0.84rem; margin: 0.4rem 0 0; }
.skin-offline-msg {
  padding: 0.9rem 1.1rem;
  border: 1px solid rgba(224, 169, 74, 0.35);
  background: rgba(224, 169, 74, 0.08);
  border-radius: var(--r);
  color: var(--accent);
  font-size: 0.9rem;
  margin: 0 0 1rem;
}
.skin-workspace { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--gap); align-items: start; }
.skin-col { display: grid; gap: var(--gap); }
.skin-col-colors, .skin-col-side { min-width: 0; }
.skin-section-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin: 0 0 0.6rem;
}
.skin-section-head h2 { font-size: 1rem; font-weight: 620; margin: 0; }
.color-channels { display: grid; gap: 0.5rem; }
.color-row {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.6rem 0.8rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
}
.color-info { display: grid; gap: 0.1rem; min-width: 0; }
.color-name { font-size: 0.9rem; }
.color-rgb, .color-lin { font-family: var(--mono); font-size: 0.72rem; color: var(--faint); }
.swatch-wrap { position: relative; width: 42px; height: 42px; flex: none; }
.swatch-input { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; }
.swatch-disc {
  width: 42px; height: 42px;
  border-radius: 50%;
  border: 2px solid var(--line);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35);
}
.live-swatches { display: flex; gap: 0.25rem; flex-wrap: wrap; }
.live-swatch { width: 18px; height: 18px; border-radius: 4px; border: 1px solid var(--line); }
.preset-block { display: grid; gap: 0.5rem; }
.preset-head { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
.skin-preset-slots, .preset-block-slots { display: grid; gap: 0.4rem; }
.skin-preset-card {
  display: grid;
  gap: 0.35rem;
  padding: 0.6rem 0.7rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.skin-preset-meta { color: var(--faint); font-size: 0.76rem; }
.skin-preset-swatches { display: flex; gap: 0.2rem; }
.skin-preset-actions { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.mutation-slots { display: grid; gap: 0.5rem; overflow: auto; }
.mutation-slot-row { display: grid; gap: 0.3rem; }
.mutation-slot-row-title { font-size: 0.78rem; color: var(--muted); }

/* ------------------------------------------------------------------ Schleuse */
.gate {
  position: fixed;
  inset: 0;
  background: rgba(11, 10, 9, 0.86);
  backdrop-filter: blur(6px);
  display: grid;
  place-items: center;
  z-index: 40;
  padding: 1rem;
}
.gate.hidden { display: none; }
.gate-card {
  width: min(430px, 100%);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 1.8rem 1.6rem 1.6rem;
  box-shadow: var(--shadow);
  text-align: center;
}
.gate-card h2 { margin: 0 0 0.5rem; font-size: 1.3rem; font-weight: 620; }
.gate-card p { color: var(--muted); margin: 0 0 1.3rem; }

/* ------------------------------------------------------------------- Mobil */
@media (max-width: 900px) {
  input, select, textarea, button { font-size: max(16px, 1rem); }
  .btn, .admin-subnav a, .srv-tab { min-height: 44px; }
  .lang-btn { min-height: 36px; }
  .actions .btn { min-height: 38px; }
  /* Schmal: Marke und Konto teilen sich die erste Zeile, die Navigation
     bekommt eine eigene darunter und scrollt darin seitlich, statt die Seite
     aus dem Bild zu schieben. */
  .site-top {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0.5rem 0.75rem;
    padding-top: calc(0.6rem + env(safe-area-inset-top));
    padding-bottom: 0.6rem;
  }
  .site-nav {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-content: flex-start;
    gap: 0.2rem;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .site-nav::-webkit-scrollbar { display: none; }
  .site-nav > a:not(.btn) { padding: 0 0.7rem; font-size: 0.86rem; }
  .site-account {
    grid-column: 2;
    grid-row: 1;
    padding-left: 0;
    border-left: 0;
    gap: 0.5rem;
  }
  .user-chip { max-width: 26vw; }
  .brand-sub { font-size: 0.8rem; }
}

@media (max-width: 560px) {
  /* Auf schmalen Geraeten blieb vom Seitennamen nur "A…" uebrig. Er sagt
     dort ohnehin nichts, was die Unternavigation nicht schon zeigt. */
  .brand-sub { display: none; }
  .brand-mark { font-size: 0.95rem; }
  .admin-subnav { top: 0; }
  .srv-grid-2, .srv-fields, .assign-form, .garage-form { grid-template-columns: 1fr; }
  .skin-workspace { grid-template-columns: 1fr; }
  .list-filter-search, .garage-filter-search { max-width: none; }
  .srv-savebar {
    position: sticky;
    bottom: 0;
    z-index: 12;
    margin-bottom: 0;
    padding-bottom: calc(0.7rem + env(safe-area-inset-bottom));
    background: rgba(16, 15, 14, 0.96);
    backdrop-filter: blur(10px);
  }
  .srv-savebar-actions { flex: 1 1 auto; }
  .srv-savebar-actions .btn { flex: 1 1 auto; }
  .page-ai-control { height: auto; overflow: visible; }
  .ai-shell { grid-template-columns: 1fr; }
  .ai-palette, .ai-inspector { border: 0; border-bottom: 1px solid var(--line-soft); max-height: 40vh; }
  .ai-stage { min-height: 55vh; order: -1; }
  .ai-stage canvas { touch-action: none; }
}

@media (max-width: 560px) {
  .data-table { font-size: 0.84rem; }
  .data-table th, .data-table td { padding: 0.5rem 0.55rem; }
  .hub-grid { grid-template-columns: 1fr; }
  .data-table td.actions .btn { min-width: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
  .btn:hover, .hub-card:hover { transform: none; }
}

/* ---------------------------------------------------------------------------
   Tabellen auf dem Telefon: Karten statt Schiebetabelle.
   Eine Tabelle, die seitlich weggeschoben werden muss, ist auf einem Telefon
   nicht bedienbar. Jede Zeile wird deshalb unter 700 px zu einer Karte, in der
   die Spaltenueberschrift vor dem Wert steht. Die Beschriftung kommt aus
   data-label, das die jeweilige Seite beim Aufbau setzt.
   --------------------------------------------------------------------------- */
@media (max-width: 700px) {
  .table-wrap {
    border: 0;
    background: transparent;
    overflow: visible;
  }
  .data-table, .data-table tbody, .data-table tr, .data-table td { display: block; width: 100%; }
  .data-table thead { display: none; }
  .data-table tbody tr {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    padding: 0.7rem 0.85rem;
    margin: 0 0 0.5rem;
  }
  .data-table tbody tr:hover td { background: transparent; }
  .data-table td {
    border: 0;
    padding: 0.18rem 0;
    display: grid;
    grid-template-columns: 8.5rem minmax(0, 1fr);
    gap: 0.6rem;
    align-items: baseline;
  }
  .data-table td::before {
    content: attr(data-label);
    color: var(--faint);
    font-size: 0.68rem;
    letter-spacing: 0.09em;
    text-transform: uppercase;
  }
  .data-table td:empty { display: none; }
  .data-table td.actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 0.35rem;
    margin-top: 0.6rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--line-soft);
  }
  .data-table td.actions::before { content: none; }
  .data-table td.actions .btn { flex: 1 1 auto; }
  .row-banned { border-color: rgba(226, 96, 74, 0.4) !important; }
}

/* Kennungen sind zum Vergleichen da, nicht zum Lesen: gleiche Zeichenbreite. */
.mono, .data-table td.mono { font-family: var(--mono); font-size: 0.84em; letter-spacing: -0.01em; }

/* Statusspalte: Abzeichen und Zusatz sauber untereinander statt als Fliesstext */
.status-cell { display: grid; gap: 0.15rem; justify-items: start; }
.status-cell .ban-badge { justify-self: start; }
.status-cell .meta { line-height: 1.35; }

/* --- Analyse ATLAS-AI-Brain ------------------------------------------------
   Dreidimensionale Live-Ansicht der eigenen KI. Dunkel wie das uebrige Portal,
   die Buehne fuellt die Karte und traegt ihre Anzeigen als Auflage, damit das
   Bild so gross wie moeglich bleibt. */
.atlas-karte-karte { padding-bottom: 12px; }
.atlas-buehne {
  position: relative;
  width: 100%;
  flex: 1 1 auto;
  min-height: 300px;
  margin-top: 0;
  border: 1px solid #1c2836;
  border-radius: 10px;
  overflow: hidden;
  background: #06090d;
}
/* Der Rahmen traegt die vollstaendige Ansicht der Karte. Er bleibt bis zum
   Ende des Ladens unsichtbar, damit niemand in eine halb aufgebaute Szene
   klickt und sie fuer kaputt haelt. */
#atlas-rahmen {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  opacity: 0;
  transition: opacity .25s ease;
}
#atlas-rahmen.ist-da { opacity: 1; }
.atlas-laden {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: #080b0e;
  transition: opacity .3s ease;
}
.atlas-laden.ist-weg { opacity: 0; pointer-events: none; }
.atlas-laden-kasten { width: min(520px, 84%); }
.atlas-laden-marke {
  font: 500 11px/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: #7f97ab;
  margin-bottom: 10px;
}
.atlas-laden-kasten h3 {
  margin: 0 0 18px;
  font-size: 20px;
  font-weight: 600;
  color: #eaf2fb;
}
.atlas-schiene {
  height: 6px;
  border-radius: 3px;
  background: #182029;
  overflow: hidden;
}
.atlas-schiene i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 3px;
  background: linear-gradient(90deg, #2f6f8f, #6fd2c8);
  transition: width .18s linear;
}
.atlas-laden-was { margin: 14px 0 2px; font-size: 14px; color: #a9bccd; }
.atlas-laden-was.ist-fehler { color: #f08a8a; }
.atlas-laden-zahl {
  margin: 0;
  font: 400 12px/1.5 var(--mono);
  color: #7f97ab;
  font-variant-numeric: tabular-nums;
}
.atlas-laden-hinweis {
  margin: 18px 0 0;
  font-size: 12px;
  line-height: 1.6;
  color: #61798e;
  max-width: 62ch;
}
.atlas-hilfe {
  flex: 0 0 auto;
  margin-top: 10px;
  font-size: 12px;
  line-height: 1.9;
  color: #8fa3b8;
}
.atlas-hilfe b { color: #7fd4ff; font-weight: 600; }
.ladder-toolbar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin: 0 0 1rem;
}
.ladder-toolbar .status-line { margin: 0; }
.ladder-step {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.ladder-table input,
.ladder-table select {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 0.45rem 0.55rem;
  color: var(--ink);
}
.ladder-table td input[type="text"] { width: 100%; min-width: 8rem; }
.ladder-step select { min-width: 8.5rem; }
.ladder-days { width: 4.6rem; }

