/* Self-hosted Fonts (CSP-konform) — ersetzt Google Fonts */
@font-face { font-family: "Space Grotesk"; src: url("/static/fonts/space-grotesk.woff2") format("woff2");
  font-weight: 300 700; font-style: normal; font-display: swap; }
@font-face { font-family: "JetBrains Mono"; src: url("/static/fonts/jetbrains-mono-var.woff2") format("woff2");
  font-weight: 100 800; font-style: normal; font-display: swap; }

/* ZeroLoad Community Portal — Vordesign / Designsystem
   Dunkel, near-black mit grünem Signal (ZeroLoad). Editorial-funktional, dicht, ruhig.
   OKLCH-Farben. Kein Glassmorphism/Gradient/Glow. Kleine Radien, 1px-Borders. */

/* ── Tokens ─────────────────────────────────────────────────────────────── */
:root {
  /* Flächen (dunkel, whisper-grün) */
  --bg:        oklch(0.165 0.006 160);
  --surface:   oklch(0.205 0.007 160);
  --surface-2: oklch(0.245 0.008 160);
  --surface-3: oklch(0.285 0.009 160);
  --border:    oklch(0.32 0.010 160);
  --border-2:  oklch(0.40 0.012 160);

  /* Text (Kontrast geprüft: ink/muted gegen bg ≥ 4.5:1) */
  --ink:       oklch(0.965 0.004 160);
  --ink-2:     oklch(0.86 0.005 160);
  --muted:     oklch(0.72 0.006 160);
  --faint:     oklch(0.58 0.006 160);

  /* Marke + Rollen */
  --primary:      oklch(0.74 0.15 152);
  --primary-2:    oklch(0.80 0.14 152);
  --primary-ink:  oklch(0.20 0.03 152);
  --primary-soft: oklch(0.30 0.05 152);
  --accent:       oklch(0.80 0.13 72);   /* Amber — Auktionen/Attention */
  --accent-ink:   oklch(0.24 0.05 72);
  --danger:       oklch(0.68 0.17 27);
  --warning:      oklch(0.82 0.13 85);
  --info:         oklch(0.74 0.10 235);
  --success:      var(--primary);

  --sel: oklch(0.74 0.15 152 / 0.22);

  /* Typo */
  --font-display: "Space Grotesk", system-ui, sans-serif;
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Spacing (4pt), Radien (klein), Schatten (nur Overlays) */
  --r-1: 5px; --r-2: 8px; --r-3: 11px; --r-pill: 999px;
  --sh-pop: 0 6px 24px -8px oklch(0 0 0 / 0.55), 0 2px 6px -3px oklch(0 0 0 / 0.5);
  --sh-line: inset 0 0 0 1px var(--border);

  /* Z-Skala (semantisch, aufsteigend in der Reihenfolge des Stapels).
     Der Backdrop MUSS unter Drawer und Modal liegen — lag er darüber, fing er
     jeden Klick ab und schloss das Panel, statt den Button darin zu treffen
     (betraf auch die mobile Sidebar: ein Tipp auf einen Nav-Link schloss sie
     nur, statt zu navigieren). */
  --z-sticky: 100; --z-backdrop: 200; --z-drawer: 300; --z-modal: 400; --z-toast: 500; --z-tip: 600;

  /* Motion */
  --e-out: cubic-bezier(0.16, 1, 0.3, 1);
  --t-1: 120ms; --t-2: 200ms; --t-3: 320ms;

  --topbar-h: 56px;
  --side-w: 248px;
  --maxw: 1220px;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: var(--font-sans); font-size: 15px; line-height: 1.55;
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}
::selection { background: var(--sel); }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.02em; margin: 0; text-wrap: balance; }
h1 { font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.05rem); }
h2 { font-size: 1.28rem; }
h3 { font-size: 1.05rem; letter-spacing: -0.01em; }
p { margin: 0 0 0.9rem; }
p:last-child { margin-bottom: 0; }
small { font-size: 0.82rem; }
code, kbd, .mono { font-family: var(--font-mono); }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }
img { max-width: 100%; display: block; }
hr { border: 0; border-top: 1px solid var(--border); margin: 1.25rem 0; }

/* ── Topbar ─────────────────────────────────────────────────────────────── */
.topbar {
  position: sticky; top: 0; z-index: var(--z-sticky);
  height: var(--topbar-h); display: flex; align-items: center; gap: 14px;
  padding: 0 18px; background: color-mix(in oklab, var(--bg) 88%, transparent);
  border-bottom: 1px solid var(--border); backdrop-filter: saturate(1.4) blur(6px);
}
.brand { display: inline-flex; align-items: center; gap: 9px; font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; letter-spacing: -0.01em; }
.brand b { color: var(--primary); }
.brand .brand-word { color: var(--ink); }
.brand .dot { width: 9px; height: 9px; border-radius: 3px; background: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
.brand-ico { width: 28px; height: 28px; border-radius: 7px; object-fit: cover; flex: none; border: 1px solid var(--border); background: #000; }

/* World-Switch (Community | Bot) */
.worlds { display: inline-flex; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-pill); padding: 3px; }
.worlds a { padding: 5px 13px; border-radius: var(--r-pill); font-size: 0.86rem; font-weight: 500; color: var(--muted); }
.worlds a.on { background: var(--surface-3); color: var(--ink); }

.top-nav { display: flex; gap: 2px; margin-left: 6px; }
.top-nav a { padding: 7px 11px; border-radius: var(--r-2); font-size: 0.9rem; color: var(--muted); font-weight: 500; }
.top-nav a:hover { color: var(--ink); background: var(--surface); }
.top-nav a.on { color: var(--ink); background: var(--surface-2); }

.top-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.topsearch { display: flex; align-items: center; gap: 8px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-2); padding: 6px 10px; color: var(--muted); min-width: 210px; }
.topsearch input { all: unset; flex: 1; color: var(--ink); font-size: 0.88rem; }
.topsearch kbd { font-size: 0.7rem; color: var(--faint); border: 1px solid var(--border); border-radius: 4px; padding: 1px 5px; }
.icon-btn { position: relative; width: 34px; height: 34px; display: grid; place-items: center; border-radius: var(--r-2); border: 1px solid var(--border); background: var(--surface); color: var(--muted); cursor: pointer; }
.icon-btn:hover { color: var(--ink); border-color: var(--border-2); }
.icon-btn .badge-dot { position: absolute; top: -3px; right: -3px; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px; background: var(--accent); color: var(--accent-ink); font-size: 0.66rem; font-weight: 700; display: grid; place-items: center; }
.avatar { border-radius: var(--r-pill); background: var(--surface-3); display: grid; place-items: center; font-weight: 600; overflow: hidden; flex: none; color: var(--ink); }
.avatar.sm { width: 28px; height: 28px; font-size: 0.72rem; }
.avatar.md { width: 40px; height: 40px; font-size: 0.9rem; }
.avatar.lg { width: 72px; height: 72px; font-size: 1.5rem; }
.burger { display: none; }

/* ── Abmelden: der sichtbare Ausgang (2026-08-27) ───────────────────────── */
/* Bewusst OHNE die Klasse `optional`: die verschwindet unter 720px und wird
   von portal-live.js aus der Topbar geraeumt. Der Ausgang bleibt. */
.zl-logout { color: var(--muted); }
.zl-logout svg { width: 16px; height: 16px; }
.zl-logout:hover {
  color: var(--danger);
  border-color: color-mix(in oklab, var(--danger) 40%, var(--border));
  background: color-mix(in oklab, var(--danger) 10%, var(--surface));
}
/* Auf schmalen Geraeten weicht nur das Wort — der Knopf bleibt als Symbol
   stehen und behaelt seine Beschriftung fuer Vorleseprogramme (title). */
@media (max-width: 620px) {
  .zl-logout-wort { display: none; }
  /* `.topbar` davor, sonst gewinnt `.btn.sm { padding: 5px 10px }` weiter
     unten: zwei Klassen schlagen eine, unabhaengig von der Reihenfolge.
     Ohne das behaelt der Knopf seine breite Polsterung, obwohl nur noch ein
     Symbol drinsteht — und genau die Breite fehlt auf schmalen Geraeten. */
  .topbar .btn.zl-logout { padding: 6px; }
}

/* ── Sprachwahl DE/EN (2026-08-27) ──────────────────────────────────────── */
/* Gleiche Bauform wie der vorhandene Welten-Umschalter (.worlds), damit die
   Kopfzeile nicht zwei verschiedene Segmentschalter zeigt. */
.zl-langswitch {
  display: inline-flex; align-items: center; gap: 2px; padding: 2px;
  border: 1px solid var(--border); border-radius: var(--r-2); background: var(--surface);
}
.zl-langbtn {
  /* NICHT var(--faint): das ergibt gegen var(--surface) nur 4,18:1 und
     verfehlt WCAG 1.4.3 (4,5:1). Der Kommentar bei den Tokens oben verspricht
     geprueften Kontrast nur fuer ink/muted gegen bg — faint gegen surface ist
     eine andere Paarung und war nie gemessen. var(--muted) liegt bei 7,2:1. */
  padding: 4px 9px; border: 0; border-radius: 5px; background: transparent;
  color: var(--muted); font: inherit; font-family: var(--font-mono);
  font-size: 0.72rem; letter-spacing: 0.05em; cursor: pointer;
  transition: background var(--t-1), color var(--t-1);
}
.zl-langbtn:hover { color: var(--ink); }
.zl-langbtn[data-on="1"] { background: var(--surface-3); color: var(--ink); }
@media (max-width: 420px) { .zl-langbtn { padding: 4px 6px; } }

/* Zurueck auf die oeffentliche Seite — gleiche Bauform wie der Ausgang,
   aber in der ruhigen Farbe: das hier ist der harmlose Weg. */
.zl-website { color: var(--muted); }
.zl-website svg { width: 16px; height: 16px; }
.zl-website:hover { color: var(--ink); border-color: var(--border-2); }
@media (max-width: 620px) {
  .zl-website-wort { display: none; }
  /* Siehe Begruendung beim Abmelden-Knopf: einfache Klasse verliert gegen
     `.btn.sm`. */
  .topbar .btn.zl-website { padding: 6px; }
}

/* Zweiter Weg: Fuss der Seitenleiste. Unter 980px ist das die Schublade,
   also der Ausgang auf dem Handy. */
.zl-side-abschluss { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border); }
.zl-side-website {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border-radius: var(--r-2);
  color: var(--muted); font-size: 0.9rem; font-weight: 500;
}
.zl-side-website svg { width: 16px; height: 16px; flex: none; opacity: 0.8; }
.zl-side-website:hover { background: var(--surface); color: var(--ink); }
.zl-side-logout {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: var(--r-2);
  background: transparent; color: var(--muted);
  font: inherit; font-size: 0.9rem; font-weight: 500;
  text-align: left; cursor: pointer;
}
.zl-side-logout svg { width: 16px; height: 16px; flex: none; opacity: 0.8; }
.zl-side-logout:hover {
  background: color-mix(in oklab, var(--danger) 12%, var(--surface));
  color: var(--danger);
}

/* ── Layout ─────────────────────────────────────────────────────────────── */
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 24px 18px 64px; }
.shell { display: grid; grid-template-columns: var(--side-w) 1fr; align-items: start; max-width: 1360px; margin: 0 auto; }
.content { min-width: 0; padding: 22px 26px 64px; }

/* Forum: optionale rechte Spalte */
.split { display: grid; grid-template-columns: 1fr 300px; gap: 26px; align-items: start; }
@media (max-width: 900px) { .split { grid-template-columns: 1fr; } .aside-right { order: -1; } }

.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
.page-head .sub { color: var(--muted); font-size: 0.92rem; margin-top: 4px; }
.crumbs { display: flex; gap: 7px; align-items: center; color: var(--faint); font-size: 0.84rem; margin-bottom: 12px; }
.crumbs a:hover { color: var(--ink); }
.crumbs .sep { opacity: 0.5; }
.eyebrow-x { display: none; } /* keine Eyebrow-Kicker */

/* ── Sidebar (Bot-Dashboard) ────────────────────────────────────────────── */
.side { position: sticky; top: var(--topbar-h); align-self: start; height: calc(100vh - var(--topbar-h)); overflow: auto; border-right: 1px solid var(--border); padding: 16px 12px; }
.side .srv { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border: 1px solid var(--border); border-radius: var(--r-2); background: var(--surface); margin-bottom: 14px; cursor: pointer; }
.side .srv .avatar { width: 30px; height: 30px; font-size: 0.72rem; }
.side .srv .name { font-weight: 600; font-size: 0.9rem; }
.side .srv .meta { color: var(--faint); font-size: 0.74rem; }
.side .srv .chev { margin-left: auto; color: var(--faint); }
.side-group { margin: 6px 0 14px; }
.side-group > .lbl { font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); padding: 6px 10px; }
.side a.nav { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--r-2); color: var(--muted); font-size: 0.9rem; font-weight: 500; }
.side a.nav svg { width: 16px; height: 16px; flex: none; opacity: 0.8; }
.side a.nav:hover { background: var(--surface); color: var(--ink); }
.side a.nav.on { background: var(--surface-2); color: var(--ink); }
.side a.nav.on svg { color: var(--primary); opacity: 1; }
.side a.nav .tag { margin-left: auto; font-size: 0.66rem; color: var(--faint); border: 1px solid var(--border); border-radius: 5px; padding: 0 5px; }
.side a.nav .cnt { margin-left: auto; font-size: 0.72rem; color: var(--faint); font-family: var(--font-mono); }

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn { display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: var(--r-2); border: 1px solid var(--border); background: var(--surface); color: var(--ink); font: inherit; font-size: 0.9rem; font-weight: 550; cursor: pointer; transition: background var(--t-1), border-color var(--t-1), transform var(--t-1); white-space: nowrap; }
.btn:hover { background: var(--surface-2); border-color: var(--border-2); }
.btn:active { transform: translateY(1px); }
.btn svg { width: 16px; height: 16px; }
.btn.primary { background: var(--primary); border-color: transparent; color: var(--primary-ink); font-weight: 650; }
.btn.primary:hover { background: var(--primary-2); }
.btn.ghost { background: transparent; }
.btn.ghost:hover { background: var(--surface); }
.btn.sm { padding: 5px 10px; font-size: 0.82rem; }
.btn.danger { color: var(--danger); }
.btn.icon { padding: 8px; }

/* ── Inputs ─────────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.field > label { font-size: 0.82rem; color: var(--muted); font-weight: 500; }
input[type=text], input[type=email], input[type=password], input[type=search], input[type=number], select, textarea {
  width: 100%; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-2);
  color: var(--ink); font: inherit; font-size: 0.92rem; padding: 9px 12px; transition: border-color var(--t-1), box-shadow var(--t-1);
}
input::placeholder, textarea::placeholder { color: var(--faint); }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-soft); }
textarea { resize: vertical; min-height: 120px; line-height: 1.6; }
.switch { position: relative; width: 40px; height: 23px; border-radius: 999px; background: var(--surface-3); border: 1px solid var(--border-2); cursor: pointer; flex: none; transition: background var(--t-2); }
.switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 17px; height: 17px; border-radius: 50%; background: var(--muted); transition: transform var(--t-2) var(--e-out), background var(--t-2); }
.switch.on { background: var(--primary); border-color: transparent; }
.switch.on::after { transform: translateX(17px); background: var(--primary-ink); }

/* ── Panels / Cards (sparsam) ───────────────────────────────────────────── */
.panel { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-3); }
.panel > .ph { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 13px 16px; border-bottom: 1px solid var(--border); }
.panel > .ph h3 { font-size: 0.98rem; }
.panel > .pb { padding: 16px; }
.panel > .pb.flush { padding: 0; }

/* ── Badges / Chips / Status ────────────────────────────────────────────── */
.badge { display: inline-flex; align-items: center; gap: 5px; font-size: 0.74rem; font-weight: 600; padding: 2px 8px; border-radius: var(--r-pill); border: 1px solid var(--border-2); color: var(--muted); background: var(--surface-2); }
.badge .d { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge.green { color: var(--primary-2); border-color: color-mix(in oklab, var(--primary) 40%, var(--border)); background: color-mix(in oklab, var(--primary) 12%, var(--surface)); }
.badge.amber { color: var(--accent); border-color: color-mix(in oklab, var(--accent) 40%, var(--border)); background: color-mix(in oklab, var(--accent) 12%, var(--surface)); }
.badge.red   { color: var(--danger); border-color: color-mix(in oklab, var(--danger) 40%, var(--border)); background: color-mix(in oklab, var(--danger) 12%, var(--surface)); }
.badge.blue  { color: var(--info); border-color: color-mix(in oklab, var(--info) 40%, var(--border)); background: color-mix(in oklab, var(--info) 12%, var(--surface)); }
.badge.plain { background: transparent; }
.chip { font-size: 0.78rem; color: var(--muted); background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-pill); padding: 3px 10px; }
.pro { font-size: 0.62rem; letter-spacing: 0.04em; font-weight: 700; color: var(--accent); border: 1px solid color-mix(in oklab, var(--accent) 45%, var(--border)); border-radius: 4px; padding: 1px 5px; vertical-align: middle; }

/* ── Tabellen / dichte Listen ───────────────────────────────────────────── */
.table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
.table th { text-align: left; font-weight: 600; color: var(--muted); font-size: 0.78rem; letter-spacing: 0.01em; padding: 10px 14px; border-bottom: 1px solid var(--border); position: sticky; top: 0; background: var(--surface); }
.table td { padding: 11px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.table tbody tr:last-child td, .table tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-2); }
.table .num { font-family: var(--font-mono); text-align: right; font-variant-numeric: tabular-nums; }
.t-actions { display: flex; gap: 6px; justify-content: flex-end; opacity: 0; transition: opacity var(--t-1); }
.table tr:hover .t-actions { opacity: 1; }

/* Forum-Zeilen (Thread-Liste) */
.rowlist { display: flex; flex-direction: column; }
.row { display: grid; grid-template-columns: auto 1fr auto; gap: 14px; align-items: center; padding: 13px 16px; border-bottom: 1px solid var(--border); }
.row:last-child { border-bottom: 0; }
.row:hover { background: var(--surface-2); }
.row .ttl { font-weight: 600; color: var(--ink); font-size: 0.98rem; }
.row .ttl:hover { color: var(--primary-2); }
.row .rmeta { color: var(--faint); font-size: 0.8rem; margin-top: 3px; display: flex; gap: 10px; flex-wrap: wrap; }
.row .rstats { display: flex; gap: 20px; text-align: right; color: var(--muted); font-size: 0.82rem; }
.row .rstats b { display: block; color: var(--ink); font-family: var(--font-mono); font-size: 0.95rem; }
.pin { color: var(--accent); }

/* ── Statistiken inline (kein Hero-Metric-Template) ─────────────────────── */
.statbar { display: flex; flex-wrap: wrap; gap: 26px; padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--r-3); background: var(--surface); }
.statbar .s { display: flex; flex-direction: column; }
.statbar .s .v { font-family: var(--font-mono); font-size: 1.15rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.statbar .s .k { color: var(--faint); font-size: 0.76rem; }
.statbar .s .up { color: var(--primary-2); }

/* Divider label */
.section-t { display: flex; align-items: center; gap: 10px; margin: 26px 0 12px; }
.section-t h2 { font-size: 1.02rem; }
.section-t .line { flex: 1; height: 1px; background: var(--border); }
.section-t a { color: var(--muted); font-size: 0.84rem; }
.section-t a:hover { color: var(--ink); }

/* Avatare mit Farbe */
.av-a { background: oklch(0.5 0.12 152); } .av-b { background: oklch(0.5 0.13 72); }
.av-c { background: oklch(0.5 0.14 25); } .av-d { background: oklch(0.5 0.11 235); }
.av-e { background: oklch(0.5 0.12 300); } .av-f { background: oklch(0.52 0.10 110); }

/* Tabs */
.tabs { display: flex; gap: 3px; border-bottom: 1px solid var(--border); margin-bottom: 18px; }
.tabs a { padding: 9px 13px; font-size: 0.9rem; color: var(--muted); font-weight: 500; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tabs a:hover { color: var(--ink); }
.tabs a.on { color: var(--ink); border-bottom-color: var(--primary); }

/* Muted / util */
.muted { color: var(--muted); } .faint { color: var(--faint); }
.mono { font-family: var(--font-mono); }
.stack { display: flex; flex-direction: column; gap: 16px; }
.rowflex { display: flex; align-items: center; gap: 10px; }
.right { margin-left: auto; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
@media (max-width: 760px){ .grid-2 { grid-template-columns: 1fr; } }

/* Empty state */
.empty { text-align: center; padding: 48px 20px; color: var(--muted); }
.empty svg { width: 34px; height: 34px; opacity: 0.5; margin-bottom: 10px; }

/* ── Mobile ─────────────────────────────────────────────────────────────── */
.backdrop { position: fixed; inset: 0; background: oklch(0 0 0 / 0.5); z-index: var(--z-backdrop); opacity: 0; pointer-events: none; transition: opacity var(--t-2); }
.backdrop.on { opacity: 1; pointer-events: auto; }
@media (max-width: 980px) {
  .shell { grid-template-columns: 1fr; }
  .side { position: fixed; top: 0; left: 0; height: 100vh; width: 280px; background: var(--bg); z-index: var(--z-drawer); transform: translateX(-100%); transition: transform var(--t-3) var(--e-out); padding-top: 14px; }
  .side.on { transform: none; }
  .burger { display: grid; }
  .content { padding: 18px 16px 56px; }
}
@media (max-width: 720px) {
  .top-nav, .topsearch, .worlds { display: none; }
  .top-right .icon-btn.optional { display: none; }
  .row { grid-template-columns: 1fr auto; }
  .hide-sm { display: none !important; }
  .statbar { gap: 18px; }
}

/* Sehr schmale Geraete: Der Wortmarke weichen, nicht den Bedienelementen.
   Nachgerechnet fuer 360px — Burger 34 + Marke 109 + Sprachwahl 66 +
   Website 34 + Abmelden 34 + Kuerzel 28 + Abstaende + 36 Randabstand
   ergeben rund 393px. Ohne den Schriftzug bleiben ~312px, also Luft.
   .topbar hat KEIN flex-wrap: was nicht passt, laeuft ueber statt umzubrechen. */
@media (max-width: 480px) {
  .brand .brand-word { display: none; }
  .top-right { gap: 6px; }
}

/* ── Motion (reduced-motion respektiert) ────────────────────────────────── */
@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.rise { animation: rise var(--t-3) var(--e-out) both; }
.rise-2 { animation-delay: 40ms; } .rise-3 { animation-delay: 80ms; } .rise-4 { animation-delay: 120ms; }
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ── Ergänzungen für die Live-Verdrahtung (Phase 2) ─────────────────────── */
/* Toast (Rückmeldung nach Speichern) — ohne diese Regeln erscheint der Text
   unformatiert am Seitenende und verschwindet nie. */
.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%) translateY(20px);
  z-index: var(--z-toast); background: var(--surface-3); border: 1px solid var(--border-2);
  color: var(--ink); padding: 11px 18px; border-radius: var(--r-2); box-shadow: var(--sh-pop);
  font-size: 0.9rem; opacity: 0; pointer-events: none; max-width: min(90vw, 520px);
  transition: opacity var(--t-2), transform var(--t-2) var(--e-out);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast.err { border-color: var(--danger); color: var(--ink); }

/* Lade-Spinner */
.spinner { width: 26px; height: 26px; border: 3px solid var(--border-2); border-top-color: var(--primary);
  border-radius: 50%; animation: zl-spin 0.7s linear infinite; margin: 44px auto; }
@keyframes zl-spin { to { transform: rotate(360deg); } }

/* Modul-Kacheln (werden auch auf bot-module.html gerendert) */
.mod-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.mod { display: flex; flex-direction: column; gap: 8px; border: 1px solid var(--border);
  border-radius: var(--r-2); background: var(--surface); padding: 13px 14px;
  transition: border-color var(--t-1), background var(--t-1); }
.mod:hover { border-color: var(--border-2); background: var(--surface-2); }
.mod .top { display: flex; align-items: center; gap: 9px; }
.mod .top .ic { display: inline-flex; font-size: 1.05rem; }
.mod .top .ic svg, .mod .top svg { width: 17px; height: 17px; color: var(--muted); }
.mod.on .top .ic svg, .mod.on .top svg { color: var(--primary); }
.mod .nm { font-weight: 600; font-size: 0.94rem; }
.mod .ds { color: var(--faint); font-size: 0.8rem; line-height: 1.45; min-height: 34px; }
.mod .ft { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 2px; }
.mod .cmds { font-size: 0.72rem; color: var(--faint); font-family: var(--font-mono); }

/* Hilfetext unter Formularfeldern */
.field .help { font-size: 0.78rem; color: var(--faint); }

/* Platzhalter-Legende (Feldtyp `placeholders`).
   `.field > .lbl` spiegelt bewusst `.field > label` darueber: der Block ist ein
   Erklaertext ohne Eingabefeld, ein <label> ohne Bezugsfeld waere hier falsch
   ausgezeichnet — gleiches Aussehen, ehrlichere Semantik. */
.field > .lbl { font-size: 0.82rem; color: var(--muted); font-weight: 500; }
.ph-list { display: grid; grid-template-columns: max-content 1fr; gap: 5px 12px; margin: 4px 0 0; align-items: baseline; }
.ph-list dt { margin: 0; }
.ph-list dd { margin: 0; color: var(--faint); font-size: 0.78rem; line-height: 1.45; }
.ph-list code { font-family: var(--font-mono); font-size: 0.76rem; color: var(--primary-2); background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px; padding: 1px 6px; white-space: nowrap; }
@media (max-width: 520px) {
  .ph-list { grid-template-columns: 1fr; gap: 2px; }
  .ph-list dd { margin: 0 0 7px; }
}

/* Sidebar-Icons einheitlich */
.side a.nav .ico { display: inline-flex; width: 16px; height: 16px; flex: none; }
.side a.nav .ico svg { width: 16px; height: 16px; }

/* Checkbox-Raster (Rollen/Kanäle auswählen — wie im bestehenden Dashboard) */
.check-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px; }
.cg-item {
  display: flex; align-items: center; gap: 9px; padding: 8px 11px;
  border: 1px solid var(--border); border-radius: var(--r-2); background: var(--surface-2);
  font-size: 0.88rem; cursor: pointer; min-width: 0;
  transition: border-color var(--t-1), background var(--t-1);
}
.cg-item:hover { border-color: var(--border-2); }
.cg-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cg-item input[type="checkbox"] { width: 16px; height: 16px; flex: none; accent-color: var(--primary); cursor: pointer; margin: 0; }
.cg-item:has(input:checked) { border-color: color-mix(in oklab, var(--primary) 55%, var(--border)); background: color-mix(in oklab, var(--primary) 10%, var(--surface-2)); }
.cg-item.off { opacity: 0.5; cursor: not-allowed; }
.cg-item.off input { cursor: not-allowed; }

/* ── Rollen-Auswahl: Kategorien ────────────────────────────────────────────
   Gegenstueck zu `.sr-*` in static/css/style.css (Dashboard). Zwei
   Oberflaechen, zwei Stilsysteme — die Klassennamen bleiben absichtlich
   gleich, damit beim Suchen nach einer Stelle die andere mit auftaucht.
   Ziehen ist die Zugabe, nicht der Weg: jede Zeile hat ein Auswahlfeld und
   jede Kategorie zwei Pfeiltasten. */
.sr-kat {
  margin: 10px 0; padding: 11px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--r-2);
  transition: border-color var(--t-1), background var(--t-1);
}
.sr-kat--frei { border-style: dashed; }
.sr-kat.is-ziel { border-color: var(--primary); background: var(--primary-soft); }
.sr-kat__kopf { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin-bottom: 8px; }
.sr-kat input[type="text"], .sr-kat input[type="number"] { margin-bottom: 6px; }
.sr-emoji { width: 3.4rem; text-align: center; flex: none; }
.sr-num { width: 4.2rem; }
.sr-grenzen { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  font-size: 0.84rem; color: var(--muted); margin-bottom: 8px; }
.sr-grenzen label { display: inline-flex; align-items: center; gap: 6px; }
.sr-liste { display: flex; flex-direction: column; gap: 6px; min-height: 2rem; }
.sr-zeile { display: flex; align-items: center; gap: 7px; padding: 6px 9px;
  border: 1px solid var(--border); border-radius: var(--r-2); background: var(--bg);
  font-size: 0.88rem; }
.sr-zeile:hover { border-color: var(--border-2); }
.sr-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sr-warn { flex: none; color: var(--warning); cursor: help; }
.sr-move { flex: none; max-width: 11rem; font-size: 0.82rem; padding: 4px 6px; margin: 0 !important; }
.sr-leer { margin: 2px 0; font-style: italic; font-size: 0.85rem; }
.sr-griff { cursor: grab; color: var(--muted); user-select: none; flex: none; padding: 0 2px; }
.sr-griff:active { cursor: grabbing; }

@media (max-width: 560px) {
  .sr-zeile { flex-wrap: wrap; }
  .sr-name { flex: 1 0 60%; }
  .sr-move { max-width: none; flex: 1 0 100%; margin-top: 5px !important; }
  .sr-griff { display: none; }
}

/* ── Flüssiger Seitenwechsel ─────────────────────────────────────────────
   Ohne das blitzt beim Klick kurz die Vordesign-Sidebar auf und springt
   dann um, sobald die echten Daten da sind. */
/* WICHTIG — die Regel muss standardmaessig GREIFEN, nicht erst wenn JS sie setzt.
   Vorher stand hier nur `html.zl-loading .side { opacity: 0 }`: die Klasse setzt aber
   JavaScript, und das laeuft erst NACH dem ersten Malen. Genau deshalb war beim
   Seitenwechsel fuer ein paar hundert Millisekunden die Vordesign-Sidebar sichtbar —
   mit erfundenem Servernamen, falschen Modulen und PRO-Abzeichen (nachgestellt und
   Bild fuer Bild belegt, 2026-08-11). Jetzt gilt dieselbe Logik wie beim Inhalt:
   versteckt, BIS das JS "fertig" meldet. */
html:not(.zl-ready) body[data-world="bot"] .side { visibility: hidden; }
/* Dasselbe fuer die rechte Topbar-Seite: dort stehen im Vordesign eine Suche und ein
   fremdes Nutzerkuerzel, die patchUser() erst spaeter ersetzt. */
html:not(.zl-ready) body[data-world="bot"] .topbar .top-right { visibility: hidden; }
.side { transition: opacity var(--t-2) var(--e-out); }

/* Inhalt sanft einblenden statt hart zu erscheinen */
.content { animation: zl-in var(--t-2) var(--e-out) both; }
@keyframes zl-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* Sidebar-Links: weicher Hover/Aktiv-Wechsel */
.side a.nav { transition: background var(--t-1), color var(--t-1); }

@media (prefers-reduced-motion: reduce) {
  html.zl-loading .side { opacity: 1; }
  .content { animation: none; }
}

/* Kein Aufblitzen des statischen Vordesign-Inhalts:
   Die HTML-Seiten enthalten Beispiel-Markup (z.B. das Auktionshaus-Formular in
   bot-module.html). Der Browser malt das, BEVOR die Skripte geladen sind.
   Deshalb den Inhaltsbereich verstecken, bis das JS gezeichnet hat. */
html:not(.zl-painted) body[data-world="bot"] .content { visibility: hidden; }

/* ══ Overlay-Kit (ui.js): Drawer · Dialog · ⋮-Menü ═══════════════════════════
   Eigener Backdrop (.ov-bd) — das bestehende .backdrop gehört der mobilen
   Sidebar in shell.js und darf hier nicht mitbenutzt werden. */
.ov-bd {
  position: fixed; inset: 0; background: oklch(0 0 0 / 0.52); z-index: var(--z-backdrop);
  opacity: 0; pointer-events: none; transition: opacity var(--t-2);
}
.ov-bd.on { opacity: 1; pointer-events: auto; }
html.ov-lock, html.ov-lock body { overflow: hidden; }

/* ── Drawer ─────────────────────────────────────────────────────────────── */
.ov-drawer {
  position: fixed; top: 0; right: 0; height: 100dvh; width: min(520px, 100vw);
  display: flex; flex-direction: column; z-index: var(--z-drawer);
  background: var(--surface); border-left: 1px solid var(--border); box-shadow: var(--sh-pop);
  transform: translateX(100%); transition: transform var(--t-3) var(--e-out);
}
.ov-drawer.wide { width: min(760px, 100vw); }
.ov-drawer.on { transform: none; }
.ov-drawer.busy { cursor: progress; }
.ov-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 15px 18px; border-bottom: 1px solid var(--border); flex: none;
}
.ov-ttl h2 { font-size: 1.02rem; line-height: 1.3; }
.ov-sub { color: var(--faint); font-size: 0.8rem; margin-top: 3px; }
.ov-body { padding: 16px 18px; overflow-y: auto; flex: 1; min-height: 0; }
.ov-body > :last-child { margin-bottom: 0; }
.ov-err {
  margin: 0 18px 12px; padding: 9px 12px; border-radius: var(--r-2); font-size: 0.85rem;
  color: var(--danger); border: 1px solid color-mix(in oklab, var(--danger) 42%, var(--border));
  background: color-mix(in oklab, var(--danger) 10%, var(--surface));
}
.ov-foot {
  display: flex; justify-content: flex-end; gap: 8px; flex: none;
  padding: 12px 18px; border-top: 1px solid var(--border); background: var(--surface-2);
}

/* Definitionsliste im Drawer (Detail-Ansicht) */
.ov-dl { display: grid; grid-template-columns: minmax(96px, 34%) 1fr; gap: 9px 14px; font-size: 0.88rem; }
.ov-dl dt { color: var(--muted); }
.ov-dl dd { color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.ov-sec { margin: 18px 0 9px; font-size: 0.78rem; color: var(--muted); font-weight: 600; }
.ov-sec:first-child { margin-top: 0; }

/* ── Bestätigungs-Dialog ────────────────────────────────────────────────── */
.ov-modal {
  position: fixed; inset: 0; z-index: var(--z-modal); display: grid; place-items: center;
  padding: 20px; opacity: 0; transition: opacity var(--t-2);
  /* Eigene Abdunklung: öffnet sich der Dialog ÜBER einem Drawer, liegt der
     gemeinsame Backdrop darunter — ohne das stünde der Dialog auf einem
     unabgedunkelten Drawer und die Fokusebene wäre nicht ablesbar. */
  background: oklch(0 0 0 / 0.5);
  /* Ohne das bleibt nach dem Schließen 220 ms lang eine unsichtbare,
     bildschirmfüllende Fläche liegen, die den nächsten Klick schluckt. */
  pointer-events: none;
}
.ov-modal.on { opacity: 1; pointer-events: auto; }
.ov-card {
  width: min(430px, 100%); background: var(--surface); border: 1px solid var(--border-2);
  border-radius: var(--r-3); box-shadow: var(--sh-pop); overflow: hidden;
  transform: scale(0.97); transition: transform var(--t-2) var(--e-out);
}
.ov-modal.on .ov-card { transform: none; }
.ov-card h2 { font-size: 1rem; padding: 17px 19px 0; }
.ov-text { padding: 8px 19px 17px; color: var(--muted); font-size: 0.89rem; line-height: 1.55; }
.ov-card .ov-foot { padding: 12px 19px; }
.btn.danger-solid {
  background: var(--danger); border-color: transparent;
  color: oklch(0.99 0 0); font-weight: 650;
}
.btn.danger-solid:hover { background: color-mix(in oklab, var(--danger) 86%, black); }

/* ── ⋮-Menü ─────────────────────────────────────────────────────────────── */
.ov-menu {
  position: fixed; z-index: var(--z-tip); min-width: 186px; padding: 5px;
  background: var(--surface-2); border: 1px solid var(--border-2); border-radius: var(--r-2);
  box-shadow: var(--sh-pop); opacity: 0; transform: translateY(-4px);
  transition: opacity var(--t-1), transform var(--t-1) var(--e-out);
}
.ov-menu.on { opacity: 1; transform: none; }
.ov-menu button {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px; width: 100%;
  padding: 7px 10px; border: 0; border-radius: 6px; background: transparent; cursor: pointer;
  color: var(--ink); font: inherit; font-size: 0.86rem; text-align: left;
}
.ov-menu button:hover:not(:disabled) { background: var(--surface-3); }
.ov-menu button:disabled { color: var(--faint); cursor: not-allowed; }
.ov-menu button.danger { color: var(--danger); }
.ov-menu .mi-hint { color: var(--faint); font-size: 0.74rem; flex: none; }

/* Zeilenaktionen auf Touch-Geräten sichtbar lassen — ohne Hover wären sie
   sonst dauerhaft unerreichbar. */
@media (hover: none) { .t-actions { opacity: 1; } }
.t-actions .btn.icon.sm { padding: 4px 7px; line-height: 1; }

@media (prefers-reduced-motion: reduce) {
  .ov-drawer { transform: none; }
}

/* Zuständige Rollen: hinzufügen und entfernen statt Mehrfachauswahl
   ------------------------------------------------------------------
   Vorher stand hier ein <select multiple>. Das listete ALLE Serverrollen
   untereinander, die Auswahl war nur ein blasser Balken — und direkt darunter
   der Satz „Nur diese Rollen sehen die Tickets dieser Art". Genau daraus
   entstand der Eindruck, es seien alle Rollen zuständig, obwohl keine einzige
   gewählt war. Jetzt stehen dort NUR die gewählten. */
.zr { display: flex; flex-direction: column; gap: 9px; }
.zr-chips { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; min-height: 34px; }
.zr-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 6px 5px 11px; border-radius: 999px;
  border: 1px solid var(--border-2); background: var(--surface-2);
  font-size: 0.86rem; max-width: 100%;
}
.zr-chip > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Eine gespeicherte, in Discord aber gelöschte Rolle: sichtbar als Problem
   markiert statt stillschweigend verschwiegen. */
.zr-chip.zr-weg { border-style: dashed; opacity: 0.75; }
.zr-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 19px; height: 19px; flex: none; padding: 0;
  border: 0; border-radius: 50%; cursor: pointer;
  background: transparent; color: var(--muted); font-size: 0.78rem; line-height: 1;
  transition: background var(--t-1), color var(--t-1);
}
.zr-x:hover { background: var(--danger, #e5484d); color: #fff; }
.zr-x:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.zr-add { max-width: 320px; }
