/* ============================================================
   style.css - Wirio Design System 💜
   Farbpalette: beruhigend, modern, augenfreundlich (Lavender).
   Helles Theme als Standard; Dark Mode automatisch, wenn das
   Betriebssystem des Nutzers dunkel eingestellt ist.
   ============================================================ */

* { margin: 0; padding: 0; box-sizing: border-box; }

/* ---------- Helles Theme (Standard) ---------- */
:root {
  /* Breite der Kanal-/Chatspalte. Die Sprachleiste unten richtet
     sich danach, damit sie buendig darin sitzt. */
  --sidebar-breite: clamp(320px, 28vw, 430px);

  --bg:            #F8F9FC;  /* Soft Gray: App-Hintergrund */
  --bg-chat:       #F4F1FF;  /* Lavender Mist: Chat-Hintergrund */
  --panel:         #FFFFFF;  /* Pure White: Karten, Sidebar */
  --hover:         #F4F1FF;  /* Hover-Flächen */
  --selected:      #CFC3F4;  /* Lavender Light: ausgewählte Chats */
  --border:        #E6E4F2;
  --text:          #2D3142;  /* Text Dark */
  --text-dim:      #6B7280;  /* Text Secondary */
  --accent:        #7E78B8;  /* Wirio Lavender */
  --accent-hover:  #9188D8;  /* Hover: heller (lt. Design-System) */
  --accent-press:  #6A64A8;  /* Gedrückt: dunkler */
  --on-accent:     #FFFFFF;
  --input-border:  #E5E7EB;
  --card:          #FFFFFF;  /* Chatkarten (lt. Design-System: weiß) */
  --list-bg:       #F8F9FC;  /* Hintergrund der Chatliste: Soft Gray */
  /* Fast pures Glas: nur ~10-15% Tönung, der Rest ist Blur */
  --bubble-mine:       rgba(213, 200, 255, 0.16);  /* eigene Nachrichten */
  --bubble-mine-text:  #2D3142;
  --bubble-theirs:     rgba(255, 255, 255, 0.10);  /* empfangene Nachrichten */
  --bubble-theirs-text:#2D3142;
  /* Lichtschimmer oben links auf dem Glas (wie in der Vorlage) */
  --bubble-sheen: linear-gradient(145deg, rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0.05) 55%);
  /* Glas-Rezept: dünn für Leisten, dicht für Dialoge/Menüs
     (dicht = lesbar, auch wenn dahinter viel Text liegt) */
  --glass-bg:     rgba(252, 251, 255, 0.62);
  --glass-strong: rgba(255, 255, 255, 0.85);
  /* Scrollleiste: halbtransparenter Lavender-Griff */
  --scrollbar-thumb:       rgba(126, 120, 184, 0.30);
  --scrollbar-thumb-hover: rgba(126, 120, 184, 0.55);
  /* Sanfter Glow um die Sprechblasen (nach Fabians Design-Vorlage) */
  --glow-mine:   0 1px 3px rgba(45, 49, 66, 0.07), 0 0 14px rgba(126, 120, 184, 0.30);
  --glow-theirs: 0 1px 3px rgba(45, 49, 66, 0.07), 0 0 12px rgba(126, 120, 184, 0.14);
  --bubble-edge: rgba(255, 255, 255, 0.65);   /* heller Glas-Rand */
  --online:        #7BC67B;  /* sanftes Grün */
  --offline:       #C9CCD8;
  --read:          #7DA7D9;  /* Pastellblau: gelesen */
  --danger:        #D97878;  /* sanftes Rot */
  --chat-pattern:  url('/chat-pattern-light.svg');  /* Doodle-Hintergrund */
  /* Sprachkanal-Buehne: bei Discord ist die Buehne etwas dunkler bzw.
     kraeftiger als der Chat daneben - hier die hellen Gegenstuecke.
     Feste Farben waeren hier falsch: Die Buehne war im Hellmodus ein
     schwarzer Klotz in einer weissen App (nachgemessen). */
  --buehne-bg:     #ECEAF6;
  --buehne-kachel: #FFFFFF;
  --knopf-bg:      #E4E1F2;
  --knopf-hover:   #D6D2EA;
  --knopf-text:    #2D3142;
  /* Ebenen-Ordnung, damit sich Fenster und Dialoge nicht streiten */
  --z-buehne:  40;    /* Deckel ueber dem Chat */
  --z-popout:  50;    /* schwebende Fenster (Chat, Stream) */
  --z-dialog:  70;    /* Dialoge liegen ueber allem Schwebenden */
  /* Die Rueckfrage liegt ueber ALLEM, auch ueber den Einstellungen.
     Sie stand auf 60 und ging deshalb hinter ihnen auf: Man klickte
     etwas an, nichts schien zu passieren, und die Frage wartete
     unsichtbar dahinter. Wer hier etwas Neues hoeher legt, macht
     denselben Fehler noch einmal. */
  --z-frage:   90;
}

/* ---------- Dark Mode ----------
   Gilt in zwei Fällen:
   1. Nutzer hat "Dunkel" gewählt  -> :root[data-theme="dark"]
   2. Nutzer hat "Automatisch" (oder nichts) gewählt UND das System
      steht auf dunkel -> @media, aber NICHT wenn "Hell" erzwungen ist
   Die Farbwerte stehen einmal in einer wiederverwendeten Regel. */
:root[data-theme="dark"],
:root[data-theme="auto"].sys-dark,
:root:not([data-theme]).sys-dark {
  --bg:            #15121F;  /* App-Hintergrund (tiefes Violett-Schwarz) */
  --bg-chat:       #191527;  /* Chat-Hintergrund, minimal heller */
  --panel:         #221E36;  /* Karten/Menüs/Popups/Eingabefeld */
  --hover:         #2C2749;  /* Hover-Flächen, Reaktionen */
  --selected:      #3B3363;  /* ausgewählt / eigene Reaktion */
  --border:        #2E2947;  /* Trennflächen, sehr dezent */
  --text:          #F5F5F7;  /* Haupttext, fast weiß */
  --text-dim:      #C7CBD6;  /* Sekundärtext (Zeitstempel/Status) */
  --accent:        #9188D8;  /* Wirio Lavender Dark */
  --accent-hover:  #A79AF2;  /* Lavender Accent (Hover/aktive Icons) */
  --accent-press:  #7E78B8;  /* gedrückt */
  --on-accent:     #FFFFFF;
  --input-border:  #322B52;  /* Rand Eingabefeld */
  --card:          #241F3B;  /* Chatkarten */
  --list-bg:       #171322;  /* Seitenleiste */
  /* Fast pures Glas: nur ~10-15% Tönung, der Rest ist Blur */
  --bubble-mine:       rgba(120, 108, 190, 0.16);  /* eigene (Lavendel-Hauch) */
  --bubble-mine-text:  #F5F5F7;
  --bubble-theirs:     rgba(120, 126, 165, 0.12);  /* empfangene Nachrichten */
  --bubble-theirs-text:#F5F5F7;
  /* Lichtschimmer oben links auf dem Glas (dunkle Variante: zarter) */
  --bubble-sheen: linear-gradient(145deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0.02) 55%);
  /* Glas-Rezept: dünn für Leisten, dicht für Dialoge/Menüs */
  --glass-bg:     rgba(25, 21, 39, 0.55);
  --glass-strong: rgba(34, 30, 54, 0.90);
  /* Scrollleiste: halbtransparenter Lavender-Griff */
  --scrollbar-thumb:       rgba(145, 136, 216, 0.30);
  --scrollbar-thumb-hover: rgba(145, 136, 216, 0.55);
  /* Glow wirkt im Dunkeln stärker -> etwas kräftiger erlaubt */
  --glow-mine:   0 0 18px rgba(145, 136, 216, 0.35);
  --glow-theirs: 0 0 14px rgba(210, 210, 240, 0.14);
  --bubble-edge: rgba(255, 255, 255, 0.10);   /* zarter Glas-Rand */
  --online:        #6FCF97;  /* Online (Dark-Variante) */
  --offline:       #555B6E;
  --chat-pattern:  url('/chat-pattern-dark.svg');  /* Doodle-Hintergrund (dunkel) */
  /* Sprachkanal-Buehne im Dunkelmodus: etwas dunkler als der Chat,
     wie bei Discord - die Kacheln heben sich davon ab. */
  --buehne-bg:     #0F0D18;
  --buehne-kachel: #201C31;
  --knopf-bg:      #2B2740;
  --knopf-hover:   #3A3556;
  --knopf-text:    #FFFFFF;
}

/* Dark-Mode-Feinheiten aus der Design-Vorgabe:
   ausgewählter Chat mit Glow, eigene Reaktion, Profilbild-Ring */
:root[data-theme="dark"] #contact-list li.active,
:root[data-theme="dark"] #group-list li.active,
:root[data-theme="auto"].sys-dark #contact-list li.active,
:root[data-theme="auto"].sys-dark #group-list li.active,
:root:not([data-theme]).sys-dark #contact-list li.active,
:root:not([data-theme]).sys-dark #group-list li.active {
  background: #312D4D;
  box-shadow: 0 0 0 1px rgba(145, 136, 216, 0.35), 0 6px 20px rgba(0, 0, 0, 0.28);
}
:root[data-theme="dark"] .reaction-chip.mine,
:root[data-theme="auto"].sys-dark .reaction-chip.mine,
:root:not([data-theme]).sys-dark .reaction-chip.mine {
  background: #4D4585;
}
:root[data-theme="dark"] #my-avatar .avatar,
:root[data-theme="dark"] #profile-avatar .avatar,
:root[data-theme="auto"].sys-dark #my-avatar .avatar,
:root[data-theme="auto"].sys-dark #profile-avatar .avatar,
:root:not([data-theme]).sys-dark #my-avatar .avatar,
:root:not([data-theme]).sys-dark #profile-avatar .avatar {
  box-shadow: 0 0 0 2px var(--accent);
}

body {
  /* Schrift lt. Design-System: Inter / SF Pro, nüchtern statt verspielt.
     (Nutzt die Systemschrift des Geräts - Apple-Geräte bekommen SF Pro,
      der Rest Inter/Segoe, ohne dass wir Schriften nachladen müssen.) */
  /* 'Noto Color Emoji' am Ende: Text nutzt Inter/SF Pro, aber alle
     Emojis werden einheitlich aus unserer mitgelieferten Font
     gezeichnet - so sehen sie auf PC und Handy gleich aus. */
  /* system-ui MUSS vor 'Noto Color Emoji' stehen: die Emoji-Font deckt
     laut unicode-range auch die normalen Ziffern 0-9 ab (Emoji-Tasten-
     kappen wie 1️⃣ bestehen aus Ziffer + Variantenzeichen). Wo keine der
     Textschriften vorhanden ist - etwa unter Android, wo weder SF Pro
     noch Segoe UI existieren - zeichnete sonst die Emoji-Font alle
     Zahlen: Uhrzeiten, Preise, Ungelesen-Zaehler. */
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Text',
               'Manrope', 'Segoe UI', system-ui, 'Noto Color Emoji', sans-serif;
  background: var(--bg);
  color: var(--text);
  height: 100vh;
  height: 100dvh;   /* dvh = echte sichtbare Höhe am Handy (Adressleiste!) */
  /* Und wenn die Tastatur offen ist, gilt die gemessene Hoehe:
     dvh kennt die Adressleiste, aber nicht die Tastatur. Gesetzt
     wird sie in tastatur.js. */
  height: var(--app-hoehe, 100dvh);
  overflow: hidden;
  /* Kein Weiterreichen des Wischens an die Seite dahinter. */
  overscroll-behavior: none;
  /* Hier stand einmal position: fixed mit top: var(--app-oben) -
     die App hing am Sichtfenster und wanderte mit, wenn das iPhone
     es verschob. Das war die Antwort darauf, dass sich die
     Schreibzeile wegschieben liess.

     Wieder heraus, weil die Geste inzwischen an der Quelle
     unterbunden wird (siehe #send-form weiter unten) - und weil der
     Umbau einen Preis hatte: Die Leiste des Geraets (Uhr, WLAN,
     Akku) leuchtete danach weiss. Die faerbt iOS selbst, richtet
     sich dabei aber danach, wie die Seite aufgebaut ist. */
}

.view { height: 100vh; height: 100dvh; height: var(--app-hoehe, 100dvh); }
.hidden { display: none !important; }

/* Zurück-Knopf: nur am Handy sichtbar (siehe Media Query unten) */
/* Nur am Handy sinnvoll: Dort ersetzt der Chat die Liste, hier
   steht sie daneben. Bewusst NICHT in der Sammelregel fuer
   Icon-Knoepfe - die wuerde dieses "none" ueberschreiben. */
#btn-back { display: none; }

/* ---------- Login-Ansicht ---------- */
#auth-view { display: flex; flex-direction: column; align-items: center; justify-content: center; }

.auth-box {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 36px;
  /* Nicht mehr fest 340px: Mit dem QR daneben braucht die Box mehr
     Platz, ohne ihn (Handy, Registrieren) bleibt sie schmal. */
  width: auto;
  max-width: calc(100vw - 32px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  box-shadow: 0 6px 24px rgba(126, 120, 184, 0.10);
}
#register-box { width: 340px; }
@media (max-width: 700px) {
  .auth-box, #register-box { width: 340px; max-width: calc(100vw - 32px); }
}
/* ---------- QR-Sucher (Kamera in der App) ----------
   Bildschirmfüllend: Beim Zielen soll man nichts anderes treffen
   können, und der Code darf gross im Bild stehen.               */
#qr-sucher {
  position: fixed;
  inset: 0;
  z-index: var(--z-dialog, 60);
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}
#qr-sucher.hidden { display: none; }
#qr-sucher-video {
  width: 100%;
  height: 100%;
  object-fit: cover;      /* lieber beschneiden als verzerren */
}
/* Der Rahmen ist nur eine Zielhilfe - er liegt über dem Bild und
   fängt keine Klicks ab, sonst käme man nicht mehr an den Knopf. */
/* Ohne Kamerabild kein Zielrahmen - siehe qr-scanner.js */
#qr-sucher.kein-bild #qr-sucher-rahmen { display: none; }
#qr-sucher-rahmen {
  position: absolute;
  width: min(70vw, 260px);
  aspect-ratio: 1;
  border: 3px solid rgba(255, 255, 255, 0.9);
  border-radius: 18px;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.45);   /* alles ausserhalb abdunkeln */
  pointer-events: none;
}
#qr-sucher-hinweis {
  position: absolute;
  left: 16px; right: 16px;
  bottom: calc(96px + env(safe-area-inset-bottom, 0px));
  text-align: center;
  color: #fff;
  font-size: 15px;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
}
#btn-qr-sucher-zu {
  /* Gemessen waren es 43 Pixel hoch - knapp unter dem, was ein
     Daumen sicher trifft. Und dieser Knopf ist der einzige Weg
     aus einer bildschirmfuellenden Kameraansicht heraus. */
  min-height: 44px;
  position: absolute;
  bottom: calc(28px + env(safe-area-inset-bottom, 0px));
  padding: 12px 28px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.15);
  border: 1px solid rgba(255, 255, 255, 0.5);
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  backdrop-filter: blur(6px);
}

/* ---------- Die zwei Wege in der Anmeldung ----------
   Breit: nebeneinander, mit einer Trennlinie dazwischen - links
   tippen, rechts scannen. Schmal (Handy): nur die linke Spalte, der
   QR waere dort sinnlos.                                          */
.auth-wege { display: flex; gap: 28px; align-items: stretch; }
.auth-spalte {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 268px;                 /* wie bisher: 340 minus Innenrand */
}
#qr-anmeldung {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 210px;
  padding-left: 28px;
  border-left: 1px solid var(--border);
  text-align: center;
}
/* Der Code selbst: weisser Grund, sonst lesen ihn Kameras im dunklen
   Modus schlecht - schwarz auf dunkelblau ist kein Kontrast. */
#qr-anmeldung-bild {
  background: #fff;
  border-radius: 10px;
  padding: 8px;
  line-height: 0;
}
#qr-anmeldung-bild svg { width: 160px; height: 160px; display: block; }
#qr-anmeldung-titel { font-weight: 600; font-size: 14px; }
/* Der Code zum Abtippen: weit auseinander und in fester Schrift -
   man liest ihn vom anderen Gerät ab und tippt ihn ein, da zählt
   jedes Zeichen einzeln. */
#qr-anmeldung-kurz-titel { font-size: 12px; color: var(--text-dim); margin-top: 4px; }
#qr-anmeldung-kurz {
  font-family: Consolas, 'Courier New', monospace;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 3px;
  color: var(--accent);
  user-select: all;              /* ein Klick markiert ihn ganz */
}
#qr-anmeldung-info { font-size: 12px; color: var(--text-dim); line-height: 1.45; }
#qr-anmeldung-stand { font-size: 12px; color: var(--accent); min-height: 16px; }

/* Am Handy steht der Code nicht sofort da - er wuerde die schmale
   Maske fuellen. Ein Tipp auf "Mit einem anderen Gerät anmelden"
   klappt ihn auf (Klasse "offen"), dann steht er unter den Feldern
   statt daneben. Gescannt wird er auf dem anderen Geraet. */
@media (max-width: 700px) {
  #qr-anmeldung { display: none; }
  #qr-anmeldung.offen {
    display: flex;
    width: 100%;
    padding-left: 0;
    border-left: none;
    border-top: 1px solid var(--border);
    padding-top: 18px;
    margin-top: 4px;
  }
  .auth-wege { flex-direction: column; gap: 0; }
  .auth-spalte { width: 100%; }
}

.auth-box h1 {
  text-align: center;
  margin-bottom: 8px;
  font-size: 26px;
  font-weight: 600;          /* Semibold lt. Design-System */
  color: var(--accent);
}

/* Das Wirio-Logo über dem Login */
.auth-box .logo {
  width: 84px;
  height: 84px;
  border-radius: 20px;
  align-self: center;
  box-shadow: 0 4px 14px rgba(126, 120, 184, 0.25);
}

/* Das Maskottchen bringt sein Leuchten selbst mit - ein zusaetzlicher
   CSS-Schatten wuerde den weichen Glow nachzeichnen und dabei wie ein
   ausgeschnittenes Rechteck wirken. Deshalb hier bewusst keiner. */

/* Maskottchen auf der Login-Seite */
.auth-mascot {
  width: 128px;
  height: auto;
  align-self: center;
  margin-bottom: -4px;
}

input, textarea {
  background: var(--panel);
  border: 1px solid var(--input-border);
  border-radius: 12px;
  padding: 10px 12px;
  color: var(--text);
  font-size: 15px;
  outline: none;
  transition: border-color 200ms ease;
}
input:focus, textarea:focus { border-color: var(--accent); }
input::placeholder, textarea::placeholder { color: var(--text-dim); }
/* Mehrzeilige Felder erben den Schriftschnitt der App statt der
   Schreibmaschinenschrift, die Browser sonst nehmen */
textarea { font-family: inherit; line-height: 1.45; resize: vertical; }

button {
  background: var(--accent);
  border: none;
  border-radius: 12px;
  padding: 10px 16px;
  color: var(--on-accent);
  font-size: 15px;
  cursor: pointer;
  transition: background 200ms ease;   /* weiche Übergänge (180-250ms) */
}
button:hover { background: var(--accent-hover); }
button:active { background: var(--accent-press); transform: scale(0.97); }  /* leichtes Eindrücken */
button.secondary {
  background: var(--hover);
  border: 1px solid var(--border);
  color: var(--text);
}
button.secondary:hover { background: var(--selected); }
button.small {
  padding: 4px 10px;
  font-size: 13px;
  background: var(--hover);
  color: var(--text);
  border: 1px solid var(--border);
}
button.small:hover { background: var(--selected); }

/* ---------- Icons (SVG, nehmen die Textfarbe an) ---------- */
.icon { display: block; }
button .icon { pointer-events: none; }

/* Jeder Knopf in der Chat-Kopfzeile enthaelt nur ein Symbol und
   gehoert mittig. Bewusst ueber den Bereich statt ueber eine Liste
   von Nummern: Die Liste darunter wird von Hand gepflegt, und
   genau deshalb sass der neue Mehr-Knopf drei Pixel zu hoch -
   er stand in keiner. */
#chat-header button {
  /* NUR ausrichten, KEIN display setzen. "#chat-header button" ist
     spezifischer als "#btn-chat-suche" - ein display hier hat das
     Ausblenden der einzelnen Knoepfe ueberstimmt, und am Handy
     standen ploetzlich wieder alle sieben in der Zeile (Titelbreite
     0 statt 150). Die Knoepfe bekommen ihr flex ohnehin von der
     Sammelregel darunter. */
  align-items: center;
  justify-content: center;
}

/* Buttons, die nur ein Icon enthalten, mittig ausrichten */
#send-btn, #btn-emoji, #btn-attach, #btn-mic, #btn-cancel-rec,
#btn-call, #btn-video, #btn-add-member, #btn-new-group,
#btn-story-photo, #btn-story-cancel, #btn-story-publish,
#btn-viewer-close, .call-buttons button, #btn-reply-cancel, #btn-edit-cancel {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Chat-Header-Buttons: runde, dezente Icon-Knöpfe in Lavender
   (wie im Design: Line-Icon in Markenfarbe) */
#chat-header .small, #sidebar header .small, .section-title .small {
  background: transparent;
  border: none;
  color: var(--accent);
  padding: 7px;
  border-radius: 50%;
}
#chat-header .small:hover, #sidebar header .small:hover,
.section-title .small:hover {
  background: var(--hover);
}

/* Profil-Buttons mit Icon + Text: Icon links */
#profile-logout, #profile-push { display: inline-flex; align-items: center; gap: 8px; }
#profile-logout .icon, #profile-push .icon { flex-shrink: 0; }

.auth-buttons { display: flex; gap: 8px; }
.auth-buttons button { flex: 1; }
.error { color: var(--danger); font-size: 14px; text-align: center; min-height: 18px; }

/* Impressum/Datenschutz-Links unter dem Login */
/* Hinweis auf das Programm - eine Spur kraeftiger als die
   Rechtslinks darunter, aber noch dezent: ein Angebot, keine
   Aufforderung. */
.programm-hinweis { text-align: center; font-size: 13px; margin-bottom: 6px; }
.programm-hinweis a { color: var(--accent); text-decoration: none; }
.programm-hinweis a:hover { text-decoration: underline; }

.legal-links { text-align: center; font-size: 13px; }
.legal-links a { color: var(--text-dim); text-decoration: none; }
.legal-links a:hover { color: var(--accent); text-decoration: underline; }

/* ---------- Messenger-Ansicht ---------- */
#chat-view { display: flex; }

#sidebar {
  /* PC: deutlich breiter und mitwachsend (min. 320px, sonst ~28% der
     Fensterbreite, hoechstens 430px) - so sieht man mehr Chat-Vorschau
     und spaeter die Kanaele der Wirio-Server */
  width: var(--sidebar-breite);
  flex-shrink: 0;
  background: var(--list-bg);   /* Soft Gray - die Karten heben sich ab */
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
}

/* Chat-Suche */
.search-box { padding: 10px 12px 0; }
.search-box input { width: 100%; }
#sidebar header {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
  color: var(--accent);
}

.add-contact { display: flex; gap: 6px; padding: 10px; position: relative; }
.add-contact input { flex: 1; min-width: 0; }
.add-contact button { padding: 8px 14px; }

/* Vorschlagsliste unter dem Hinzufügen-Feld */
/* (#user-suggest gab es, solange die Nutzersuche als Zeile in der
   Seitenleiste hing. Sie steckt längst in einem eigenen Fenster -
   die Trefferzeilen darunter sind geblieben.) */
.suggest-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 9px 12px;
  background: transparent;
  border: none;
  color: var(--text);
  font-size: 14px;
  text-align: left;
}
.suggest-row:hover { background: var(--hover); }
.suggest-row .avatar {
  width: 30px; height: 30px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
.suggest-row .avatar.fallback {
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 13px;
}

/* Scrollbarer Bereich mit beiden Listen (Gruppen + Kontakte) */
.lists { overflow-y: auto; flex: 1; }

.section-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 16px 4px;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}

/* Chatkarten (lt. Design-System): weiße Karten mit weichem Schatten
   und 14px-Radius auf Soft Gray statt Zeilen mit Trennlinien */
#contact-list, #group-list { list-style: none; padding: 8px 12px 0; }
#contact-list li, #group-list li {
  padding: 12px 14px;
  padding-right: 52px;      /* Platz für das Ungelesen-Badge rechts */
  cursor: pointer;
  background: var(--card);
  border-radius: 14px;
  margin-bottom: 8px;
  box-shadow: 0 1px 3px rgba(45, 49, 66, 0.06);
  position: relative;
}

/* ---------- Profilbilder (Avatare) ---------- */
.avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;         /* Foto füllt den Kreis, ohne zu verzerren */
  flex-shrink: 0;
}
.avatar.fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: 17px;
}

/* Listeneintrag mit Avatar: Bild links, Text rechts daneben */
li.with-avatar {
  display: flex;
  align-items: center;
  gap: 11px;
}
.li-text { min-width: 0; flex: 1; }

/* Eigenes Profil oben: Avatar (klein) + Name, klickbar */
#me-box {
  display: flex;
  align-items: center;
  gap: 9px;
  cursor: pointer;
  min-width: 0;
}
#me-box .avatar { width: 32px; height: 32px; font-size: 14px; }
#me-box:hover #my-name { text-decoration: underline; }
#my-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Ungelesen-Badge: lila Zahl, vertikal mittig am rechten Rand */
.badge {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  background: var(--accent);
  color: var(--on-accent);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  padding: 3px 8px;
  min-width: 24px;
  text-align: center;
}
#contact-list li, #group-list li { transition: background 200ms ease; }
#contact-list li:hover, #group-list li:hover { background: var(--hover); }
/* Ausgewählter Chat: dünner Lavender-Streifen + nur LEICHTE Tönung,
   nicht voll einfärben (lt. Design-System) */
#contact-list li.active, #group-list li.active {
  background: rgba(207, 195, 244, 0.18);   /* Hauch von Lavender Light */
  border-left: 3px solid var(--accent);
}
.contact-name {
  font-weight: 600;
  display: flex; align-items: center; gap: 7px;
  min-width: 0;              /* sonst darf der Name nicht schrumpfen */
}
/* Nur der Name kuerzt - Punkt, Glocke und Sprachkanal-Chip daneben
   bleiben stehen. Ohne das brachen lange Namen um und die Zeilen
   der Liste wurden unterschiedlich hoch. */
.name-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.contact-last {
  font-size: 13px;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
}

/* Online-Status-Punkt */
.dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
.dot.online  { background: var(--online); }
/* Kein grauer Punkt fuer "offline": Nur Anwesenheit ist eine
   Nachricht wert. Die Regel bleibt stehen, damit die Farbe
   definiert ist, falls der Punkt irgendwo gebraucht wird. */
.dot.offline { background: var(--offline); display: none; }

#chat-area {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  /* Dezentes Doodle-Muster hinter den Nachrichten (Wirio-Stil).
     Liegt auf dem Chat-Bereich fest, die Nachrichten scrollen darüber. */
  background-color: var(--bg-chat);
  background-image: var(--chat-pattern);
  background-repeat: repeat;
  /* Die Kachelung bleibt fein: Werden die Symbole groesser, faellt
     jedes einzelne staerker auf. Zurueckhaltend wird das Muster ueber
     die Deckkraft in der SVG-Datei (0.07 statt frueher 0.20). */
  background-size: 300px 300px;
}
#chat-header {
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
  font-weight: 600;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}
#chat-title {
  flex: 1;                 /* füllt die Mitte -> steht links neben ← */
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

#messages {
  flex: 1;
  overflow-y: auto;
  /* Kein Nachrutschen durch den Browser: Chromium haelt beim
     Einfuegen von Inhalt OBERHALB des Sichtfensters die Ansicht von
     selbst still (scroll anchoring). Beim Nachladen aelterer
     Nachrichten rechnet ladeAeltere() denselben Ausgleich aber noch
     einmal - zusammen war es das Doppelte, und die Ansicht landete
     ganz unten bei der neuesten Nachricht.

     Der eigene Ausgleich muss bleiben: Safari kennt scroll anchoring
     nicht, dort gaebe es sonst gar keinen. Also den des Browsers ab.
     (Nachgemessen: Sprung auf 4104 statt 2089 - genau der doppelte
     Weg.) */
  overflow-anchor: none;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Leerer Zustand: freundliches Maskottchen, wenn kein Chat offen ist */
#empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 24px;
  text-align: center;
}
#empty-state.hidden { display: none; }
#empty-state .mascot { width: 190px; height: auto; }
#empty-text { color: var(--text-dim); font-size: 16px; max-width: 320px; }

/* Nachrichtenblasen: 18px-Radius, sehr dezenter Schatten,
   weiches Einblenden statt Springen (lt. Design-System) */
.msg {
  max-width: 65%;
  padding: 9px 14px;
  border-radius: 18px;
  font-size: 15px;
  line-height: 1.4;
  word-wrap: break-word;
  box-shadow: 0 1px 3px rgba(45, 49, 66, 0.07);
  animation: msg-in 220ms ease both;
  /* Milchglas: verwischt das Doodle-Muster hinter der Blase */
  backdrop-filter: blur(12px) saturate(1.15);
  -webkit-backdrop-filter: blur(12px) saturate(1.15);   /* Safari/iPhone */
}
@keyframes msg-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes chat-in {
  from { opacity: 0; transform: scale(0.98); }
  to   { opacity: 1; transform: scale(1); }
}
.msg.mine {
  align-self: flex-end;
  /* Glas-Schimmer ÜBER der getönten Fläche (zwei Schichten) */
  background: var(--bubble-sheen), var(--bubble-mine);
  color: var(--bubble-mine-text);
  border-bottom-right-radius: 5px;
  border: 1px solid var(--bubble-edge);
  box-shadow: var(--glow-mine);
}
.msg.theirs {
  align-self: flex-start;
  background: var(--bubble-sheen), var(--bubble-theirs);
  color: var(--bubble-theirs-text);
  border-bottom-left-radius: 5px;
  border: 1px solid var(--bubble-edge);
  box-shadow: var(--glow-theirs);
}
.msg .time { display: block; font-size: 11px; opacity: 0.6; margin-top: 3px; text-align: right; }

/* ---------- Sprachnachricht (WhatsApp-Anordnung) ----------
   [Play] [Wellenform mit Punkt / Zeiten] [Avatar+Mikro bzw. 1.0x] */
.voice-msg {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 260px;
  padding: 4px 2px;
}

/* Play/Pause: nacktes Symbol ohne Kreis, in der Blasen-Textfarbe */
.voice-play {
  width: 36px; height: 36px;
  border: none;
  background: transparent;
  color: currentColor;
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0;
}

/* Rechts: Avatar mit kleinem Mikro-Abzeichen */
.voice-avatar-wrap {
  position: relative;
  width: 44px; height: 44px;
  flex-shrink: 0;
}
.voice-avatar-wrap .avatar {
  width: 44px; height: 44px;
  border-radius: 50%;
  object-fit: cover;
}
.voice-avatar-wrap .avatar.fallback {
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 17px;
}
.voice-mic-badge {
  position: absolute;
  bottom: -2px; left: -5px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
}

/* Mittelteil: Wellenform oben, Zeitleiste darunter */
.voice-mid {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Wellenform: Säulen in der Textfarbe der Blase - blass für
   Ungespieltes, kräftig für den bereits gehörten Teil.
   Tippen/Ziehen darin spult (touch-action: none hält dem
   Browser das Scrollen fern). */
.voice-wave {
  position: relative;   /* Anker für den Positions-Punkt */
  display: flex;
  align-items: center;
  gap: 2px;
  height: 30px;
  cursor: pointer;
  touch-action: none;
}
/* Der Punkt, der die Abspielposition zeigt (wandert mit) */
.voice-dot {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--accent);
  pointer-events: none;   /* Tippen geht durch auf die Wellenform */
  box-shadow: 0 0 4px rgba(126, 120, 184, 0.5);
}
.voice-wave span {
  flex: 1;
  min-width: 2px;
  border-radius: 2px;
  background: currentColor;
  opacity: 0.32;
  transition: opacity 120ms;
}
.voice-wave span.on { opacity: 1; }

/* Unter der Wellenform: aktuelle Zeit links, Gesamtdauer rechts */
.voice-times {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.voice-time {
  font-size: 11px;
  opacity: 0.75;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;   /* Zeit "zappelt" nicht */
}

/* Rechte Spalte: Tempo-Pille + Herunterladen */
.voice-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.voice-speed {
  border: none;
  border-radius: 12px;
  padding: 4px 9px;
  font-size: 12px;
  font-weight: 700;
  background: var(--accent);
  color: #fff;
  min-width: 44px;
}
.msg.mine .voice-speed { background: rgba(255, 255, 255, 0.92); color: var(--accent); }

/* Absendername über fremden Nachrichten in Gruppen */
.msg .sender {
  font-size: 12px;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 2px;
}

/* Haken: ✓ = gesendet, ✓✓ = gelesen */
.checks { margin-left: 5px; }
.checks.read { color: var(--read); opacity: 1; }

/* Platzhalter, während verschlüsselte Medien geladen werden */
.media-loading { font-size: 13px; opacity: 0.7; padding: 6px 0; }

/* Nachrichten sind antippbar (öffnet das Aktions-Menü) */
.msg { cursor: pointer; }

/* Zitat-Block in der Blase (worauf geantwortet wurde) */
.reply-quote {
  border-left: 3px solid var(--accent);
  background: rgba(126, 120, 184, 0.10);
  border-radius: 8px;
  padding: 5px 9px;
  margin-bottom: 5px;
  font-size: 13px;
}
.reply-quote-name { font-weight: 700; color: var(--accent); font-size: 12px; }
.reply-quote-text {
  opacity: 0.8;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 240px;
}

/* Aktions-Menü an einer angetippten Nachricht */
.msg-actions {
  display: flex;
  gap: 2px;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 6px;
  margin-top: 6px;
  box-shadow: 0 4px 14px rgba(22, 25, 36, 0.18);
  width: max-content;
  animation: msg-in 180ms ease;
}
.msg-actions button {
  background: transparent;
  border: none;
  font-size: 17px;
  padding: 3px 5px;
  border-radius: 50%;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.msg-actions button:hover { background: var(--hover); }
.msg-actions button:active { background: var(--selected); }
.msg-actions .act-icon { color: var(--accent); }        /* Antworten/Bearbeiten in Lavender */
.msg-actions .act-danger { color: var(--danger); }       /* Löschen in Rot */
/* schmaler Trenner zwischen Emoji-Reaktionen und Aktions-Icons */
.msg-actions-sep {
  width: 1px;
  align-self: stretch;
  background: var(--border);
  margin: 4px 3px;
}

/* Reaktions-Chips unter der Nachricht */
/* Die Reaktionen haengen UNTER der Blase, nicht darin.

   Vorher lagen sie innerhalb und waren damit auf die Breite der
   Blase eingeschnuert: Sechs Reaktionen an einer Nachricht mit dem
   Wort "Viele" stapelten sich zu einer 152 px hohen Saeule, die
   seitlich herausstand. Absolut positioniert und mit max-content
   bleiben sie einzeilig, egal wie kurz die Nachricht ist. */
.reactions {
  position: absolute;
  top: 100%;
  margin-top: -6px;
  display: flex;
  gap: 4px;
  flex-wrap: nowrap;
  width: max-content;
  z-index: 1;
}
/* Bei eigenen Nachrichten rechts buendig, sonst links - so bleibt
   die Reihe an der Seite, an der die Blase steht. */
.msg.theirs .reactions { left: 8px; }
.msg.mine .reactions { right: 8px; }
/* Die Reihe liegt ausserhalb und nimmt keinen Platz ein - die
   Blase muss ihn also selbst schaffen. */
.msg.hat-reaktionen { margin-bottom: 16px; }
.reactions.hidden { display: none; }
.reaction-chip {
  /* Eigene Hoehe mitbringen: Seit die Reihe schwebt, gibt ihr
     niemand mehr eine - die Chips waren auf 13 px zusammengefallen
     und kaum zu treffen. */
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  background: var(--hover);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 999px;
  padding: 1px 8px;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
.reaction-chip.mine { background: var(--selected); border-color: var(--accent); }
.reaction-chip:hover { background: var(--selected); }

/* Emoji-Auswahl über dem Eingabefeld (mit Suche + Kategorien) */
#emoji-panel {
  display: flex;
  flex-direction: column;
  padding: 8px 10px;
  background: var(--panel);
  border-top: 1px solid var(--border);
}
#emoji-panel.hidden { display: none; }

#emoji-search {
  width: 100%;
  margin-bottom: 8px;
  background: var(--bg);
  border: 1px solid var(--input-border);
  border-radius: 10px;
  padding: 8px 12px;
  font-size: 14px;
  color: var(--text);
  outline: none;
}
#emoji-search:focus { border-color: var(--accent); }

/* Reiter-Leiste (Kategorien) */
#emoji-tabs {
  display: flex;
  gap: 2px;
  overflow-x: auto;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.emoji-tab {
  background: transparent;
  border: none;
  font-size: 20px;
  /* waren 30 px hoch - zu wenig zum sicheren Treffen */
  min-width: 40px;
  height: 38px;
  padding: 0 8px;
  border-radius: 10px;
  line-height: 1;
  flex-shrink: 0;
  opacity: 0.7;
}
.emoji-tab:hover { background: var(--hover); opacity: 1; }
.emoji-tab.active { background: var(--selected); opacity: 1; }

#emoji-cat-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-dim);
  padding: 8px 2px 4px;
}

#emoji-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  /* 180 px zeigten bei 414 px Inhalt weniger als die Haelfte - man
     scrollte staendig. Der vh-Anteil sorgt dafuer, dass die Leiste
     auf kleinen Geraeten nicht den halben Bildschirm frisst. */
  max-height: min(250px, 30vh);
  overflow-y: auto;
  /* Der Bildlauf soll im Raster bleiben und nicht den Chat
     dahinter mitziehen. */
  overscroll-behavior: contain;
}
.emoji-btn {
  background: transparent;
  border: none;
  font-size: 23px;
  /* Feste, quadratische Trefferflaeche statt Polsterung: So ist sie
     unabhaengig davon, wie breit das einzelne Emoji gezeichnet wird
     (Flaggen und Familien sind deutlich breiter als ein Smiley). */
  width: 40px;
  height: 40px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  line-height: 1;
}
.emoji-btn:hover { background: var(--hover); }
.emoji-empty {
  color: var(--text-dim);
  font-size: 14px;
  padding: 16px;
  width: 100%;
  text-align: center;
}

/* Standort-Link in einer Nachricht */
.location-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
  padding: 4px 0;
}
.location-link:hover { text-decoration: underline; }

/* Profil-Menü (Dropdown beim Klick aufs Profilbild) */
#profile-menu {
  position: absolute;
  top: 54px;
  left: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 6px 24px rgba(45, 49, 66, 0.18);
  padding: 6px;
  z-index: 30;
  min-width: 210px;
  /* Ohne Obergrenze zog die lange Zeile mit den Rechtslinks das
     Menue bis an den linken Bildschirmrand - es sah aus wie eine
     eingeblendete Seite, nicht wie ein Menue, das aus dem eigenen
     Bild aufklappt. */
  max-width: min(300px, calc(100vw - 48px));
}
#profile-menu.hidden { display: none; }
.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: transparent;
  border: none;
  color: var(--text);
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 15px;
  text-align: left;
}
.menu-item:hover { background: var(--hover); }
.menu-item .icon { flex-shrink: 0; color: var(--accent); }
.menu-item.danger { color: var(--danger); }
.menu-item.danger .icon { color: var(--danger); }
#sidebar header { position: relative; }   /* Anker für das Menü */

/* "Henning tippt..." - eine kleine Blase, die unten links über dem
   Eingabefeld schwebt. Vorher war es ein Balken über die ganze
   Breite, der den Chat nach oben schob, sobald jemand tippte. */
#typing-indicator {
  position: absolute;
  left: 14px;
  /* Sitzt direkt ueber dem Eingabefeld: Die Blase ist ein Kind des
     Formulars, "100 Prozent" ist also dessen Oberkante. Waechst das
     Feld, wandert sie von selbst mit. */
  bottom: 100%;
  margin-bottom: 8px;
  z-index: 5;
  padding: 6px 12px;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.22);
  font-size: 12.5px;
  font-style: normal;
  color: var(--text-dim);
  animation: msg-in 180ms ease;
  pointer-events: none;      /* nie im Weg beim Tippen */
  max-width: calc(100% - 28px);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#typing-indicator .ty-name { color: var(--accent); font-weight: 600; }
#typing-indicator.hidden { display: none; }

/* Knopf in einem Leerzustand: Er nimmt dem Text die Arbeit ab.
   Ein leerer Bereich soll nicht erklaeren, was man tun koennte -
   er soll es anbieten. */
.empty-action {
  margin-top: 18px;
  padding: 11px 22px;
  border-radius: 22px;
  border: none;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: background 160ms ease, transform 120ms ease;
}
.empty-action:hover { background: var(--accent-hover); }
.empty-action:active { transform: scale(0.97); }

/* Der Kanal, den man gerade anschaut. Heller Grund und kraeftigere
   Schrift - dieselbe Sprache wie beim aktiven Chat in der Liste. */
.channel-item.aktiv {
  background: var(--selected);
}
.channel-item.aktiv > span {
  color: var(--text);
  font-weight: 600;
}
/* Ein Balken an der Seite, wie beim aktiven Server in der
   Schmalleiste - dieselbe Bedeutung, dieselbe Form. */
.channel-item {
  position: relative;
}
.channel-item.aktiv::after {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 60%;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}

/* ---------- Kanalgruppen (wie bei Discord) ---------- */
.channel-gruppe {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 14px 5px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
  list-style: none;
  cursor: default;
}
.ch-plus {
  width: 22px;
  height: 22px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--text-dim);
  border-radius: 6px;
  cursor: pointer;
  opacity: 0.7;
}
.ch-plus:hover { background: var(--hover); color: var(--accent); opacity: 1; }

/* ---------- Herausgeloestes Chat-Fenster mit Reitern ---------- */
/* EIN Fenster, das ueber allem schwebt und beim Bereichswechsel
   stehen bleibt. Weitere Chats kommen als Reiter dazu. */
.popout {
  position: fixed;
  z-index: var(--z-popout);   /* mit dem Stream-Fenster auf einer Ebene */
  width: 340px;
  height: 420px;
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.42);
  overflow: hidden;
}
.popout.zieht { user-select: none; cursor: grabbing; }

/* Griffleiste - hier stehen die Reiter, und hier wird gezogen */
.po-kopf {
  display: flex;
  align-items: stretch;
  background: var(--hover);
  border-bottom: 1px solid var(--border);
  cursor: grab;
  flex-shrink: 0;
  touch-action: none;      /* sonst scrollt das Geraet beim Ziehen */
  min-height: 38px;
}
.po-reiter {
  display: flex;
  gap: 3px;
  padding: 5px 6px;
  overflow-x: auto;
  scrollbar-width: none;
  flex: 1;
  min-width: 0;
}
.po-reiter::-webkit-scrollbar { display: none; }

.po-reiter-knopf {
  display: flex;
  align-items: center;
  gap: 5px;
  max-width: 130px;
  padding: 5px 7px 5px 10px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-dim);
  font-size: 12.5px;
  cursor: pointer;
  flex-shrink: 0;
}
.po-reiter-knopf:hover { background: var(--border); }
.po-reiter-knopf.aktiv {
  background: var(--panel);
  color: var(--text);
  font-weight: 600;
}
.po-reiter-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Zaehler am Reiter, wenn dort etwas ankam, waehrend er nicht vorn
   war. Rot, weil es um Aufmerksamkeit geht - und mit Zahl, damit
   man sieht, ob es eine Nachricht war oder zwanzig. */
.po-reiter-zahl {
  min-width: 17px;
  height: 17px;
  padding: 0 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9px;
  background: var(--danger);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1;
  flex-shrink: 0;
}
.po-reiter-zahl.hidden { display: none; }
.po-reiter-zu {
  display: flex; align-items: center; justify-content: center;
  width: 17px; height: 17px;
  border-radius: 5px;
  color: var(--text-dim);
  flex-shrink: 0;
}
.po-reiter-zu:hover { background: var(--border); color: var(--text); }

.po-buehne { flex: 1; min-height: 0; display: flex; }
.po-liste {
  flex: 1;
  overflow-y: auto;
  padding: 12px 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  /* Derselbe Doodle-Hintergrund wie im grossen Chat. Die
     Vorgabe (scroll) haelt ihn an der Flaeche fest, statt ihn mit
     den Nachrichten mitlaufen zu lassen - genauso wie dort. */
  background-color: var(--bg-chat);
  background-image: var(--chat-pattern);
  background-repeat: repeat;
  background-size: 300px 300px;
}
.po-liste.hidden { display: none; }

.po-msg {
  /* Ohne align-self fuellt eine Blase in einer Spalte die ganze
     Breite - sie stand dann quer durchs Fenster, egal wie kurz der
     Satz war. Sie soll sich an den Inhalt schmiegen. */
  align-self: flex-start;
  position: relative;
  max-width: 78%;
  /* Rechts bleibt Platz fuer die Uhrzeit, die dort schwebt -
     im schmalen Fenster spart das je Nachricht eine Zeile. */
  padding: 6px 46px 6px 11px;
  border-radius: 14px;
  border: 1px solid var(--bubble-edge);
  background: var(--bubble-sheen), var(--bubble-theirs);
  color: var(--bubble-theirs-text);
  border-bottom-left-radius: 5px;
  font-size: 13.5px;
  line-height: 1.4;
  word-break: break-word;
}
.po-msg.mine {
  align-self: flex-end;
  background: var(--bubble-sheen), var(--bubble-mine);
  color: var(--bubble-mine-text);
  border-bottom-left-radius: 14px;
  border-bottom-right-radius: 5px;
}
/* Folgt eine Blase derselben Person, ruecken sie zusammen und die
   Ecke bleibt rund - der Zipfel gehoert nur an das Ende. */
.po-msg.folgt { margin-top: -3px; }
.po-msg.theirs.folgt { border-bottom-left-radius: 14px; }
.po-msg.mine.folgt { border-bottom-right-radius: 14px; }
/* Uhrzeit: klein, rechts, unaufdringlich - wie im grossen Chat */
.po-zeit {
  position: absolute;
  right: 9px;
  bottom: 5px;
  font-size: 10.5px;
  opacity: 0.5;
  line-height: 1;
  white-space: nowrap;
}
.po-wer { font-size: 11.5px; font-weight: 600; color: var(--accent); margin-bottom: 2px; }
.po-sys {
  align-self: center;
  font-size: 11.5px;
  color: var(--text-dim);
  padding: 3px 9px;
  border-radius: 9px;
  background: var(--hover);
}

.po-form {
  display: flex;
  gap: 7px;
  padding: 9px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
.po-form input {
  flex: 1; min-width: 0;
  padding: 8px 11px;
  border-radius: 9px;
  border: 1px solid var(--input-border);
  background: var(--bg);
  color: var(--text);
  font-size: 13.5px;
  outline: none;
}
.po-form input:focus { border-color: var(--accent); }
/* Anfasser zum Groesserziehen, unten rechts. Zwei kurze Striche
   statt eines Symbols - so machen es Fenster ueberall, und es
   braucht kein eigenes Bild. */
.po-groesse {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 16px;
  height: 16px;
  cursor: nwse-resize;
  touch-action: none;
  z-index: 2;
}
.po-groesse::before,
.po-groesse::after {
  content: '';
  position: absolute;
  right: 3px;
  background: var(--text-dim);
  opacity: 0.5;
  border-radius: 1px;
}
.po-groesse::before { bottom: 3px; width: 9px; height: 1.5px; transform: rotate(-45deg); transform-origin: right bottom; }
.po-groesse::after { bottom: 3px; width: 5px; height: 1.5px; transform: rotate(-45deg); transform-origin: right bottom; margin-bottom: 4px; }
.po-groesse:hover::before, .po-groesse:hover::after { opacity: 0.9; }


.po-senden {
  width: 34px; height: 34px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  cursor: pointer; flex-shrink: 0;
}

/* Am Handy waere ein schwebendes Fenster kaum zu bedienen - der
   Bildschirm ist selbst nicht viel groesser. Dort bleibt es beim
   normalen Chat. */
@media (max-width: 700px) {
  #btn-popout { display: none; }
  .popout { display: none; }
}

/* ---------- Erwaehnungen ---------- */
/* Im Text: dezent hervorgehoben, damit man sie beim Ueberfliegen
   findet - aber nicht so laut, dass sie den Satz zerreisst. */
.mention {
  color: var(--accent);
  font-weight: 600;
  border-radius: 4px;
  padding: 0 2px;
}
/* Bin ich selbst gemeint, darf es deutlicher sein - das ist die
   Nachricht, die man suchen wuerde. */
.mention.mich {
  background: var(--selected);
  color: var(--accent);
}

/* Die Vorschlagsliste beim Tippen von @ */
.mention-liste {
  position: fixed;
  z-index: 45;
  max-height: 240px;
  overflow-y: auto;
  padding: 5px;
  border-radius: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.34);
}
.mention-eintrag {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: 9px;
  background: transparent;
  cursor: pointer;
  text-align: left;
}
.mention-eintrag:hover, .mention-eintrag.aktiv { background: var(--hover); }
.mention-eintrag .avatar { width: 26px; height: 26px; font-size: 11px; flex-shrink: 0; }
.mention-name { font-size: 14px; color: var(--text); font-weight: 600; }
.mention-handle { font-size: 12px; color: var(--text-dim); margin-left: auto; }

/* ---------- Nach einem Einladungslink ---------- */
#join-modal {
  position: fixed;
  inset: 0;
  z-index: 62;
  background: rgba(15, 12, 25, 0.62);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
#join-modal.hidden { display: none; }
.join-box {
  width: min(92vw, 380px);
  max-height: 85vh;
  overflow-y: auto;
  padding: 26px 22px 20px;
  border-radius: 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
  text-align: center;
  animation: popup-in 200ms ease;
}
#join-avatar .avatar { width: 72px; height: 72px; font-size: 28px; margin: 0 auto; }
#join-name { margin-top: 12px; font-size: 19px; font-weight: 700; color: var(--text); }
#join-count { margin-top: 3px; font-size: 13px; color: var(--text-dim); }


.join-actions { display: flex; gap: 10px; margin-top: 20px; }
.join-actions button { flex: 1; }

/* ---------- Server als Bilder in der Schmalleiste ---------- */
/* Klappen unter dem Server-Knopf auf. Die volle Hoehe steht in
   --voll und wird beim Fuellen ausgerechnet - "auto" laesst sich
   nicht weich uebergehen. */
#rail-servers {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  max-height: 0;
  /* "overflow: hidden" waere der naheliegende Weg, die Hoehe zu
     begrenzen - es schneidet aber auch SEITLICH ab, und damit den
     Balken am aktiven Server (der links aus dem Knopf herausragt).
     clip-path schneidet nur oben und unten: Die negativen Werte
     links und rechts lassen dort alles stehen. */
  overflow: visible;
  clip-path: inset(0 -60px);
  transition: max-height 260ms ease, opacity 200ms ease, margin 260ms ease;
  opacity: 0;
  /* Zugeklappt ist die Leiste zwar null hoch, zaehlt in der Spalte
     aber weiter als eigenes Element - der Abstand zwischen Server
     und Marktplatz waere dadurch doppelt so gross (20 statt 10 px).
     Der negative Rand hebt genau diesen einen Zwischenraum auf. */
  margin: 0 0 -10px;
}
#rail-servers.offen {
  max-height: var(--voll, 320px);
  opacity: 1;
  margin: 6px 0;
}

/* Nur der Server, in dessen Sprachkanal man sitzt. Gilt, wenn man
   den Server-Bereich verlassen hat - so sieht man weiter, wo
   gesprochen wird, ohne die ganze Liste vor Augen zu haben. */
#rail-servers.nur-sprachkanal .rail-server-btn { display: none; }
#rail-servers.nur-sprachkanal .rail-server-btn.spricht { display: block; }

/* Zeichen am unteren Rand des Bildes, wenn man dort im Sprachkanal
   sitzt - wie bei Discord. Ein Ring waere mehrdeutig, ein
   Lautsprecher ist es nicht.
   Der Rand in Hintergrundfarbe schneidet das Zeichen sauber aus dem
   Bild aus, statt es daraufzukleben. */
.rail-voice-badge {
  position: absolute;
  right: -2px;
  bottom: -2px;
  width: 17px;
  height: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--online);
  border: 2.5px solid var(--bg);
  color: #fff;
  pointer-events: none;
}
.rail-voice-badge svg { width: 10px; height: 10px; }

.rail-server-btn {
  position: relative;
  width: 40px;
  height: 40px;
  padding: 0;
  border: none;
  background: transparent;
  border-radius: 50%;
  cursor: pointer;
  flex-shrink: 0;
  transition: border-radius 160ms ease;
}
.rail-server-btn .avatar {
  width: 40px; height: 40px; font-size: 16px;
  border-radius: 50%;
  transition: border-radius 160ms ease;
}
/* Beim Zeigen und beim offenen Server wird aus dem Kreis ein
   abgerundetes Quadrat - so macht es Discord, und es zeigt ohne
   Worte, welcher gerade offen ist. */
.rail-server-btn:hover .avatar,
.rail-server-btn.aktiv .avatar { border-radius: 14px; }

/* Der Name beim Zeigen - wie bei Discord. Sitzt am Dokument, weil
   die Serverleiste seitlich abschneidet (overflow fuer die
   Aufklapp-Bewegung). Die Stelle rechnet zeigeServerName() aus. */
.rail-name {
  position: fixed;
  z-index: 60;
  transform: translateY(-50%) scale(0.96);
  transform-origin: left center;
  padding: 7px 11px;
  border-radius: 9px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.34);
  color: var(--text);
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;      /* nie im Weg */
  transition: opacity 120ms ease, transform 120ms ease;
}
.rail-name.sichtbar {
  opacity: 1;
  transform: translateY(-50%) scale(1);
}

/* Balken links am offenen Server */
.rail-server-btn.aktiv::before {
  content: '';
  position: absolute;
  left: -10px;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 22px;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}

/* Wer Bewegung abgestellt hat, bekommt sie auch hier nicht */
@media (prefers-reduced-motion: reduce) {
  #rail-servers { transition: none; }
}

/* ---------- Mitgliederliste rechts (wie bei Discord) ---------- */
#member-panel {
  width: 220px;
  flex-shrink: 0;
  overflow-y: auto;
  padding: 12px 8px;
  background: var(--panel);
  border-left: 1px solid var(--border);
}
#member-panel.hidden { display: none; }
/* Vom Nutzer weggeklappt - gilt in jeder Bildschirmgroesse */
#member-panel.zu { display: none; }

.mp-titel {
  padding: 12px 8px 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.mp-person {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 8px;
  border-radius: 8px;
  cursor: pointer;
  user-select: none;             /* langes Druecken soll nichts markieren */
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
.mp-person:hover { background: var(--hover); }
.mp-person .avatar { width: 28px; height: 28px; font-size: 12px; }
.mp-name {
  font-size: 14px;
  color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Profilkarte beim Linksklick (Discord zeigt so etwas auch) */
.mp-karte {
  position: fixed;
  z-index: 72;
  width: 260px;
  padding: 14px;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.4);
}
.mk-kopf { display: flex; align-items: center; gap: 11px; }
.mk-bild.avatar { width: 52px; height: 52px; font-size: 20px; }
.mk-namen { min-width: 0; }
.mk-name {
  font-size: 16px; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mk-handle { font-size: 12.5px; color: var(--text-dim); }
.mk-abschnitt {
  margin-top: 12px; padding-top: 10px;
  border-top: 1px solid var(--border);
}
.mk-titel {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-dim); margin-bottom: 5px;
}
.mk-eingabe {
  width: 100%;
  margin-top: 12px;
  padding: 9px 11px;
  border-radius: 9px;
  border: 1px solid var(--input-border);
  background: var(--bg);
  color: var(--text);
  font-size: 13.5px;
  outline: none;
}
.mk-eingabe:focus { border-color: var(--accent); }
/* Gesperrt heisst: sichtbar, aber erkennbar nicht benutzbar */
.mk-eingabe:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  background: var(--hover);
}

/* Der Weg zur Freundschaft - dasselbe Zeichen wie in der Kopfzeile */
.mk-freund {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 8px;
  padding: 10px 12px;
  border: none;
  border-radius: 9px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.mk-freund:hover { background: var(--accent-hover); }
.mk-freund:disabled { opacity: 0.6; cursor: default; }
.mk-freund svg { flex-shrink: 0; }

/* Am Handy mittig statt neben der Zeile - dort ist kein Platz
   daneben, und die Karte waere halb ausserhalb. */
@media (max-width: 700px) {
  .mp-karte {
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%, -50%);
    width: min(88vw, 300px);
  }
}

/* Menue am Zeiger */
/* Dieselben Masse wie beim allgemeinen Rechtsklick-Menue
   (.kmenue) - zwei verschieden aussehende Menues in einer App
   fallen sofort auf. */
.mp-menue {
  position: fixed;
  z-index: 70;
  min-width: 190px;
  padding: 5px;
  border-radius: 11px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.36);
}
.mp-eintrag {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border: none;
  background: transparent;
  border-radius: 8px;
  font-size: 13.5px;
  color: var(--text);
  cursor: pointer;
}
.mp-eintrag svg { flex-shrink: 0; color: var(--text-dim); }
.mp-eintrag:hover svg { color: var(--text); }
.mp-eintrag.danger svg { color: var(--danger, #e5484d); }
/* Der Pfeil einer Untergruppe bleibt rechts stehen */
.mp-eintrag.mp-pfeil > span:first-of-type { flex: 1; }
.mp-eintrag:hover { background: var(--hover); }
.mp-eintrag.danger { color: var(--danger); }
.mp-trenner { height: 1px; margin: 5px 8px; background: var(--border); }

/* Uebergruppe: Beim Zeigen erscheint SEITLICH ein zweites Panel -
   das Hauptmenue bleibt dabei stehen, nichts springt. */
.mp-unter { position: relative; }
.mp-pfeil::after { content: '›'; float: right; opacity: 0.5; font-size: 16px; line-height: 1; }
.mp-unter:hover > .mp-pfeil { background: var(--hover); }

.mp-unterinhalt {
  display: none;
  position: absolute;
  /* Zwei Pixel Ueberlappung: Sonst reisst der Zeigerkontakt ab,
     wenn die Maus vom Eintrag zum Untermenue wandert. */
  left: calc(100% - 2px);
  top: -5px;
  min-width: 170px;
  padding: 5px;
  border-radius: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.36);
}
.mp-unter:hover > .mp-unterinhalt { display: block; }

/* Kein Platz mehr nach rechts? Dann nach links aufklappen. */
.mp-unterinhalt.nach-links {
  left: auto;
  right: calc(100% - 2px);
}

/* Am Handy nimmt die Liste den halben Bildschirm - deshalb nur auf
   Knopfdruck, und dann als Schicht ueber dem Verlauf. */
@media (max-width: 700px) {
  /* Am Handy schiebt sie sich herein, statt zu verschwinden -
     deshalb hier kein display:none. */
  #member-panel.zu { display: block; }
  #member-panel {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(78vw, 300px);
    z-index: 24;
    transform: translateX(100%);
    transition: transform 220ms ease;
    padding-top: calc(14px + env(safe-area-inset-top));
  }
  /* Am Handy faehrt sie herein, wenn sie NICHT zugeklappt ist */
  #member-panel:not(.zu) { transform: none; }
  /* Am Handy gibt es kein Zeigen mit der Maus: Ein Tipp auf die
     Uebergruppe klappt sie auf, und zwar untereinander - seitlich
     waere auf einem schmalen Bildschirm kein Platz. */
  .mp-unterinhalt {
    position: static;
    min-width: 0;
    margin: 2px 0 4px 10px;
    padding: 2px 0 2px 8px;
    border: none;
    border-left: 2px solid var(--border);
    border-radius: 0;
    background: transparent;
    box-shadow: none;
  }
  .mp-unter:hover > .mp-unterinhalt { display: none; }
  .mp-unter.offen > .mp-unterinhalt { display: block; }
  .mp-unter.offen > .mp-pfeil::after { content: '⌄'; }
}

/* Menue mit den Massnahmen bei einem Mitglied */
.mod-menue {
  /* fest im Fenster: Die Stelle rechnet zeigeModMenue() aus */
  position: fixed;
  /* ÜBER dem Fenster, aus dem es aufgerufen wird. Mit 60 lag es
     unter der Gruppeninfo (70): Man tippte auf die drei Punkte und
     es passierte scheinbar nichts - das Menü stand dahinter.
     Unterhalb der Rückfrage (90) muss es bleiben, damit ein
     "Wirklich entfernen?" darüber aufgeht. */
  z-index: calc(var(--z-dialog) + 5);
  min-width: 190px;
  padding: 5px;
  border-radius: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.32);
}
.mod-eintrag {
  display: block;
  width: 100%;
  text-align: left;
  padding: 9px 12px;
  border: none;
  background: transparent;
  border-radius: 8px;
  font-size: 14px;
  color: var(--text);
  cursor: pointer;
}
.mod-eintrag:hover { background: var(--hover); }
.mod-eintrag.danger { color: var(--danger); }
.mod-trenner { height: 1px; margin: 5px 8px; background: var(--border); }

/* Rang-Kennzeichen in der Mitgliederliste. Je hoeher der Rang,
   desto kraeftiger - Mitglieder tragen gar keins. */
.gi-admin.rang-1 { background: var(--hover); color: var(--text-dim); }
.gi-admin.rang-2 { background: var(--selected); color: var(--accent); }
.gi-admin.rang-3 { background: var(--accent); color: var(--on-accent); }

/* Der Herabstufen-Pfeil ist derselbe wie zum Befoerdern, nur
   gedreht - so braucht es kein zweites Symbol. */
.gi-promote.runter svg { transform: rotate(180deg); }

/* Info-Nachricht im Verlauf ("X ist beigetreten"). Bewusst keine
   Blase: Niemand hat sie geschrieben, sie gehoert keiner Seite. */
.sys-msg {
  align-self: center;
  max-width: 80%;
  margin: 10px auto;
  padding: 5px 12px;
  border-radius: 12px;
  background: var(--hover);
  color: var(--text-dim);
  font-size: 12.5px;
  text-align: center;
  line-height: 1.4;
}

/* ---------- Sprachkanaele ---------- */
/* Ein Sprachkanal sieht anders aus als ein Textkanal: Lautsprecher
   statt Raute, und darunter stehen die, die gerade drin sitzen. */
/* Das SVG ist von Haus aus ein Block-Element und schob den Namen
   dadurch in die naechste Zeile. */
.channel-item.voice-channel > span {
  display: flex;
  align-items: center;
  gap: 7px;
}
.channel-item.voice-channel > span svg { flex-shrink: 0; opacity: 0.75; }
/* Kein eigener Hintergrund, wenn jemand drinsitzt: Bei Discord
   bleibt der Kanal unauffaellig, die Runde darunter ist die
   Auskunft. Der Hintergrund liess ihn wie ausgewaehlt aussehen. */

/* Sitzt jemand drin, gehoert die Runde UNTER den Kanalnamen, nicht
   daneben - so macht es Discord, und nur so bleibt Platz fuer mehr
   als einen Namen. Die Kanalzeile ist ein flex in einer Reihe;
   umbrechen lassen und der Liste die volle Breite geben genuegt. */
/* Der rechte Rand ist beim Textkanal fuer das Ungelesen-Zeichen
   reserviert. Sprachkanaele haben keins - dort gehoert der Platz der
   Sitzungszeit. */
.channel-item.voice-channel { flex-wrap: wrap; padding-right: 14px; }
.channel-item.voice-channel.hat-leute { padding-bottom: 7px; }

.voice-members {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 6px 0 2px 22px;
}
.voice-member {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text-dim);
}
.voice-member .avatar { width: 20px; height: 20px; font-size: 10px; }
.voice-member.stumm { opacity: 0.55; }
.voice-member svg { opacity: 0.8; }

/* Die Leiste bleibt sichtbar, egal wo man in der App ist */
#voice-bar {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(72px + env(safe-area-inset-bottom));
  z-index: 25;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 14px;
  background: var(--panel);
  border: 1px solid var(--online);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
}
#voice-bar.hidden { display: none; }
#voice-bar-icon svg { color: var(--online); vertical-align: -3px; }
#voice-bar-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
#voice-bar-name {
  font-weight: 600; font-size: 14px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#voice-bar-count { font-size: 12px; color: var(--text-dim); }

/* Wie lange die Sitzung im Sprachkanal laeuft - am rechten Rand der
   Kanalzeile, fuer jeden sichtbar, der den Kanal sieht.
   Ziffern mit fester Breite, sonst zappelt die Zeile bei jedem
   Sekundenwechsel: eine 1 ist schmaler als eine 8. */
.channel-item .kanal-zeit {
  margin-left: auto;
  padding-left: 8px;
  font-size: 11.5px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;      /* nie schrumpfen - sonst steht dort "18:4" */
}
/* display:flex ist hier kein schmueckendes Beiwerk: Ohne das liegt
   das Symbol linksbuendig im Knopf statt in der Mitte - ein Knopf
   ist von Haus aus kein Flex-Behaelter. Derselbe Fehler wie
   seinerzeit bei der Kamera im Schreibfeld. */
#voice-bar button {
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
#voice-bar button.active-off { background: var(--danger); color: #fff; }

/* Solange die Sprachleiste steht, bekommen die scrollenden
   Bereiche darunter Platz. Sonst waere die letzte Zeile nicht mehr
   erreichbar - man scrollt bis ans Ende und die Leiste liegt davor.
   Die 78 px sind die Leistenhoehe plus ein wenig Luft. */
body.im-sprachkanal #chat-list,
body.im-sprachkanal #channel-list,
body.im-sprachkanal #server-list,
body.im-sprachkanal #contact-list { padding-bottom: 78px; }
body.im-sprachkanal #market-grid { padding-bottom: 86px; }

/* Am grossen Bildschirm sitzt die Leiste unten in der Kanalspalte -/* Am grossen Bildschirm sitzt die Leiste unten in der Kanalspalte -
   nicht daneben. Vorher stand sie mit fester Breite bei 76 px und
   damit auf gleicher Hoehe wie die Knoepfe der Schmalleiste; das
   wirkte gedraengt und liess die Knoepfe verschoben aussehen.
   Jetzt beginnt sie am rechten Rand der Schmalleiste (64 px) und
   endet mit der Spalte - so wie bei Discord. */
@media (min-width: 701px) {
  #voice-bar {
    left: calc(64px + 10px);
    right: auto;
    width: calc(var(--sidebar-breite) - 20px);
    bottom: 12px;
  }
}

/* Ladeplatzhalter: graue Blasen mit wanderndem Schimmer, solange
   der Verlauf unterwegs ist. Sie stehen dort, wo gleich die echten
   Nachrichten erscheinen. */
.msg-skeleton {
  height: 42px;
  margin: 12px 0;
  border-radius: 16px;
  max-width: 80%;
  background: linear-gradient(90deg,
    var(--hover) 25%, var(--border) 50%, var(--hover) 75%);
  background-size: 200% 100%;
  animation: skel-schimmer 1.4s linear infinite;
}
.msg-skeleton.mine { margin-left: auto; }   /* eigene Seite */
@keyframes skel-schimmer { to { background-position: -200% 0; } }

/* Gelöschte Nachricht: dezenter Platzhalter */
.msg.deleted {
  opacity: 0.7;
  font-style: italic;
  color: var(--text-dim) !important;
  background: var(--hover) !important;
  box-shadow: none;
  cursor: default;
}

/* Antwort-Leiste über dem Eingabefeld */
#reply-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 18px;
  background: var(--panel);
  border-top: 1px solid var(--border);
}
#reply-bar.hidden { display: none; }
.reply-info {
  flex: 1;
  min-width: 0;
  border-left: 3px solid var(--accent);
  padding-left: 9px;
}
#reply-name { display: block; font-weight: 700; color: var(--accent); font-size: 12px; }
#reply-text {
  display: block;
  color: var(--text-dim);
  font-size: 13px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Datums-Trenner im Chat: kleine Pille in der Mitte ("Heute") */
.date-divider {
  align-self: center;
  background: var(--card);
  color: var(--text-dim);
  font-size: 12px;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 999px;
  margin: 6px 0;
  box-shadow: 0 1px 2px rgba(45, 49, 66, 0.05);
}

/* Punkt im Chat-Header sauber ausrichten */
#chat-title .dot { display: inline-block; margin-right: 3px; }

/* ---------- Profil-Bereich (Tab am Handy) ---------- */
#profile-pane {
  display: none;              /* wird nur im Profil-Tab eingeblendet */
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 36px 22px;
}
#profile-pane .avatar { width: 96px; height: 96px; font-size: 36px; cursor: pointer; }
#profile-name { font-size: 20px; font-weight: 600; }
/* Der feste @handle unter dem Anzeigenamen (gedämpft, klein) */
#profile-handle { font-size: 14px; color: var(--text-dim); margin-top: 2px; }
/* @handle-Anhängsel neben Namen (Suche, Chat-Kopfzeile) */
.handle-tag {
  display: block;
  width: 100%;
  font-size: 12px;
  font-weight: 400;
  color: var(--text-dim);
  margin-top: 1px;
}
.profile-btn { width: 100%; max-width: 260px; }
#profile-pane .legal-links { margin-top: 10px; }

/* ---------- Status/Stories ---------- */
/* Die Status-Leiste kostet Platz, den die Chatliste besser gebrauchen
   kann. Sie erscheint deshalb nur, wenn es wirklich Beiträge gibt -
   sonst führt der Weg zum eigenen Status über das Plus-Menü. */
#story-strip {
  display: flex;
  gap: 12px;
  padding: 10px 14px 4px;
  overflow-x: auto;
}
#story-strip:empty { display: none; }
#story-strip.leer { display: none; }

.story-item { text-align: center; cursor: pointer; flex-shrink: 0; width: 56px; }
.story-ring {
  position: relative;
  width: 52px; height: 52px;
  border-radius: 50%;
  padding: 3px;
  display: flex; align-items: center; justify-content: center;
}
.story-ring .avatar { width: 44px; height: 44px; font-size: 18px; }
.story-ring.unseen { background: linear-gradient(135deg, var(--accent), #CFC3F4); }
.story-ring.seen   { background: var(--border); }
.story-ring.empty  { background: transparent; border: 2px dashed var(--border); }
/* Das Plus fuehrt zu einem weiteren Status - man kann beliebig
   viele nacheinander haben. Gross genug, um es am Handy sicher zu
   treffen, ohne aus Versehen den eigenen Status zu oeffnen. */
.story-plus {
  position: absolute;
  right: -3px; bottom: -3px;
  background: var(--accent);
  color: var(--on-accent);
  width: 26px; height: 26px;
  border-radius: 50%;
  /* Mittig durch Flex statt durch eine passend geraten line-height:
     Hier stand ein ＋ als Schriftzeichen, das je nach Schrift anders
     hoch sitzt. Jetzt ist es ein Symbol aus icons.js. */
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--panel);
  cursor: pointer;
}
.story-label {
  font-size: 11px;
  color: var(--text-dim);
  margin-top: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Status erstellen */
#story-composer {
  position: fixed; inset: 0;
  background: rgba(22, 25, 36, 0.65);
  display: flex; align-items: center; justify-content: center;
  z-index: 25;
}
#story-composer.hidden { display: none; }
.story-box {
  background: var(--panel);
  border-radius: 18px;
  padding: 16px;
  width: min(92vw, 380px);
  display: flex; flex-direction: column; gap: 12px;
}
#composer-preview {
  border-radius: 14px;
  min-height: 300px;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
#composer-preview img { max-width: 100%; max-height: 55vh; display: block; }
#story-text {
  background: transparent;
  border: none;
  color: #fff;
  font-size: 22px;
  font-weight: 600;
  text-align: center;
  width: 100%;
  min-height: 120px;
  resize: none;
  padding: 20px;
}
#story-text::placeholder { color: rgba(255, 255, 255, 0.7); }
.story-colors { display: flex; gap: 8px; justify-content: center; }
.color-chip {
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 2px solid var(--border);
  padding: 0;
}
.story-actions { display: flex; gap: 8px; justify-content: flex-end; }

/* Status ansehen (Vollbild) */
#story-viewer {
  position: fixed; inset: 0;
  background: #161924;
  z-index: var(--z-dialog);   /* wie die Einstellungen: ueber der Buehne */
  display: flex; flex-direction: column;
}
#story-viewer.hidden { display: none; }
#viewer-top {
  display: flex; align-items: center; gap: 10px;
  /* Der Betrachter fuellt den ganzen Bildschirm (inset: 0), und mit
     viewport-fit=cover reicht das bis unter die Notch. Ohne diesen
     Abstand lagen Name und Schliessen-Knopf dort darunter. */
  padding: calc(12px + env(safe-area-inset-top)) 16px 12px;
  color: #F5F5F7;
}
/* Schliessen, Loeschen, Melden: mit dem Daumen zu treffen.
   Gemessen waren es 42x30. */
#viewer-top button { min-width: 38px; min-height: 38px; }
#viewer-top .avatar { width: 38px; height: 38px; }
#viewer-name { font-weight: 600; }
#viewer-time { font-size: 12px; color: #9CA1B3; }
#viewer-views { margin-left: auto; font-size: 14px; color: #9CA1B3; }
#viewer-top button { flex-shrink: 0; }
#viewer-views { margin-left: auto; }
/* Wenn kein Augen-Zähler da ist, schiebt der Löschen-Knopf nach rechts */
#viewer-views.hidden + #btn-story-delete { margin-left: auto; }
#btn-story-delete {
  background: var(--danger);
  color: #fff;
  border: none;
}
#btn-story-delete:hover { background: #c96a6a; }
#viewer-content {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  overflow: hidden;
  color: #F5F5F7;
}
#viewer-content img { max-width: 100%; max-height: 100%; object-fit: contain; }
.story-text-view {
  /* Dieselbe Buehne wie bei Bildern: Hochformat, mittig, runde
     Ecken. Sonst schwebt der Text am breiten Bildschirm im Nichts. */
  width: auto;
  height: 100%;
  aspect-ratio: 9 / 16;
  max-width: 100%;
  margin: 0 auto;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;

  font-size: 26px;
  font-weight: 600;
  color: #fff;
  text-align: center;
  padding: 30px;
  word-wrap: break-word;
  /* Ohne Hintergrund waere der Rahmen unsichtbar - die Farbe kommt
     aus der Story selbst, das hier ist nur der Rueckfall. */
  background: #23263A;
}
/* Fortschrittsbalken oben: einer je Status, wie man es kennt */
#viewer-bars {
  display: flex; gap: 4px;
  padding: 10px 12px 2px;
}
.viewer-bar {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.28);
  overflow: hidden;
}
.viewer-bar > i {
  display: block;
  height: 100%;
  width: 0;
  background: #fff;
  border-radius: 2px;
}
/* Schon gesehen: ganz voll. Laufend: waechst in seiner eigenen Zeit. */
.viewer-bar.done > i { width: 100%; }
.viewer-bar.run  > i { animation: viewer-bar-fill linear forwards; }
@keyframes viewer-bar-fill { from { width: 0; } to { width: 100%; } }

/* Buehne mit den beiden Tippflaechen */
#viewer-stage {
  position: relative;
  flex: 1;
  display: flex;
  min-height: 0;
}
#viewer-stage #viewer-content { flex: 1; }
.viewer-tap {
  position: absolute;
  top: 0; bottom: 0;
  width: 32%;
  z-index: 2;
  -webkit-tap-highlight-color: transparent;
}
#viewer-back { left: 0; }
#viewer-next { right: 0; width: 68%; }

/* Beim Halten tritt alles Beiwerk zurueck, nur der Status bleibt */
#story-viewer.paused #viewer-bars,
#story-viewer.paused #viewer-top,
#story-viewer.paused #story-react-bar { opacity: 0; transition: opacity 200ms ease; }

@media (prefers-reduced-motion: reduce) {
  .settings-box { animation: none; }

  .msg-skeleton { animation: none; background: var(--hover); }

  .viewer-bar.run > i { animation: none; width: 100%; }
}

/* Bearbeiten-Leiste (gleicher Look wie die Antwort-Leiste) */
#edit-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 18px;
  background: var(--panel);
  border-top: 1px solid var(--border);
}
#edit-bar.hidden { display: none; }

/* Popups erscheinen mit Fade + leichtem Zoom (95% -> 100%) */
@keyframes popup-in {
  from { opacity: 0; transform: scale(0.95); }
  to   { opacity: 1; transform: scale(1); }
}
.settings-box, .forward-box, .call-box, .story-box, .auth-box {
  animation: popup-in 200ms ease;
}

/* ---------- Einstellungen ---------- */
#settings-modal {
  position: fixed; inset: 0;
  background: rgba(22, 25, 36, 0.55);
  display: flex; align-items: center; justify-content: center;
  /* Die Ebenen-Variable gab es laengst, nur benutzt hat sie hier
     niemand: Mit 28 lag der Dialog UNTER der Sprachkanal-Buehne (40)
     und ging hinter ihr auf. */
  z-index: var(--z-dialog);
}
#settings-modal.hidden { display: none; }
.settings-box {
  background: var(--panel);
  border-radius: 16px;
  width: min(92vw, 360px);
  max-height: 85vh;
  overflow-y: auto;
  /* Platz für den Rollbalken immer freihalten. Ohne das war der
     Kasten 360 px breit, solange der Inhalt hineinpasste, und 342,
     sobald er rollen musste - beim Umschalten zwischen den
     Kategorien sprang also die ganze Breite. */
  scrollbar-gutter: stable;
  box-shadow: 0 12px 40px rgba(22, 25, 36, 0.35);
}
.settings-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
}
.settings-section-title {
  font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--text-dim);
  padding: 14px 16px 6px;
}
#theme-options { padding: 4px 10px 14px; display: flex; flex-direction: column; gap: 4px; }
.theme-option {
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  background: transparent; border: 1.5px solid transparent;
  padding: 12px 14px;
  border-radius: 12px;
  color: var(--text);
  font-size: 15px;
  text-align: left;
}
.theme-option:hover { background: var(--hover); }
.theme-option .theme-ico { color: var(--accent); display: flex; }
.theme-option.active {
  background: rgba(126, 120, 184, 0.10);
  border-color: var(--accent);
}
.theme-option.active::after {
  content: '✓'; margin-left: auto; color: var(--accent); font-weight: 700;
}

/* iPhone-Installations-Hinweis (nur Safari-Tab, nicht standalone) */
#ios-install-hint {
  display: flex; align-items: center; gap: 10px;
  max-width: 340px;
  margin: 14px auto 0;
  background: rgba(126, 120, 184, 0.10);
  border: 1px solid var(--accent);
  border-radius: 14px;
  padding: 12px 14px;
  font-size: 13px;
  color: var(--text);
  line-height: 1.45;
}
#ios-install-hint.hidden { display: none; }
#ios-hint-close {
  background: transparent; border: none;
  color: var(--text-dim); font-size: 14px;
  flex-shrink: 0; padding: 4px;
}

/* Schlüssel-Sicherung */
/* Anzeigename ändern */
#name-card { padding: 4px 16px 14px; }
#name-info { font-size: 14px; color: var(--text-dim); line-height: 1.5; margin-bottom: 12px; }
#name-row { display: flex; gap: 8px; }
#name-row #name-input {
  flex: 1;
  min-width: 0;
  padding: 11px;
  border-radius: 12px;
  border: 1.5px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
}
#name-row .key-btn { flex: 0 0 auto; padding: 11px 18px; }

#key-card { padding: 4px 16px 14px; }
#key-info { font-size: 14px; color: var(--text-dim); line-height: 1.5; margin-bottom: 12px; }
/* Untereinander, nicht nebeneinander: In einer Reihe wurden aus vier
   Knöpfen vier schmale Spalten, deren Beschriftung über drei Zeilen
   brach - 80 Pixel breit und 84 hoch, während Passwort und 2FA
   darüber die volle Breite hatten. Jetzt sieht alles im Bereich
   gleich aus, egal wie viele Knöpfe es gerade sind. */
#key-actions { display: flex; flex-direction: column; gap: 8px; }
.key-btn {
  flex: 1;
  background: rgba(126, 120, 184, 0.10);
  color: var(--accent);
  border: 1.5px solid var(--accent);
  padding: 11px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
}
.key-btn:hover { background: rgba(126, 120, 184, 0.18); }

/* Konto löschen */
#delete-account-card { padding: 4px 16px 18px; }
.da-head { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
#da-icon {
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--hover); color: var(--accent);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
#da-title { font-size: 18px; font-weight: 600; }
#da-info { font-size: 14px; color: var(--text-dim); line-height: 1.5; margin-bottom: 12px; }
#da-warn {
  background: rgba(217, 120, 120, 0.10);
  border: 1px solid rgba(217, 120, 120, 0.30);
  border-radius: 12px;
  padding: 12px 14px;
  margin-bottom: 14px;
}
.da-warn-title {
  display: flex; align-items: center; gap: 8px;
  color: var(--danger); font-weight: 700; font-size: 14px; margin-bottom: 2px;
}
#da-warn-text { font-size: 13px; color: var(--text-dim); }
#btn-delete-account {
  width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  background: var(--danger);
  color: #fff;
  border: none;
  padding: 13px;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 600;
}
#btn-delete-account:hover { background: #c96a6a; }
#btn-delete-account .icon { color: #fff; }

/* ---------- Weiterleiten-Auswahl ---------- */
#forward-modal {
  position: fixed; inset: 0;
  background: rgba(22, 25, 36, 0.55);
  display: flex; align-items: center; justify-content: center;
  z-index: var(--z-dialog);   /* wie die Einstellungen: ueber der Buehne */
}
#forward-modal.hidden { display: none; }
.forward-box {
  background: var(--panel);
  border-radius: 16px;
  width: min(92vw, 360px);
  max-height: 70vh;
  display: flex; flex-direction: column;
  overflow: hidden;
  box-shadow: 0 12px 40px rgba(22, 25, 36, 0.35);
}
.forward-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
}
#forward-list { overflow-y: auto; padding: 6px; }
.forward-row {
  display: flex; align-items: center; gap: 11px;
  width: 100%;
  background: transparent; border: none;
  padding: 10px 12px;
  border-radius: 10px;
  color: var(--text);
  font-size: 15px;
  text-align: left;
}
.forward-row:hover { background: var(--hover); }
.forward-row .avatar { width: 38px; height: 38px; font-size: 15px; }

/* Kurze Bestätigungs-Einblendung (Toast) */
#toast {
  position: fixed;
  left: 50%; bottom: 90px;
  transform: translateX(-50%) translateY(10px);
  background: var(--text);
  color: var(--panel);
  padding: 9px 18px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease, transform 200ms ease;
  /* Ueber ALLEM. Eine Meldung wie "Kopiert" oder "Gemerkt" ist die
     Antwort auf etwas, das man gerade getan hat - meist in einem
     Dialog. Auf Ebene 40 lag sie darunter und war unsichtbar. */
  z-index: 200;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- Keine Verbindung ----------
   Oben, schmal, ueber allem - auch ueber offenen Fenstern, denn die
   Leitung fehlt ja dort genauso. Er liegt darueber statt darin: Ein
   Balken, der Platz wegnimmt, wuerde die ganze Ansicht springen
   lassen, sobald er kommt oder geht. */
#netz-hinweis {
  position: fixed;
  left: 50%;
  top: calc(env(safe-area-inset-top, 0px) + 10px);
  transform: translateX(-50%) translateY(-8px);
  max-width: calc(100vw - 32px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: var(--text);
  color: var(--panel);
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease, transform 200ms ease;
  z-index: 200;
}
#netz-hinweis.zeigen { opacity: 1; transform: translateX(-50%) translateY(0); }
#netz-hinweis.hidden { display: none; }

/* ---------- Anruf-Ansicht ---------- */
#call-overlay {
  position: fixed;
  inset: 0;
  background: rgba(22, 25, 36, 0.55);   /* Rest der App abdunkeln */
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 20;
  animation: msg-in 220ms ease;
}
#call-overlay.hidden { display: none; }

.call-box {
  position: relative;   /* Bezug fuer den Verkleinern-Knopf oben rechts */
  background: var(--panel);
  border-radius: 20px;
  padding: 36px 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  box-shadow: 0 12px 40px rgba(22, 25, 36, 0.35);
  min-width: 260px;
}
.call-box .avatar { width: 96px; height: 96px; font-size: 36px; }

/* ---- Videoanruf-Layout ---- */
#call-videos {
  position: relative;
  width: 100%;
  border-radius: 14px;
  overflow: hidden;
  background: #000;
}
#call-videos.hidden { display: none; }
#remote-video {
  display: block;
  width: 100%;
  max-height: 60vh;
  min-height: 220px;
  object-fit: cover;
  background: #000;
}
#local-video {
  position: absolute;
  right: 10px;
  bottom: 10px;
  width: 96px;
  border-radius: 10px;
  border: 2px solid rgba(255, 255, 255, 0.55);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}
/* Im Video-Modus: Box breiter, Avatar weg, Name/Status kompakt */
/* ============================================================
   Videoanruf: Vollbild
   Das Bild des Gegenübers füllt den Bildschirm, alles andere
   schwebt darüber. Vorher lag das Video in einer Karte, die nur
   etwa 40 Prozent der Fläche nutzte - das sah aus wie "Video mit
   Bedienleiste darunter" statt nach einem Anruf.
   ============================================================ */
#call-overlay.video {
  background: #0B0D14;
  padding: 0;
}
#call-overlay.video .call-box {
  isolation: isolate;
  width: 100%;
  height: 100%;
  max-width: none;
  padding: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  gap: 0;
  position: relative;
  justify-content: flex-start;
}
#call-overlay.video #call-videos {
  position: absolute;
  inset: 0;
  border-radius: 0;
  /* Ausdruecklich die unterste Ebene: Ein <video> wird sonst in einer
     eigenen Schicht gezeichnet und legt sich ueber alles, was keinen
     eigenen Stapelwert hat - die Knoepfe waren zwar anklickbar, aber
     nicht zu sehen. */
  z-index: 0;
}
#call-overlay.video #remote-video {
  width: 100%;
  height: 100%;
  max-height: none;
  object-fit: cover;
}
/* Bei laufendem Video sagen Bild und Name nichts Neues - man sieht
   die Person ja. Beides tritt zurück. */
#call-overlay.video .call-box > .avatar,
#call-overlay.video #call-avatar { display: none; }
#call-overlay.video #call-name {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 18px);
  left: 0; right: 0;
  text-align: center;
  font-size: 17px;
  color: #fff;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6);
  z-index: 2;
  pointer-events: none;
}
#call-overlay.video #call-status {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 42px);
  left: 0; right: 0;
  text-align: center;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.8);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6);
  z-index: 2;
  pointer-events: none;
}
/* Die Knöpfe schweben unten über dem Bild */
#call-overlay.video .call-buttons {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 28px);
  justify-content: center;
  margin: 0;
  z-index: 3;
  transition: opacity 300ms ease;
}
/* Nach ein paar Sekunden ohne Berührung treten sie zurück -
   ein Tippen aufs Bild holt sie wieder. */
#call-overlay.video.ruhe .call-buttons,
#call-overlay.video.ruhe #call-name,
#call-overlay.video.ruhe #call-status { opacity: 0; }

/* Eigenes Bild: schwebt frei und lässt sich verschieben */
#call-overlay.video #local-video {
  width: 108px;
  right: 14px;
  top: calc(env(safe-area-inset-top, 0px) + 70px);
  bottom: auto;
  z-index: 4;
  cursor: grab;
  touch-action: none;
}
#call-overlay.video #local-video.faesst-an { cursor: grabbing; }

/* Verkleinern im Videoanruf: rund und ohne Wort.

   Mit Wort war der Knopf 118 Pixel breit und lag ueber dem mittig
   stehenden Namen (Text 56..319, Knopf 245..363 - 74 Pixel
   Ueberlappung). Ohne Wort bleibt das Zeichen, das man aus der
   verkleinerten Leiste ohnehin kennt, und das Bild behaelt seinen
   Platz.

   Und die Notch: Name, Stand, Knopfreihe und das eigene Bild rechnen
   sie alle mit - dieser Knopf als einziger nicht. Auf einem iPhone
   lag er damit unter der Uhr. */
#call-overlay.video #btn-call-min {
  top: calc(env(safe-area-inset-top, 0px) + 12px);
  width: 44px;
  min-width: 44px;
  padding: 0;
  border-radius: 50%;
}
#call-overlay.video #btn-call-min span { display: none; }

/* Bleibt der Name trotzdem lang, kuerzt er - statt unter den Knopf
   zu laufen. Beidseitig gleich viel Abstand, damit die Mitte die
   Mitte bleibt. */
#call-overlay.video #call-name,
#call-overlay.video #call-status {
  padding-inline: 64px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#call-name { font-size: 21px; font-weight: 600; }
#call-status { color: var(--text-dim); min-height: 20px; }

.call-buttons { display: flex; gap: 10px; margin-top: 10px; }
.speaker-on { background: var(--accent) !important; color: var(--on-accent) !important; }
/* Anruf-Knopf im "aus"-Zustand (stumm / Kamera aus): rot getönt */
.call-buttons .active-off { background: var(--danger) !important; color: #fff !important; }
.call-accept  { background: var(--online); }     /* sanftes Grün */
.call-accept:hover { background: #6cb56c; }
.call-hangup  { background: var(--danger); }     /* sanftes Rot */
.call-hangup:hover { background: #c96a6a; }

/* ---------- Bottom-Navigation (nur Handy, siehe Media Query) ---------- */
#bottom-nav { display: none; }
.nav-btn {
  background: transparent;
  border: none;
  color: var(--text-dim);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  flex: 1;
  font-size: 21px;
  padding: 4px 0 2px;
  border-radius: 0;
  transition: color 200ms ease;
}
.nav-btn:hover, .nav-btn:active { background: transparent; }
.nav-btn span { font-size: 11px; font-weight: 600; }
.nav-btn.active { color: var(--accent); }   /* aktiver Tab: Lavender */

/* Letzter Platz der Leiste: das eigene Profilbild statt eines
   Symbols mit Beschriftung. Klick öffnet das Profil-Menü. */
.nav-me { justify-content: center; }
#nav-avatar .avatar {
  /* So gross wie in der Schmalleiste am Rechner (40 px). Vorher
     30 px - darauf wirkte der Statuspunkt viel wuchtiger, obwohl
     er dieselbe Groesse hat. */
  width: 38px; height: 38px;
  font-size: 15px;
  box-shadow: 0 0 0 2px transparent;
  transition: box-shadow 200ms ease;
}
/* Solange das Menü offen ist, bekommt das Bild denselben Lavender-Ring,
   den sonst der aktive Tab trägt */
.nav-me.open #nav-avatar .avatar { box-shadow: 0 0 0 2px var(--accent); }

/* Bilder und Videos in Nachrichten */
.msg img, .msg video {
  display: block;
  max-width: 100%;
  max-height: 320px;
  border-radius: 10px;
  margin-bottom: 4px;
}
.msg img { cursor: pointer; }   /* Klick = in voller Größe öffnen */
.msg video { min-width: 220px; }

/* Sprachnachrichten: kompakter Audio-Player */
.msg audio { display: block; width: 250px; max-width: 100%; margin-bottom: 4px; }

/* Mikro: Halten-Geste - der Browser darf daraus kein Scrollen
   oder Textmarkieren machen. transform lässt das Mikro dem
   Finger nach oben folgen. */
#btn-mic {
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  transition: transform 60ms linear;
}

/* Einrast-Anzeige: Pfeil + Schloss über dem Mikro */
#rec-lock {
  position: absolute;
  right: 16px;
  bottom: 76px;
  z-index: 14;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 7px;
  border-radius: 18px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 4px 14px rgba(45, 49, 66, 0.16);
  color: var(--accent);
  animation: lock-in 180ms ease;
}
#rec-lock.hidden { display: none; }
#rec-lock .rl-chev { display: flex; animation: chev-bounce 1s infinite; }
#rec-lock .rl-lock { display: flex; }

/* Eingerastet: Schloss wird kräftig lavender und hüpft kurz */
#rec-lock.locked {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  animation: lock-pop 220ms ease;
}
#rec-lock.locked .rl-chev { display: none; animation: none; }

@keyframes lock-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes chev-bounce {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}
@keyframes lock-pop {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.18); }
  100% { transform: scale(1); }
}

/* Mikrofon-Button während der Aufnahme: sanftes Rot, pulsierend */
#btn-mic.recording {
  background: var(--danger);
  color: #fff;
  animation: pulse 1.2s infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.6; }
}
#send-form {
  position: relative;      /* Bezugspunkt fuer die Tipp-Blase */
  display: flex;
  padding: 12px;
  border-top: 1px solid var(--border);
  background: var(--panel);
}

/* Die Composer-Leiste im WhatsApp-Stil: EINE runde Pille,
   in der die Icons und das Textfeld zusammen sitzen. */
#composer-pill {
  flex: 1;
  display: flex;
  /* flex-end statt center: Wenn das Textfeld mitwächst, sollen Emoji
     und Co. UNTEN stehen bleiben - so wandern sie nicht mit dem Text
     nach oben (gleiches Verhalten wie bei WhatsApp). */
  align-items: flex-end;
  gap: 2px;
  background: var(--hover);
  border-radius: 24px;
  padding: 4px 6px;
  min-width: 0;
}
/* min-width: 0 ist entscheidend: ohne das hat ein Textfeld eine
   eingebaute Mindestbreite (~200px) und sprengt am Handy die Zeile -
   die ganze Seite wird dann breiter als der Bildschirm! */
#composer-pill input,
#composer-pill textarea {
  flex: 1; min-width: 0;
  background: transparent;
  border: none;
  box-shadow: none;
  padding: 10px 6px;
}
#composer-pill input:focus,
#composer-pill textarea:focus { outline: none; border: none; box-shadow: none; }
#composer-pill button { flex-shrink: 0; }

/* Das mitwachsende Eingabefeld.
   Ein textarea bringt eigene Voreinstellungen mit, die hier
   ausgeräumt werden müssen: eigene Schrift, ein Anfasser zum
   Größerziehen und eine Grundlinie, die es in der Zeile verrutschen
   lässt. Die HÖHE selbst rechnet app.js aus (passeFeldhoeheAn). */
#send-input {
  font-family: inherit;       /* sonst nimmt es die Browser-Schrift */
  font-size: 16px;            /* unter 16px zoomt das iPhone beim Antippen */
  line-height: 20px;          /* feste Zeilenhöhe = verlässliches Rechnen */
  -webkit-text-size-adjust: 100%;   /* iOS soll die Schrift nicht anpassen */
  resize: none;               /* kein Anfasser in der Ecke */
  overflow-y: hidden;         /* wird bei Bedarf von app.js auf auto gesetzt */
  /* Sicherheitsnetz gegen ein plattgedrücktes Feld: Selbst wenn die
     Höhenmessung schiefgeht (z.B. weil das Feld beim Messen noch
     unsichtbar war), bleibt immer Platz für eine ganze Zeile. Genau
     das fehlte - am Handy stand der Text deshalb halb außerhalb. */
  min-height: 40px;
  max-height: 124px;          /* ~5 Zeilen + Innenabstand */
  /* Beim Rollen im Feld nicht die ganze Seite mitziehen */
  overscroll-behavior: contain;
}

/* Senden: runder Lavender-Kreis mit weißem Icon (nur sichtbar bei Text) */
#send-btn {
  width: 40px; height: 40px;
  padding: 0;
  border-radius: 50%;
  color: #fff;
}
/* Plus, Emoji & Mikrofon: nackte Icons in der Leiste (wie WhatsApp) */
#btn-emoji, #btn-attach, #btn-mic, #btn-cancel-rec {
  width: 40px; height: 40px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  border: none;
}
#btn-emoji:hover, #btn-attach:hover, #btn-mic:hover, #btn-cancel-rec:hover {
  background: var(--selected);
  color: var(--accent);
}

/* Anhang-Menü (Foto/Video, Standort) über dem 📎-Button */
#attach-menu {
  position: absolute;
  bottom: 66px;
  left: 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 6px 24px rgba(45, 49, 66, 0.18);
  padding: 6px;
  z-index: 15;
  min-width: 190px;
}
#attach-menu.hidden { display: none; }
#chat-area { position: relative; }   /* Anker für das Menü */

/* ============================================================
   Responsive Ansichten
   - Desktop  (> 1024px): Sidebar 280px + Chat (Standard oben)
   - Tablet   (701-1024px): schmalere Sidebar + Chat
   - Handy    (<= 700px): ENTWEDER Liste ODER Chat (WhatsApp-Stil),
     Wechsel über die Klasse .chat-open + Zurück-Knopf
   ============================================================ */

/* ---------- Tablet ---------- */
@media (min-width: 701px) and (max-width: 1024px) {
  /* Auch hier mitwachsend: schmale Tablets ~230px, grosse bis 320px */
  /* Mittlere Bildschirme: schmalere Spalte - die Sprachleiste
   folgt automatisch, weil sie dieselbe Variable nutzt. */
:root { --sidebar-breite: clamp(230px, 30vw, 320px); }
#sidebar { width: var(--sidebar-breite); }
}

/* ---------- Handy ---------- */
@media (max-width: 700px) {
  /* (Die Schlüssel-Knöpfe stehen jetzt überall untereinander -
     die Sonderregel für schmale Schirme braucht es nicht mehr.) */

  /* Einstellungen am Handy: ganze Seite statt schwebender Kasten */
  #settings-modal { align-items: stretch; justify-content: stretch; padding: 0; }
  .settings-box {
    width: 100%;
    max-width: none;
    max-height: none;
    height: 100%;
    border-radius: 0;
    box-shadow: none;
    /* Kein Aufpopp-Effekt mehr: Eine ganze Seite schiebt sich herein,
       sie springt nicht auf. */
    animation: settings-herein 220ms ease;
    padding-bottom: env(safe-area-inset-bottom);
  }
  /* Die Kopfzeile bleibt oben stehen - der Schliessen-Knopf muss
     auch auf einer langen Seite immer erreichbar sein. */
  /* Schliessen und Zurueck sind die einzigen Wege aus einer
     bildschirmfuellenden Seite heraus - die muss man mit dem
     Daumen treffen. Gemessen waren es 40x28 (QR) und 42x38
     (Einstellungen). Die Flaeche waechst, das Symbol nicht.

     KEIN display hier! .settings-header button waere staerker
     als .hidden - der Zurueck-Pfeil (btn-settings-back) haengt
     genau daran und stuende sonst auf jeder Seite. Dieselbe
     Falle hatte schon #chat-header button. */
  .settings-header button {
    min-width: 44px;
    min-height: 44px;
  }
  /* Die Symbole sind display:block - text-align richtet daran
     nichts aus, ohne das haengen sie in der groesseren Flaeche
     links. Kein Knopf dort hat Text daneben (geprueft). */
  .settings-header button svg { margin-inline: auto; }

  .settings-header {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--panel);
    padding-top: calc(14px + env(safe-area-inset-top));
  }
  @keyframes settings-herein {
    from { transform: translateX(18px); opacity: 0; }
    to   { transform: none;             opacity: 1; }
  }

  /* Eine Spalte: Liste füllt den ganzen Bildschirm ... */
  #sidebar { width: 100%; border-right: none; }
  #chat-area { display: none; }

  /* ... bis ein Chat geöffnet wird - dann umgekehrt,
     mit weichem Einblenden (lt. Design-System: 180-250ms, kein Springen) */
  #chat-view.chat-open #sidebar { display: none; }
  #chat-view.chat-open #chat-area {
    display: flex;
    animation: chat-in 220ms ease;
  }
  /* Zurückgehen: der Chat schiebt sich nach rechts aus dem Bild,
     während die Liste dahinter wieder auftaucht. Die Klasse setzt
     app.js kurz, danach verschwindet der Chat wie gehabt. */
  #chat-view.chat-open.chat-raus #chat-area {
    animation: chat-raus 200ms cubic-bezier(0.4, 0, 0.7, 0.2) both;
  }
  #chat-view.chat-open.chat-raus #sidebar {
    display: flex;
    animation: liste-rein 220ms ease both;
  }
  @keyframes chat-raus {
    from { transform: translateX(0); opacity: 1; }
    to   { transform: translateX(100%); opacity: 0.6; }
  }
  @keyframes liste-rein {
    from { transform: translateX(-14%); opacity: 0.5; }
    to   { transform: translateX(0); opacity: 1; }
  }

  /* Bottom-Navigation einblenden (im offenen Chat ausgeblendet) */
  #bottom-nav {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    background: var(--panel);
    border-top: 1px solid var(--border);
    padding: 6px 0 calc(6px + env(safe-area-inset-bottom));
    z-index: 8;   /* über der Marktplatz-Ansicht (7) */
  }
  #chat-view.chat-open #bottom-nav { display: none; }
  .lists, #profile-pane { padding-bottom: 84px; }   /* nichts hinter der Leiste verstecken */

  /* Tab-Ansichten: was die Seitenleiste je Tab zeigt */
  #sidebar.mode-chats .add-contact { display: none; }
  #sidebar.mode-contacts .search-box { display: none; }
  #sidebar.mode-contacts .groups-title { display: none; }
  #sidebar.mode-contacts #group-list { display: none; }
  #sidebar.mode-profile .search-box,
  #sidebar.mode-profile .add-contact,
  #sidebar.mode-profile .lists { display: none; }
  #sidebar.mode-profile #profile-pane { display: flex; }

  /* Zurueck-Knopf einblenden. inline-flex, damit das Icon mittig
     sitzt - das kam vorher aus der Sammelregel fuer Icon-Knoepfe. */
  #btn-back {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
  }

  /* Deutlich einrücken: Nachrichten mit viel Luft zum Rand */
  #messages { padding: 22px 28px; }
  .msg { max-width: 84%; padding: 10px 15px; }
  #chat-header { padding: 14px 22px; }

  /* Eingabezeile: eingerückt, Senden-Pfeil weit weg von der Kante,
     und Platz für den iPhone-Home-Balken (safe-area).
     Kompakte Knöpfe, damit die Zeile sicher in jede Bildschirmbreite passt. */
  #send-form {
    /* Knapp halten: Bei offener Tastatur bleiben vom Bildschirm nur
       rund 500 px, und davon gingen 69 fuer ein 40-px-Feld drauf.
       Oben und unten je 5 statt 10 - der Home-Balken bekommt
       trotzdem seinen Platz. */
    padding: 5px 12px calc(5px + env(safe-area-inset-bottom));
  }

  /* Sicherheitsnetz: nichts darf die Seite horizontal aufdrücken */
  body { overflow-x: hidden; }

  /* Listen und Kopfzeile: gleiche Einrückung */
  #sidebar header { padding: 16px 22px; }
  .add-contact { padding: 12px 22px; }
  .section-title { padding: 12px 22px 4px; }
  #contact-list li, #group-list li { padding: 14px 22px; }

  input { font-size: 16px; }   /* verhindert Auto-Zoom beim iPhone */
}

/* ============================================================
   Glas-Ebenen (Milchglas über dem Chat)
   Kopfzeile und Composer SCHWEBEN über dem Verlauf - die
   Nachrichten scrollen sichtbar verwischt unter ihnen durch.
   Menüs, Dialoge, Datums-Trenner, Toast und Anruf-Fenster
   bekommen dasselbe Glas-Rezept. Steht bewusst am Datei-Ende,
   damit es die früheren festen Hintergründe überschreibt.
   ============================================================ */

/* Nachrichten füllen den ganzen Chat-Bereich; oben/unten Platz
   lassen, damit nichts dauerhaft unter den Glasleisten klebt */
#messages {
  position: absolute;
  inset: 0;
  padding: 78px 20px 88px;
}
/* Schiebt einen kurzen Verlauf nach unten ans Eingabefeld */
#messages::before {
  content: '';
  margin-top: auto;
}
#empty-state { position: absolute; inset: 0; }

/* Kopfzeile bleibt oben, alles Übrige (Leisten) rutscht nach unten */
#chat-header { margin-bottom: auto; }

/* Die Leisten liegen ÜBER den absolut positionierten Nachrichten */
#chat-header, #edit-bar, #reply-bar, #emoji-panel, #send-form {
  position: relative;
  z-index: 6;
}

/* Die Tipp-Blase gehört NICHT in die Zeile darüber: Sie ist ein Kind
   des Eingabe-Formulars. Mit "relative" würde sie zwar optisch nach
   oben rutschen, ihren Platz in der Zeile aber behalten - das
   Eingabefeld wurde dadurch zusammengedrückt, sobald jemand tippte.
   "absolute" nimmt sie aus der Zeile heraus. */
#typing-indicator {
  position: absolute;
  z-index: 6;
}

/* Dünnes Glas: Leisten und kleine schwebende Elemente */
#chat-header, #send-form, #typing-indicator, #edit-bar, #reply-bar,
#rec-lock, #toast, .date-divider {
  background: var(--glass-bg);
  backdrop-filter: blur(18px) saturate(1.25);
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
}

/* Dichtes Glas: Dialoge und Menüs (viel Inhalt -> mehr Deckung) */
#attach-menu, #profile-menu, #emoji-panel, #gif-panel,
#sticker-panel, .settings-box, .forward-box, .call-box, .share-contact-box {
  background: var(--glass-strong);
  backdrop-filter: blur(18px) saturate(1.25);
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
}

/* Toast war dunkel mit heller Schrift - auf Glas normale Textfarbe */
#toast { color: var(--text); }

/* Handy: seitlich mehr Luft, unten Platz für die Home-Geste */
@media (max-width: 700px) {
  #messages { padding: 78px 28px 96px; }
}

/* ============================================================
   Scrollleiste im Glas-Stil
   Schmaler Lavender-Griff, der über dem Inhalt schwebt -
   keine graue Systemleiste mehr. Gilt überall (Chat, Listen,
   Menüs, Einstellungen).
   ============================================================ */
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 8px;
  /* 2px unsichtbarer Rand: der Griff wirkt schmaler und "schwebt" */
  border: 2px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
  background-clip: padding-box;
}
::-webkit-scrollbar-corner { background: transparent; }

/* Firefox kennt die Regeln oben nicht - dort die Standard-Variante */
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: thin; scrollbar-color: var(--scrollbar-thumb) transparent; }
}

/* Die Scrollbahn im Chat endet an den Glasleisten: oben unter der
   Kopfzeile beginnen, unten vor dem Eingabefeld aufhören - der
   Griff läuft nicht mehr hinter den Leisten weiter. */
#messages::-webkit-scrollbar-track {
  margin-top: 65px;
  margin-bottom: 74px;
}

/* ============================================================
   Medien-Vollansicht (Lightbox) + Video-Vorschau + GIF-Galerie
   ============================================================ */

/* Abgedunkelter Glas-Hintergrund über der ganzen App */
#lightbox {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(22, 25, 36, 0.78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: flex;
  align-items: center;
  justify-content: center;
}
#lightbox.hidden { display: none; }
/* Aufgehen: der dunkle Grund blendet ein, das Medium wächst leicht
   heran - so kommt es "aus der Blase heraus" statt aufzublitzen. */
#lightbox:not(.hidden) { animation: lb-grund 180ms ease both; }
@keyframes lb-grund { from { opacity: 0; } to { opacity: 1; } }

#lightbox-content img, #lightbox-content video {
  max-width: 92vw;
  max-height: 88vh;
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  animation: lb-auf 220ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}
@keyframes lb-auf {
  from { opacity: 0; transform: scale(0.9); }
  to   { opacity: 1; transform: scale(1); }
}
/* Blättern: das neue Medium kommt aus der Richtung herein, in die
   gewischt wurde. Die Klasse setzt app.js beim Wechsel. */
#lightbox-content.rein-links img, #lightbox-content.rein-links video {
  animation: lb-rein-links 260ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}
#lightbox-content.rein-rechts img, #lightbox-content.rein-rechts video {
  animation: lb-rein-rechts 260ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}
@keyframes lb-rein-links {
  from { opacity: 0.2; transform: translateX(38%) scale(0.94); }
  to   { opacity: 1; transform: translateX(0) scale(1); }
}
@keyframes lb-rein-rechts {
  from { opacity: 0.2; transform: translateX(-38%) scale(0.94); }
  to   { opacity: 1; transform: translateX(0) scale(1); }
}
/* Während des Wischens nach unten folgt das Medium dem Finger -
   dann bitte KEINE Animation, sonst ruckelt es gegen die Geste. */
#lightbox.folgt #lightbox-content img,
#lightbox.folgt #lightbox-content video { animation: none; transition: none; }

/* Zugehen nach dem Wisch nach unten: fällt weich nach unten weg */
#lightbox.faellt { animation: lb-grund 200ms ease reverse both; }
#lightbox.faellt #lightbox-content img,
#lightbox.faellt #lightbox-content video {
  animation: lb-faellt 200ms ease both;
}
@keyframes lb-faellt {
  to { opacity: 0; transform: translateY(60vh) scale(0.8); }
}

/* Wer "Bewegung reduzieren" eingestellt hat, bekommt die Gesten
   ohne Schwung: alles passiert, nur ohne Flug und Federn. */
@media (prefers-reduced-motion: reduce) {
  #lightbox:not(.hidden),
  #lightbox-content img, #lightbox-content video,
  #lightbox-content.rein-links img, #lightbox-content.rein-links video,
  #lightbox-content.rein-rechts img, #lightbox-content.rein-rechts video,
  #lightbox.faellt, #lightbox.faellt #lightbox-content img,
  #lightbox.faellt #lightbox-content video { animation: none; }
  .msg.wisch-bereit::after { animation: none; }
  .msg.wisch-antwort::after, .msg.wisch-zurueck { transition: none; }
  .msg.gedrueckt { transition: none; }
  #chat-view.chat-open.chat-raus #chat-area,
  #chat-view.chat-open.chat-raus #sidebar { animation: none; }
}
#lightbox-close {
  position: absolute;
  /* Mit viewport-fit=cover reicht die Vollansicht bis in die Ecken.
     Ohne den Sicherheitsabstand saesse dieser Knopf auf dem iPhone
     unter der Notch - sichtbar, aber kaum zu treffen. */
  top: calc(16px + env(safe-area-inset-top));
  right: calc(16px + env(safe-area-inset-right));
  width: 44px; height: 44px;
  border-radius: 50%;
  border: none;
  background: var(--glass-strong);
  color: var(--text);
  display: flex; align-items: center; justify-content: center;
  z-index: 41;
}

/* Blättern in der Vollansicht: Pfeile links/rechts + Zähler unten.
   Am Handy wischt man - dort sind die Pfeile Beiwerk und kleiner. */
.lb-pfeil {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 46px; height: 46px;
  border-radius: 50%;
  border: none;
  background: var(--glass-strong);
  color: var(--text);
  display: flex; align-items: center; justify-content: center;
  z-index: 41;
  cursor: pointer;
}
.lb-pfeil.hidden, .lb-pfeil.zoom-aus { display: none; }
/* Gezoomtes Bild: kein Überstand-Beschnitt, damit man alles erreicht */
#lightbox-content img, #lightbox-content video { transform-origin: center; }
/* Quer gehalten liegen die abgerundeten Ecken seitlich. */
#lb-prev { left: calc(16px + env(safe-area-inset-left)); }
#lb-next { right: calc(16px + env(safe-area-inset-right)); }
#lb-next svg { transform: rotate(180deg); }   /* derselbe Pfeil, gespiegelt */
#lb-zaehler {
  position: absolute;
  /* Sonst liegt der Zaehler auf dem Home-Balken. */
  bottom: calc(18px + env(safe-area-inset-bottom)); left: 50%;
  transform: translateX(-50%);
  padding: 5px 12px;
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  z-index: 41;
}
#lb-zaehler.hidden { display: none; }
@media (max-width: 700px) {
  /* Am Handy zählt das Wischen - die Pfeile treten zurück */
  .lb-pfeil { width: 38px; height: 38px; opacity: 0.75; }
  #lb-prev { left: calc(6px + env(safe-area-inset-left)); }
  #lb-next { right: calc(6px + env(safe-area-inset-right)); }
}

/* Video-Vorschau in der Blase: Standbild + Play-Kreis */
.video-thumb {
  position: relative;
  cursor: pointer;
  display: inline-block;
  line-height: 0;   /* kein Geist-Abstand unter dem Video */
}
.video-thumb video { pointer-events: none; }
.video-play-overlay {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 48px; height: 48px;
  border-radius: 50%;
  background: rgba(22, 25, 36, 0.55);
  backdrop-filter: blur(6px);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
}

/* GIF-Galerie: schwebt über dem Composer (dichtes Glas, s. oben) */
#gif-panel {
  position: absolute;
  bottom: 80px;
  left: 12px; right: 12px;
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 10px;
  z-index: 15;
  box-shadow: 0 8px 28px rgba(22, 25, 36, 0.25);
}
#gif-panel.hidden { display: none; }
#gif-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 8px;
  color: var(--text-dim);
  font-size: 14px;
}
#gif-grid img {
  width: 100%;
  height: 100px;
  object-fit: cover;
  border-radius: 10px;
  cursor: pointer;
}
#gif-grid img:hover { outline: 2px solid var(--accent); }

/* ============================================================
   Fallback für Geräte OHNE Milchglas-Unterstützung
   (ältere Tablets/Browser ohne backdrop-filter): dort wären die
   Blasen fast unsichtbar und Zeitangaben schwer lesbar. Diese
   Geräte bekommen automatisch wieder feste Farben.
   ============================================================ */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .msg.mine   { background: #E9E2FF; }
  .msg.theirs { background: #FFFFFF; }
  :root[data-theme="dark"] .msg.mine,
  :root[data-theme="auto"].sys-dark .msg.mine,
  :root:not([data-theme]).sys-dark .msg.mine   { background: #3A3560; }
  :root[data-theme="dark"] .msg.theirs,
  :root[data-theme="auto"].sys-dark .msg.theirs,
  :root:not([data-theme]).sys-dark .msg.theirs { background: #25273A; }

  /* Leisten, Menüs und Dialoge: feste Panel-Farbe statt Glas */
  #chat-header, #send-form, #typing-indicator, #edit-bar, #reply-bar,
  #rec-lock, #toast, #attach-menu, #profile-menu,
  #emoji-panel, #gif-panel, #sticker-panel,
  .settings-box, .forward-box, .call-box, .share-contact-box {
    background: var(--panel);
  }
  .date-divider { background: var(--card); }
}

/* ============================================================
   GIF erstellen + Snapchat-Text auf Story-Fotos
   ============================================================ */

/* Kopfzeile der GIF-Galerie mit dem Erstellen-Knopf */
#gif-panel-head { display: flex; margin-bottom: 8px; }
#btn-gif-create {
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(126, 120, 184, 0.10);
  color: var(--accent);
  border: 1.5px solid var(--accent);
  border-radius: 10px;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
}
#btn-gif-create:hover { background: rgba(126, 120, 184, 0.18); }

/* "GIF" in der Sprechblase: Endlosschleife, wie ein Bild anklickbar */
.gif-loop {
  border-radius: 12px;
  cursor: pointer;
  max-width: 100%;
}

/* ============================================================
   Sticker (wie bei WhatsApp: Packs vom eigenen Server)
   ============================================================ */
#sticker-panel {
  position: absolute;
  bottom: 80px;
  left: 12px; right: 12px;
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 6px 0 10px;
  z-index: 15;
  box-shadow: 0 8px 28px rgba(22, 25, 36, 0.25);
}
#sticker-panel.hidden { display: none; }
#sticker-scroll { color: var(--text-dim); font-size: 14px; }
.sticker-section-title {
  font-size: 12px;
  font-weight: 700;
  color: var(--text-dim);
  padding: 10px 14px 4px;
  text-transform: capitalize;
}
.sticker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
  gap: 8px;
  padding: 4px 12px;
}
.sticker-grid img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  cursor: pointer;
  border-radius: 10px;
}
.sticker-grid img:hover { background: rgba(126, 120, 184, 0.14); }

/* Sticker in der Sprechblase: KEINE Blase - der Sticker schwebt
   frei über dem Muster (deshalb Glas, Rand und Schatten aus) */
.msg.sticker-msg {
  background: none;
  border: none;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  padding: 2px;
}
.sticker-img {
  width: 160px;
  max-width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  display: block;
}

/* ============================================================
   Einfügen aus der Zwischenablage: Vorschau vor dem Senden
   ============================================================ */
/* Vollbild-Editor wie bei WhatsApp: immer dunkel (wie die Lightbox),
   damit das Medium im Mittelpunkt steht - egal welches Theme läuft */
#paste-modal {
  position: fixed;
  inset: 0;
  background: rgba(16, 18, 27, 0.92);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  display: flex;
  flex-direction: column;
  align-items: center;
  z-index: 60;
  padding: 16px;
}
#paste-modal.hidden { display: none; }

/* X oben links (rund, wie der Lightbox-Schließer) */
#btn-paste-cancel {
  position: absolute;
  top: 16px; left: 16px;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  z-index: 61;
}
#btn-paste-cancel:hover { background: rgba(255, 255, 255, 0.20); }

/* Bühne: das große Bild/Video, nimmt allen freien Platz */
#paste-stage {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 40px 0 12px;
}
#paste-preview, #paste-preview-video {
  max-width: min(92vw, 720px);
  max-height: 100%;
  border-radius: 8px;
  object-fit: contain;
}
#paste-preview.hidden, #paste-preview-video.hidden { display: none; }

/* Kommentarzeile: breites Rundfeld + runder Senden-Knopf rechts */
#paste-compose {
  display: flex;
  align-items: center;
  gap: 12px;
  width: min(92vw, 640px);
  margin: 8px 0 14px;
}
#paste-caption {
  flex: 1;
  padding: 14px 18px;
  border-radius: 12px;
  border: none;
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  font-size: 15px;
}
#paste-caption::placeholder { color: rgba(255, 255, 255, 0.55); }
#paste-caption:focus { outline: 2px solid var(--accent); }
#btn-paste-send {
  width: 52px; height: 52px;
  flex-shrink: 0;
  border-radius: 50%;
  border: none;
  background: var(--accent);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 16px rgba(126, 120, 184, 0.45);
}
#btn-paste-send:hover { filter: brightness(1.1); }

/* Thumbnail-Leiste: alle gewählten Medien + die ＋-Kachel */
#paste-thumbs {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
  max-width: 92vw;
  padding-bottom: 6px;
}
.paste-thumb {
  position: relative;
  width: 56px; height: 56px;
  border-radius: 10px;
  border: 2px solid transparent;
  overflow: hidden;
  cursor: pointer;
  padding: 0;
  background: rgba(255, 255, 255, 0.06);
}
.paste-thumb img, .paste-thumb video {
  width: 100%; height: 100%;
  object-fit: cover;
  pointer-events: none;
}
.paste-thumb.active { border-color: var(--accent); }
/* kleines ✕ zum Entfernen einzelner Medien (erscheint beim Zeigen) */
.paste-thumb .thumb-remove {
  position: absolute;
  top: 2px; right: 2px;
  width: 18px; height: 18px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  font-size: 11px;
  line-height: 1;
  display: none;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.paste-thumb:hover .thumb-remove { display: flex; }
.paste-thumb-add {
  width: 56px; height: 56px;
  border-radius: 10px;
  border: 1.5px dashed rgba(255, 255, 255, 0.45);
  background: none;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.paste-thumb-add:hover { border-color: var(--accent); color: var(--accent); }

/* ---- Bild-Editor: Werkzeuge oben Mitte (wie bei WhatsApp) ---- */
#edit-toolbar {
  position: absolute;
  top: 16px; left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
  z-index: 61;
}
#edit-toolbar.hidden { display: none; }

/* Am Handy passt die Leiste nicht mittig neben das X.
   Sieben Knöpfe zu 44 px sind mit Abständen 368 breit - auf einem
   375-px-Bildschirm beginnt die zentrierte Leiste damit bei 4 px und
   liegt auf dem Schließen-Knopf bei 16. Deshalb hier: Sie fängt
   NEBEN ihm an, nutzt den Rest der Breite und rollt seitlich, falls
   das Gerät noch schmaler ist. Nach unten ausweichen geht nicht -
   dort sitzen schon die Farben und die Emoji-Auswahl (68 px). */
@media (max-width: 700px) {
  #edit-toolbar {
    left: 68px; right: 12px;
    transform: none;
    justify-content: space-between;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: none;
  }
  #edit-toolbar::-webkit-scrollbar { display: none; }
  #edit-toolbar button { width: 38px; height: 38px; flex-shrink: 0; }
}
#edit-toolbar button {
  width: 44px; height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
#edit-toolbar button:hover { background: rgba(255, 255, 255, 0.20); }
#edit-toolbar button.active { background: var(--accent); }

/* Farbpalette: klappt unter der Werkzeugleiste auf */
#pen-colors {
  position: absolute;
  top: 68px; left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 22px;
  background: rgba(0, 0, 0, 0.45);
  z-index: 61;
}
#pen-colors.hidden { display: none; }
.pen-color {
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.6);
  cursor: pointer;
  padding: 0;
}
.pen-color.active { border-color: #fff; transform: scale(1.2); }

/* Die durchsichtige Leinwand liegt exakt über dem Bild */
#stage-wrap {
  position: relative;
  display: flex;
  max-width: min(92vw, 720px);
  max-height: 100%;
}
#stage-wrap.hidden { display: none; }
#edit-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 8px;
  touch-action: none;   /* Finger malt, statt zu scrollen */
}
#edit-canvas.drawing { cursor: crosshair; }

/* Emoji-Schnellauswahl im Editor (unter der Werkzeugleiste) */
#emoji-quick {
  position: absolute;
  top: 68px; left: 50%;
  transform: translateX(-50%);
  display: grid;
  grid-template-columns: repeat(10, 34px);
  gap: 4px;
  padding: 10px;
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.55);
  z-index: 61;
}
#emoji-quick.hidden { display: none; }
#emoji-quick button {
  width: 34px; height: 34px;
  border: none;
  background: none;
  font-size: 22px;
  cursor: pointer;
  border-radius: 8px;
}
#emoji-quick button:hover { background: rgba(255, 255, 255, 0.15); }

/* Zuschneide-Rahmen: heller Rand, abgedunkelter Rest, Eck-Griffe */
#crop-box {
  position: absolute;
  border: 2px solid #fff;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.55);
  cursor: move;
  touch-action: none;
}
#crop-box.hidden { display: none; }
.crop-grip {
  position: absolute;
  width: 18px; height: 18px;
  background: #fff;
  border-radius: 50%;
  touch-action: none;
}
.crop-grip[data-corner="nw"] { top: -9px; left: -9px; cursor: nwse-resize; }
.crop-grip[data-corner="ne"] { top: -9px; right: -9px; cursor: nesw-resize; }
.crop-grip[data-corner="sw"] { bottom: -9px; left: -9px; cursor: nesw-resize; }
.crop-grip[data-corner="se"] { bottom: -9px; right: -9px; cursor: nwse-resize; }

/* Übernehmen/Verwerfen im Zuschneide-Modus */
#crop-actions {
  display: flex;
  gap: 12px;
  margin: 8px 0 2px;
}
#crop-actions.hidden { display: none; }
#crop-actions button {
  width: 48px; height: 48px;
  border-radius: 50%;
  border: none;
  color: #fff;
  display: flex; align-items: center; justify-content: center;
}
#btn-crop-apply { background: var(--accent); }
#btn-crop-cancel { background: rgba(255, 255, 255, 0.12); }

/* ⏱1-Knopf (Einmalansicht) in der Kommentarzeile */
#btn-once {
  width: 44px; height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.55);
  background: none;
  color: #fff;
  font-size: 15px;
  font-weight: 800;
}
#btn-once.hidden { display: none; }
#btn-once.active {
  background: var(--accent);
  border-color: var(--accent);
}

/* Einmalansicht in der Sprechblase: Kachel statt Bild */
.once-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
  min-width: 170px;
  cursor: pointer;
}
.once-card .once-ring {
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800;
  color: var(--accent);
  flex-shrink: 0;
}
.once-card .once-label { font-weight: 600; font-size: 14px; }
.once-card .once-sub { font-size: 12px; opacity: 0.7; }
.once-card.opened { cursor: default; opacity: 0.65; }
.once-card.opened .once-ring { border-style: dashed; }

/* ---- Kamera ---- */
#camera-modal {
  position: fixed;
  inset: 0;
  background: rgba(16, 18, 27, 0.96);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 62;
}
#camera-modal.hidden { display: none; }
#camera-live {
  max-width: 94vw;
  max-height: 78vh;
  border-radius: 12px;
}
#btn-camera-close {
  position: absolute;
  top: 16px; left: 16px;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
}
/* Der Auslöser: großer weißer Ring unten in der Mitte */
#btn-camera-shot {
  position: absolute;
  bottom: 26px; left: 50%;
  transform: translateX(-50%);
  width: 64px; height: 64px;
  border-radius: 50%;
  border: 5px solid #fff;
  background: rgba(255, 255, 255, 0.25);
}
#btn-camera-shot:hover { background: rgba(255, 255, 255, 0.45); }

/* ---- Datei-Nachricht (Dokument): Kachel mit Name + Größe ---- */
.file-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
  cursor: pointer;
  min-width: 180px;
}
.file-card .file-ico { font-size: 26px; }
.file-card .file-name {
  font-weight: 600;
  word-break: break-all;
  font-size: 14px;
}
.file-card .file-size { font-size: 12px; opacity: 0.7; }

/* ---- Kontakt-Karte in der Sprechblase ---- */
.contact-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 2px;
  min-width: 200px;
}
.contact-card .cc-name { font-weight: 700; font-size: 14px; }
.contact-card .cc-handle { font-size: 12px; opacity: 0.7; }
.contact-card .cc-add {
  margin-left: auto;
  padding: 7px 12px;
  border-radius: 10px;
  border: 1.5px solid var(--accent);
  background: none;
  color: var(--accent);
  font-size: 12px;
  font-weight: 700;
}
.contact-card .cc-add:hover { background: rgba(126, 120, 184, 0.12); }

/* ---- Kontakt-teilen-Dialog ---- */
#share-contact-modal {
  position: fixed;
  inset: 0;
  background: rgba(22, 25, 36, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 60;
}
#share-contact-modal.hidden { display: none; }
.share-contact-box {
  width: min(340px, 90vw);
  max-height: 60vh;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 14px;
}
#share-contact-title { font-weight: 700; margin-bottom: 10px; }
#share-contact-list { list-style: none; margin: 0; padding: 0; }
#share-contact-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 6px;
  border-radius: 10px;
  cursor: pointer;
}
#share-contact-list li:hover { background: rgba(126, 120, 184, 0.12); }

/* Der Snapchat-Text: halbtransparentes Band über dem Foto.
   Im Composer verschiebbar (Ziehen), im Viewer fest positioniert. */
#composer-preview { position: relative; }
.story-media-wrap {
  position: relative;
  display: flex;
  max-width: 100%; max-height: 100%;
}
.story-media-wrap img { max-width: 100%; max-height: 100%; object-fit: contain; }
.story-overlay {
  position: absolute;
  left: 0; right: 0;
  transform: translateY(-50%);
  text-align: center;
  color: #fff;
  background: rgba(0, 0, 0, 0.45);
  padding: 8px 14px;
  font-size: 18px;
  line-height: 1.35;
  word-wrap: break-word;
  outline: none;
  z-index: 2;
}
#story-overlay-edit {
  cursor: grab;
  touch-action: none;   /* Ziehen ist Verschieben, kein Scrollen */
  min-height: 22px;
}
#story-overlay-edit:empty::before { content: attr(data-ph); opacity: 0.7; }

/* ============================================================
   Gruppeninfo (Klick auf den Gruppennamen)
   ============================================================ */
#group-info-modal {
  position: fixed; inset: 0;
  background: rgba(22, 25, 36, 0.55);
  display: flex; align-items: center; justify-content: center;
  z-index: var(--z-dialog);   /* ueber den schwebenden Fenstern */
}
#group-info-modal.hidden { display: none; }
/* Der Gruppenname im Kopf ist der einzige Fenstertitel der App,
   der von jemandem eingegeben wurde - alle anderen sind uebersetzte
   Beschriftungen. Er wuchs deshalb ungebremst: ein langer Name
   schob den Kopf auf drei Zeilen, ein einzelnes langes Wort lief
   sogar seitlich aus dem Fenster (gemessen 631 Pixel in einem 375
   Pixel breiten Fenster).

   Zwei Zeilen, dann Punkte: Ein Titel darf umbrechen - er ist die
   Ueberschrift des Fensters, keine Listenzeile. Aber irgendwo muss
   Schluss sein. Der volle Name steht im Tooltip. */
#gi-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;   /* auch ein Wort ohne Leerzeichen bricht */
  min-width: 0;
}
#gi-meta { padding: 2px 16px 8px; color: var(--text-dim); font-size: 13px; }
#gi-members { list-style: none; padding: 4px 8px 14px; }
#gi-members li {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  border-radius: 10px;
}
#gi-members li:hover { background: var(--hover); }
#gi-members .avatar {
  width: 36px; height: 36px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
#gi-members .avatar.fallback {
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 14px;
}
/* Nur der Name kuerzt, das Rang-Zeichen daneben bleibt stehen.
   Vorher brachen lange Namen um und die Zeilen der Liste wurden
   unterschiedlich hoch (nachgemessen 52 und 56 Pixel). */
#gi-members .gi-name {
  flex: 1;
  min-width: 0;              /* sonst darf der Name nicht schrumpfen */
  font-size: 15px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gi-admin {
  flex-shrink: 0;            /* der Rang gehoert zur Zeile, nicht der Name allein */
  background: rgba(126, 120, 184, 0.15);
  color: var(--accent);
  font-size: 11px; font-weight: 700;
  padding: 3px 8px;
  border-radius: 8px;
}

/* Gruppenname im Kopf: zeigt an, dass man ihn anklicken kann */
#chat-title.clickable { cursor: pointer; }
#chat-title.clickable:hover { color: var(--accent); }

/* ============================================================
   Freundschaftsanfragen in der Seitenleiste
   ============================================================ */
#request-list { list-style: none; }
#request-list li {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
}
#request-list .avatar {
  width: 36px; height: 36px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
#request-list .avatar.fallback {
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 14px;
}
/* Name oben, @handle darunter - der Block traegt die Breite. */
#request-list .fr-text { flex: 1 1 auto; min-width: 0; }
#request-list .fr-name {
  display: block;
  font-size: 14px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#request-list .handle-tag {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fr-accept, .fr-decline, .fr-block {
  width: 32px; height: 32px;
  border-radius: 50%;
  border: none;
  flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.fr-accept  { background: var(--accent);  color: #fff; }
.fr-accept:hover { background: var(--accent-hover); }
.fr-decline { background: var(--hover); color: var(--text-dim); }
.fr-decline:hover { background: rgba(217, 120, 120, 0.15); color: var(--danger); }
/* Blockieren steht neben Annehmen und Ablehnen, traegt aber die
   Warnfarbe: Es wirkt ueber diese eine Anfrage hinaus. */
.fr-block { background: var(--hover); color: var(--danger); }
.fr-block:hover { background: rgba(217, 120, 120, 0.28); }

/* ============================================================
   Gruppen-Verwaltung: Pin-Leiste, Gruppenbild, Beschreibung
   ============================================================ */

/* Angepinnte Nachricht: schwebt als Glas-Leiste direkt unter der
   Kopfzeile (absolut positioniert, wegen des Glas-Layouts) */
#pinned-bar {
  position: absolute;
  top: 65px; left: 0; right: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  border-bottom: 1px solid var(--border);
  background: var(--glass-bg);
  backdrop-filter: blur(18px) saturate(1.25);
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
  z-index: 6;
}
#pinned-bar.hidden { display: none; }
#pinned-ico { color: var(--accent); display: flex; flex-shrink: 0; }
#pinned-text {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#btn-unpin { flex-shrink: 0; }

/* Gruppenbild im Info-Fenster */
#gi-avatar-row { display: flex; justify-content: center; padding: 10px 0 4px; }
.gi-group-avatar {
  width: 84px; height: 84px;
  border-radius: 50%;
  object-fit: cover;
}
.gi-group-avatar.fallback {
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-weight: 700; font-size: 32px;
}
.gi-group-avatar.clickable { cursor: pointer; }
.gi-group-avatar.clickable:hover { opacity: 0.85; }
#gi-meta { text-align: center; }

/* Beschreibung */
#gi-desc {
  padding: 6px 16px 10px;
  font-size: 14px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}
#gi-desc.gi-desc-empty { color: var(--text-dim); font-style: italic; cursor: pointer; }
#gi-desc:not(.gi-desc-empty) { color: var(--text); }
#gi-desc.hidden { display: none; }

/* Zum-Admin-machen-Knopf in der Mitgliederliste */
.gi-promote {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1.5px solid var(--accent);
  background: transparent;
  color: var(--accent);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.gi-promote:hover { background: rgba(126, 120, 184, 0.12); }
/* Geht nicht, ist aber da: Der Knopf sagt beim Antippen, warum -
   das ist ehrlicher als ein Knopf, der einfach fehlt. Blass genug,
   damit man den Unterschied vorher sieht. */
.gi-promote.gesperrt { border-color: var(--border); color: var(--text-dim); opacity: 0.55; }
.gi-promote.gesperrt:hover { background: transparent; }

/* 🔕 hinter dem Namen stummgeschalteter Chats */
.mute-mark {
  display: inline-flex;
  margin-left: 5px;
  color: var(--text-dim);
  vertical-align: middle;
  opacity: 0.8;
}

/* ============================================================
   QR-Einladung
   ============================================================ */
#qr-modal {
  position: fixed; inset: 0;
  background: rgba(22, 25, 36, 0.55);
  display: flex; align-items: center; justify-content: center;
  /* Dialoge gehoeren ueber die schwebenden Fenster. Vorher lagen sie
     bei 30 und damit UNTER Popout (40) und Stream-Fenster (60) - der
     QR-Code liess sich von einem Fenster verdecken. */
  z-index: var(--z-dialog);
}
#qr-modal.hidden { display: none; }

/* (Hier standen die Stilregeln der alten Gerätekopplung: Fenster,
   sechsstelliger Code, Abtipp-Login. Alles entfernt, als der
   Anmelde-QR sie abgelöst hat.) */
/* Weißer Rahmen ums Muster: Scanner brauchen die "Ruhezone" */
#qr-code-box {
  display: flex; justify-content: center;
  padding: 14px 0 6px;
}

/* Einladung als Link weitergeben - im QR-Fenster und im
   Kontakt-Fenster derselbe Knopf. */
#btn-qr-teilen, #btn-ac-teilen {
  display: block;
  margin: 10px auto 4px;
  padding: 9px 18px;
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
#btn-qr-teilen:hover, #btn-ac-teilen:hover { filter: brightness(1.08); }

/* "Oder lass dich finden" im Kontakt-Fenster: die Antwort fuer den,
   der niemanden zu suchen weiss. Kleiner als das grosse QR-Fenster -
   es ist ein Angebot am Rand, kein Hauptdarsteller. */
#ac-finden {
  border-top: 1px solid var(--border);
  margin-top: 14px;
  padding-top: 12px;
  text-align: center;
}
#ac-finden-titel {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-dim);
}
#ac-finden-qr { display: flex; justify-content: center; padding: 10px 0 2px; }
#ac-finden-qr svg {
  background: #fff;
  border-radius: 10px;
  width: 132px; height: 132px;
}
#ac-finden-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--accent);
  padding: 2px 0;
}
#qr-code-box svg {
  background: #fff;
  border-radius: 14px;
  width: 220px; height: 220px;
}
#qr-name {
  text-align: center;
  font-size: 17px;
  font-weight: 700;
  color: var(--accent);
  padding: 4px 0;
}
#qr-hint {
  text-align: center;
  font-size: 13px;
  color: var(--text-dim);
  line-height: 1.5;
  padding: 2px 20px 18px;
}

/* ============================================================
   Kontakt-hinzufügen-Fenster (öffnet über das + neben KONTAKTE)
   ============================================================ */
#add-contact-modal {
  position: fixed; inset: 0;
  background: rgba(22, 25, 36, 0.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 30;
}
#add-contact-modal.hidden { display: none; }
#ac-search-row { padding: 12px 16px 8px; }
#ac-search-row input { width: 100%; }
#ac-results {
  padding: 0 8px 14px;
  min-height: 60px;
  max-height: 320px;
  overflow-y: auto;
  color: var(--text-dim);
  font-size: 14px;
  text-align: center;
}
#ac-results .suggest-row { text-align: left; border-radius: 10px; }

/* Gründer-Chip, Entfernen-Knopf und Gruppe-verlassen */
.gi-admin.gi-owner {
  background: var(--accent);
  color: #fff;
}
.gi-kick {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1.5px solid var(--danger);
  background: rgba(217, 120, 120, 0.12);
  color: var(--danger);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.gi-kick:hover { background: var(--danger); color: #fff; }
#btn-gi-leave {
  display: block;
  width: calc(100% - 32px);
  margin: 2px 16px 16px;
  padding: 11px;
  border: none;
  border-radius: 12px;
  background: rgba(217, 120, 120, 0.12);
  color: var(--danger);
  font-size: 14px;
  font-weight: 600;
}
#btn-gi-leave:hover { background: rgba(217, 120, 120, 0.22); }

/* Runde Icon-Knöpfe: das globale Button-Padding (10px 16px) würde
   das Icon auf 0px zusammenquetschen - deshalb hier ausdrücklich 0 */
.fr-accept, .fr-decline, .fr-block, .gi-promote, .gi-kick { padding: 0; }

/* ============================================================
   Zwei-Faktor-Anmeldung
   ============================================================ */
#twofa-card { padding: 4px 16px 14px; }
#twofa-status { font-size: 14px; color: var(--text-dim); line-height: 1.5; margin-bottom: 12px; }
#btn-twofa { width: 100%; }

#twofa-modal {
  position: fixed; inset: 0;
  background: rgba(22, 25, 36, 0.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 30;
}
#twofa-modal.hidden { display: none; }
#tf-scan-hint, #tf-backup-hint {
  font-size: 13px; color: var(--text-dim); line-height: 1.5;
  padding: 8px 16px 4px;
}
#tf-qr { display: flex; justify-content: center; padding: 8px 0 4px; }
#tf-qr svg { background: #fff; border-radius: 12px; width: 200px; height: 200px; }
/* Das Geheimnis als Text - falls die Kamera nicht will, kann man
   es in der App auch von Hand eintippen */
#tf-secret {
  text-align: center;
  font-family: monospace;
  font-size: 11px;
  color: var(--text-dim);
  word-break: break-all;
  padding: 2px 20px 8px;
  user-select: all;
}
#tf-code-row { display: flex; gap: 8px; padding: 4px 16px 16px; }
#tf-code-row input {
  flex: 1; min-width: 0;
  text-align: center;
  font-size: 20px;
  letter-spacing: 6px;
  font-variant-numeric: tabular-nums;
}
#tf-step-scan.hidden, #tf-step-backup.hidden { display: none; }
#tf-backup-codes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  padding: 8px 20px 18px;
  font-family: monospace;
  font-size: 15px;
  text-align: center;
  user-select: all;
}
#tf-backup-codes div {
  background: var(--hover);
  border-radius: 8px;
  padding: 7px 4px;
}

/* ============================================================
   Login/Registrieren getrennt + 2FA-Feld + neue Settings-Karten
   ============================================================ */

/* Der Text-Link unter den Auth-Knöpfen ("Neu hier? ...") */
.auth-link {
  background: transparent;
  border: none;
  color: var(--accent);
  font-size: 14px;
  padding: 4px;
  align-self: center;
}
.auth-link:hover { text-decoration: underline; }

/* 2FA beim Login: dezenter Hinweis + großes Code-Feld */
#login-2fa { display: flex; flex-direction: column; gap: 8px; }
#login-2fa.hidden { display: none; }
#login-2fa-hint { font-size: 13px; color: var(--text-dim); line-height: 1.5; }
#login-code {
  text-align: center;
  font-size: 20px;
  letter-spacing: 6px;
  font-variant-numeric: tabular-nums;
}

/* Registrieren: Hinweis unterm Anmeldenamen */
#reg-hint { font-size: 12px; color: var(--text-dim); line-height: 1.5; margin-top: -6px; }

/* Passwort-ändern-Karte */
#pw-card {
  padding: 4px 16px 14px;
  display: flex; flex-direction: column; gap: 8px;
}

/* Benachrichtigungs-Schalter */
/* Der geteilte Bildschirm eines anderen: schwebendes Fenster unten
   rechts. Bewusst KEIN Vollflaechen-Overlay - man will nebenher
   weiterschreiben koennen. Vollbild gibt es per Knopf/Doppelklick. */
#bildschirm-panel {
  position: fixed;
  right: 18px; bottom: 74px;      /* ueber der Sprachleiste */
  width: min(460px, calc(100vw - 36px));
  z-index: var(--z-popout);
  background: var(--panel);
  /* Gleiche Anmutung wie Fabians Chat-Popout: 1px Rand, derselbe
     Schatten. Vorher 1.5px und ein anderer Schatten - zwei
     schwebende Fenster nebeneinander sahen aus wie aus zwei Apps. */
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.42);
}
#bildschirm-kopf {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px;
}
#bildschirm-name {
  flex: 1;
  font-size: 13px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* ============================================================
   Sprachkanal-Buehne (Discord-Ansicht): grosse Kacheln aller
   Teilnehmer ueber dem Chatbereich. Gruener Rand = spricht gerade
   (geschaltet von zeigeWerRedet ueber die Klasse voice-member).
   ============================================================ */
#sprach-buehne {
  position: absolute; inset: 0;
  z-index: var(--z-buehne);        /* ueber Nachrichten, unter Dialogen */
  display: flex; flex-direction: column;
  background: var(--buehne-bg);    /* dunkler als der Chat, wie bei Discord */
}
#buehne-kopf {
  display: flex; align-items: center; gap: 8px;
  padding: 14px 20px 10px;
  font-weight: 700; font-size: 15px;
}
/* Mitgliederlisten-Schalter rechts aussen, wie bei Discord */
#bu-members {
  margin-left: auto;
  width: 36px; height: 36px;
  border-radius: 50%;
  border: none;
  background: var(--knopf-bg); color: var(--knopf-text);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
#bu-members:hover { background: var(--knopf-hover); }
#bu-members.hidden { display: none; }
#buehne-titel { display: flex; align-items: center; gap: 8px; }
#buehne-kacheln {
  flex: 1;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
  padding: 4px 20px 12px;
  align-content: center;           /* wenige Kacheln schweben mittig */
}
.buehne-kachel {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--buehne-kachel);
  border-radius: 12px;
  border: 3px solid transparent;
  display: flex; align-items: center; justify-content: center;
  transition: border-color 0.12s;
}
/* Discord-Gruen fuer "spricht gerade" */
.buehne-kachel.redet { border-color: #23a55a; }
/* Leitung abgerissen, Gnadenfrist laeuft: ausgegraut, nicht weg */
.buehne-kachel.getrennt { opacity: 0.45; }
.bu-getrennt {
  position: absolute; top: 10px; right: 10px;
  background: rgba(0, 0, 0, 0.55);
  padding: 3px 8px; border-radius: 7px;
  font-size: 11px; font-weight: 600;
}
#channel-list .voice-member.getrennt { opacity: 0.45; }

/* Rotes Ungelesen-Abzeichen am Chat-Symbol in der Leiste links -
   wie bei Discord. Haengt an der Ecke des Knopfes; der braucht dafuer
   einen Anker (position: relative kommt von .rail-btn selbst oder
   hier zur Sicherheit). */
#rail-chats { position: relative; }
.rail-abzeichen {
  position: absolute;
  top: -3px; right: -5px;
  min-width: 17px; height: 17px;
  padding: 0 4px;
  border-radius: 9px;
  background: #e5484d;
  color: #fff;
  font-size: 10px; font-weight: 800;
  line-height: 17px;
  text-align: center;
  /* Dunkler Rand, damit es sich vom Knopf abhebt wie bei Discord */
  box-shadow: 0 0 0 2.5px var(--bg, #15121F);
  pointer-events: none;      /* Klick geht weiter an den Knopf */
}

/* "Sitzt im Sprachkanal" am Kontakt in der Chatliste - gruen wie
   alles Lebendige im Sprachbereich, klickbar zum Direkteinstieg */
.voice-hinweis {
  display: inline-flex; align-items: center; gap: 4px;
  margin-left: 8px;
  padding: 2px 8px;
  border: none; border-radius: 8px;
  background: rgba(35, 165, 90, 0.16);
  color: #23a55a;
  font: inherit; font-size: 11px; font-weight: 700;
  cursor: pointer;
  max-width: 170px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.voice-hinweis:hover { background: rgba(35, 165, 90, 0.3); }
.voice-hinweis svg { flex-shrink: 0; }
/* Mit der Kachel-Id davor: Die Kacheln tragen auch die Klasse
   voice-member (fuer den gruenen Sprechring), und deren Winz-Avatar
   (.voice-member .avatar, 21px - fuer die Kanalliste gedacht) steht
   SPAETER in der Datei und gewann sonst den Gleichstand. Genau so
   gefunden: Die Bilder blieben trotz aller Regeln bei 21px. */
#buehne-kacheln .buehne-kachel .avatar {
  width: 96px; height: 96px;
  min-width: 0;
  border-radius: 50%;
  font-size: 38px;
  display: flex; align-items: center; justify-content: center;
}
/* Mitwachsend, wo der Browser Container-Einheiten kann (Chromium
   ueberall bei uns): 42 % der Kachelhoehe, gedeckelt. Prozente gehen
   NICHT - gegen eine aspect-ratio-Hoehe loesen sie sich nicht auf. */
.buehne-kachel { container-type: size; }
@supports (height: 42cqh) {
  #buehne-kacheln .buehne-kachel .avatar {
    width: 42cqh; height: 42cqh;
    max-width: 150px; max-height: 150px;
    font-size: clamp(28px, 16cqh, 60px);
  }
}
.bu-name {
  position: absolute; left: 10px; bottom: 9px;
  display: flex; align-items: center; gap: 5px;
  background: rgba(0, 0, 0, 0.55);
  padding: 3px 9px;
  border-radius: 7px;
  font-size: 12.5px; font-weight: 600;
  max-width: calc(100% - 20px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bu-live { position: absolute; top: 10px; left: 10px; }
.bu-watch {
  position: absolute; right: 10px; bottom: 9px;
  display: flex; align-items: center; gap: 6px;
  background: #e5484d; color: #fff;
  border: none; border-radius: 8px;
  padding: 6px 11px;
  font: inherit; font-size: 12px; font-weight: 700;
  cursor: pointer;
}
.bu-watch:hover { filter: brightness(1.15); }
/* ---- Fokus-Modus: ein Stream gross, der Rest als schmale Leiste ---- */
#buehne-kacheln.fokus-modus {
  display: flex; flex-direction: column;
  align-content: stretch;
  gap: 12px;
}
.buehne-kachel.fokussiert {
  flex: 1; min-height: 0;
  aspect-ratio: auto;
  background: #000;
  overflow: hidden;
}
#buehne-video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;      /* Balken statt Beschnitt */
  background: #000;
}
#buehne-strip {
  flex: 0 0 96px;
  display: flex; justify-content: center; gap: 10px;
  min-height: 96px;
}
#buehne-strip .buehne-kachel {
  width: 170px; height: 96px;
  aspect-ratio: auto;
  flex: 0 0 auto;
}
#buehne-strip .buehne-kachel .avatar { width: 40px; height: 40px; min-width: 0; font-size: 17px; }
#buehne-strip .bu-name { font-size: 11px; padding: 2px 7px; left: 7px; bottom: 6px; }
#buehne-strip .bu-watch { padding: 4px 8px; font-size: 11px; right: 7px; bottom: 6px; }
#buehne-strip .bu-watch span { display: none; }   /* nur das Symbol - zu eng */

/* Steuerleiste auf dem Stream: erscheint beim Drueberfahren */
#buehne-video-steuer {
  position: absolute; right: 12px; bottom: 12px;
  display: flex; align-items: center; gap: 8px;
  background: rgba(0, 0, 0, 0.65);
  padding: 7px 10px;
  border-radius: 10px;
  opacity: 0;
  transition: opacity 0.15s;
  z-index: 2;
}
.buehne-kachel.fokussiert:hover #buehne-video-steuer,
#buehne-video-steuer:focus-within { opacity: 1; }
#buehne-video-steuer.hidden { display: none; }
#bv-ton { width: 80px; accent-color: var(--accent); }
#bv-ton-zeichen { display: flex; align-items: center; opacity: 0.75; }
#buehne-video-steuer .small {
  background: transparent; border: none; color: #fff;
  cursor: pointer; display: flex; align-items: center;
  padding: 4px; border-radius: 6px;
}
#buehne-video-steuer .small:hover { background: rgba(255, 255, 255, 0.15); }
/* Im Vollbild zeigt der Browser das Video allein - die Steuerleiste
   haengt an der Kachel und ist dort nicht zu sehen. Doppelklick oder
   Esc fuehren wieder heraus. */

/* Die Knopfleiste unten: runde Knoepfe wie bei Discord */
#buehne-leiste {
  display: flex; justify-content: center; gap: 14px;
  padding: 14px 0 20px;
}
.bu-knopf {
  width: 48px; height: 48px;
  border-radius: 50%;
  border: none;
  background: var(--knopf-bg); color: var(--knopf-text);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: background 0.12s;
}
.bu-knopf:hover { background: var(--knopf-hover); }
.bu-knopf.an-aus { background: #e5484d; }   /* stumm/taub/live = rot */
.bu-knopf.rot { background: #e5484d; }
.bu-knopf.rot:hover { filter: brightness(1.15); }

/* Rotes LIVE-Abzeichen wie bei Discord: neben dem Namen dessen, der
   den Bildschirm teilt, und in der eigenen Sprachleiste. Rot mit
   Absicht - es soll auffallen, denn der eigene Bildschirm ist gerade
   fuer andere sichtbar. */
.live-abzeichen {
  background: #e5484d;
  color: #fff;
  font-size: 9.5px; font-weight: 800;
  letter-spacing: 0.05em; line-height: 1.3;
  padding: 1.5px 5.5px;
  border-radius: 4px;
  flex-shrink: 0;
  user-select: none;
}
/* Nur bei den ANDEREN ist das Abzeichen der Weg zum Zuschauen -
   das eigene ist reine Anzeige. */
.live-abzeichen.klickbar { cursor: pointer; }
.live-abzeichen.klickbar:hover { filter: brightness(1.15); }
/* Der Teilen-Knopf selbst wird rot, solange die Uebertragung laeuft -
   derselbe Gedanke: nicht vergessen lassen, dass man live ist. */
#btn-voice-screen.active-on {
  background: #e5484d;
  border-color: #e5484d;
  color: #fff;
}

/* Tonregler der Uebertragung: klein, startet links (stumm) */
#bildschirm-ton-zeichen { display: flex; align-items: center; opacity: 0.7; }
#bildschirm-ton {
  width: 74px;
  accent-color: var(--accent);
}
/* Ein Klick holt die grosse Ansicht zurueck (siehe app.js) - der
   Zeiger sagt es. */
#bildschirm-video {
  cursor: pointer;
  display: block;
  width: 100%;
  /* 16:9 als Rahmen; anderes Seitenverhaeltnis bekommt Balken statt
     das Panel beliebig hoch zu ziehen */
  aspect-ratio: 16 / 9;
  background: #000;
  object-fit: contain;
}

/* Einstellungen -> Ton: Mikrofon und Wiedergabe waehlen.
   Gehoert hierher und nicht in die Sprachleiste - dort stand sonst
   ein zweites, gleich aussehendes Mikrofon-Symbol neben dem
   Stummschalter, und eng ist die Leiste ohnehin. */
#ton-card { padding: 4px 16px 16px; }
#ton-card select {
  width: 100%;
  padding: 11px 12px;
  border-radius: 11px;
  border: 1.5px solid var(--border);
  background: var(--hover);
  color: var(--text);
  font: inherit; font-size: 14px;
}
#ton-card select:focus { outline: none; border-color: var(--accent); }

/* Pegelbalken: zeigt sofort, ob das gewaehlte Mikrofon etwas hoert.
   Ohne das merkt man erst im Gespraech, dass man stumm ist. */
#ton-pegel-zeile {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 2px 4px;
}
#ton-pegel-text { font-size: 12px; color: var(--text-dim); white-space: nowrap; }
#ton-pegel-bahn {
  flex: 1; height: 8px; border-radius: 4px;
  background: rgba(255, 255, 255, 0.09);
  overflow: hidden;
}
#ton-pegel-fuellung {
  height: 100%; width: 0%;
  border-radius: 4px;
  background: linear-gradient(90deg, var(--accent), #4ade80);
  /* Kurz, aber nicht ruckartig: Sprache springt schnell. */
  transition: width 90ms linear;
}
.settings-hinweis {
  font-size: 12px; color: var(--text-dim);
  margin: 12px 2px 0; line-height: 1.5;
}

#notif-card { padding: 4px 16px 14px; }
/* Alle drei Zeilen, nicht nur die erste. Und die ganze Zeile ist
   die Tippflaeche: Sie sind <label>, der Fingerdruck irgendwo
   darauf schaltet das Kaestchen. */
#notif-req-row, #notif-acc-row, #notif-msg-row {
  display: flex; align-items: center; gap: 10px;
  font-size: 14px;
  cursor: pointer;
  min-height: 44px;
}
#notif-req-toggle, #notif-acc-toggle, #notif-msg-toggle {
  width: 22px; height: 22px;
  flex-shrink: 0;
  accent-color: var(--accent);
}

/* Eigene Kennung im Profil-Abschnitt */
#my-code-line {
  font-size: 13px;
  color: var(--text-dim);
  margin-top: 8px;
  font-variant-numeric: tabular-nums;
  user-select: all;   /* zum einfachen Kopieren */
}

/* ============================================================
   Einstellungen im WhatsApp-Stil: Kategorien-Hauptliste
   ============================================================ */
#settings-home { padding: 6px 8px 14px; }
#settings-home.hidden { display: none; }
.settings-cat {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: transparent;
  border: none;
  padding: 13px 12px;
  border-radius: 12px;
  color: var(--text);
  font-size: 15px;
  text-align: left;
}
.settings-cat:hover { background: var(--hover); }
.settings-cat .cat-ico {
  display: flex;
  color: var(--accent);
  flex-shrink: 0;
}
/* Pfeil rechts als Wegweiser */
.settings-cat::after {
  content: '›';
  margin-left: auto;
  color: var(--text-dim);
  font-size: 18px;
}
.settings-cat-page.hidden { display: none; }

/* ============================================================
   Story-Reaktionen
   ============================================================ */
/* Emoji-Leiste unter der fremden Story */
#story-react-bar {
  display: flex;
  justify-content: center;
  gap: 10px;
  padding: 10px 0 4px;
}
#story-react-bar.hidden { display: none; }
#story-react-bar button {
  font-size: 24px;
  background: rgba(255, 255, 255, 0.10);
  border: none;
  border-radius: 50%;
  width: 46px; height: 46px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: transform 120ms;
}
#story-react-bar button:hover { transform: scale(1.18); }
#story-react-bar button.mine {
  background: rgba(145, 136, 216, 0.45);
  outline: 2px solid var(--accent);
}

/* Reaktions-Zusammenfassung bei der eigenen Story (im Kopf) */
#viewer-reacts {
  color: #F5F5F7;
  font-size: 14px;
  margin-left: 10px;
  white-space: nowrap;
}
#viewer-reacts.hidden { display: none; }

/* ============================================================
   Story-Reaktion als Chat-Nachricht (Mini-Vorschau + Emoji)
   ============================================================ */
.story-react-msg { display: flex; flex-direction: column; gap: 6px; }
.sr-label { font-size: 12px; color: inherit; opacity: 0.7; font-style: italic; }
.sr-thumb {
  position: relative;
  width: 96px;
  display: inline-block;
  line-height: 0;
}
.sr-thumb img {
  width: 96px;
  border-radius: 12px;
  display: block;
}
.sr-emoji {
  position: absolute;
  right: -10px; bottom: -8px;
  font-size: 26px;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35));
}

/* ============================================================
   Neues Layout nach Fabians Design-Vorlage (Juli 2026):
   Markenzeile, Filter-Chips, EINE Chatliste als Glaskarten,
   runde Composer-Knöpfe, Tipp-Punkte. Steht am Datei-Ende,
   damit es frühere Regeln überschreibt.
   ============================================================ */

/* ---------- Markenzeile oben in der Seitenleiste ---------- */
/* Beide Kopfzeilen exakt gleich hoch - so fluchten die
   Trennlinien von Seitenleiste und Chat sauber nebeneinander */
#sidebar header, #chat-header {
  /* Mindesthoehe statt fester Hoehe: Der Chat-Kopf ist seit der
     Zustandszeile zweizeilig und wuerde sonst oben und unten kleben.
     Bei einzeiligem Inhalt bleibt es bei 64 Pixeln, die Trennlinien
     fluchten also weiterhin. */
  min-height: 64px;
  padding-top: 6px;
  padding-bottom: 6px;
  align-items: center;
}
/* Eigenes Profilbild oben: gleiche Größe wie Lupe und ＋ */
#me-box .avatar { width: 38px; height: 38px; font-size: 15px; }

#brand {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
#brand-mascot { height: 30px; width: auto; }
#brand-name {
  font-size: 20px;
  font-weight: 800;
  color: var(--accent);
}
#header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Runde Kopfzeilen-Knöpfe: Lavendel-Glas mit Glow (Fabians Vorlage) -
   beide gleich, dünne helle Linien-Icons, leuchtender Rand */
:root {
  --hdr-glass:      rgba(126, 120, 184, 0.14);
  --hdr-glass-edge: rgba(126, 120, 184, 0.38);
  --hdr-glow:       0 0 12px rgba(126, 120, 184, 0.35);
  --hdr-icon:       #7E78B8;
}
:root[data-theme="dark"],
:root[data-theme="auto"].sys-dark,
:root:not([data-theme]).sys-dark {
  --hdr-glass:      rgba(145, 136, 216, 0.18);
  --hdr-glass-edge: rgba(200, 190, 255, 0.35);
  --hdr-glow:       0 0 16px rgba(145, 136, 216, 0.45);
  --hdr-icon:       #BCB2FF;
}
.hdr-btn,
.hdr-btn.accent {
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: 50%;
  background: var(--hdr-glass);
  border: 1px solid var(--hdr-glass-edge);
  color: var(--hdr-icon);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.hdr-btn:hover,
.hdr-btn.accent:hover {
  background: rgba(145, 136, 216, 0.30);
  color: var(--accent-hover);
}

/* Neu-Menü unter dem ＋ (gleiches Glas wie das Profil-Menü) */
#new-menu {
  position: absolute;
  top: calc(100% - 6px);
  right: 12px;
  background: var(--glass-strong);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  padding: 6px;
  z-index: 30;
  min-width: 210px;
}
#new-menu.hidden { display: none; }

/* ---------- Filter-Chips (Alle / Ungelesen / Gruppen) ---------- */
#chat-filters {
  display: flex;
  gap: 8px;
  padding: 10px 12px 4px;
  /* In schmalen Leisten scrollen die Chips seitlich statt umzubrechen */
  overflow-x: auto;
  scrollbar-width: none;
  /* Weiche Kante rechts, damit man SIEHT, dass es weitergeht. Ohne
     sie stand der letzte Chip einfach abgeschnitten da und wirkte
     wie ein Darstellungsfehler - nachgemessen im Programmfenster
     (1200 breit): "Anzeigen" endete 23 Pixel hinter dem Rand.

     Nachgemessen passt die Reihe nirgends ganz: am Handy fehlen
     3 Pixel (378 gegen 375), in der Seitenspalte des Programms 35.
     Auffaellig war deshalb nur der Rechner - die Spalte ist dort
     mit 336 Pixeln schmaler als ein Handybildschirm.

     Kostet nichts, wenn alles hineinpasst: Dann liegt am rechten
     Rand ohnehin nur Hintergrund, und der verblasst unsichtbar. */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 22px), transparent);
}
#chat-filters::-webkit-scrollbar { display: none; }
.chip {
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  background: var(--hover);
  color: var(--text-dim);
  border: 1px solid var(--border);
  white-space: nowrap;
  flex-shrink: 0;
}
.chip:hover { background: var(--selected); color: var(--text); }
.chip.active {
  background: var(--accent);
  color: var(--on-accent);
  border-color: transparent;
}
.chip.active:hover { background: var(--accent-hover); color: var(--on-accent); }

/* ---------- Archiv-Zeile ueber der Chatliste ----------
   Der Weg ins Archiv und zurueck. Flacher als eine Chat-Zeile: Sie
   ist ein Griff, kein Chat - deshalb kein Profilbild, keine Uhrzeit
   und etwas ruhigere Schrift.                                     */
#chat-list li.archiv-zeile {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;                /* rechts kein Extra-Platz: keine Uhrzeit */
  color: var(--text-dim);
  font-size: 14px;
  font-weight: 600;
}
#chat-list li.archiv-zeile .archiv-ico {
  display: flex;
  width: 40px;                        /* auf Höhe der Profilbilder darunter */
  justify-content: center;
  color: var(--text-dim);
}
#chat-list li.archiv-zeile .archiv-text { flex: 1; }
#chat-list li.archiv-zeile:hover { color: var(--text); }
#chat-list li.archiv-zeile:hover .archiv-ico { color: var(--accent); }
/* Steht man im Archiv, ist die Zeile die Kopfzeile darüber - sie
   darf dann deutlicher sein als der Inhalt, den sie überschreibt. */
#chat-list li.archiv-zeile.offen { color: var(--text); }
#chat-list li.archiv-zeile.offen .archiv-ico { color: var(--accent); }
/* Die Trennlinie der Liste beginnt beim Avatar - unter dieser Zeile
   soll sie durchgehen, sonst schwebt der Kopf über dem Nichts. */
#chat-list li.archiv-zeile + li::before { left: 0; }
#chat-list li.archiv-zeile .badge { position: static; }

/* ---------- Die vereinte Chatliste ----------
   Durchgehende Liste statt einzelner Karten: Karten sehen hübsch aus,
   kosten aber je Zeile Rand, Abstand und Schatten. Bei gleicher
   Bildschirmhöhe passen so drei Chats mehr aufs Handy - und genau so
   machen es die grossen Messenger auch.                          */
#chat-list {
  list-style: none;
  padding: 4px 0 0;
}
#chat-list li {
  padding: 10px 16px;
  padding-right: 62px;      /* Platz für Zeit + Badge rechts */
  cursor: pointer;
  position: relative;
  transition: background 160ms ease;
}
/* Feine Trennlinie, die beim Avatar beginnt - nicht am Bildschirmrand */
#chat-list li + li::before {
  content: '';
  position: absolute;
  left: 68px; right: 0; top: 0;
  height: 1px;
  background: var(--border);
  opacity: 0.6;
}
#chat-list li:hover { background: var(--hover); }
/* Aktiver Chat: Lavender-Rand mit sanftem Glow (wie im Design) */
#chat-list li.active {
  background: rgba(207, 195, 244, 0.16);
}
:root[data-theme="dark"] #chat-list li.active,
:root[data-theme="auto"].sys-dark #chat-list li.active,
:root:not([data-theme]).sys-dark #chat-list li.active {
  background: #312B52;
}
/* Zeit der letzten Nachricht oben rechts, Badge darunter */
.li-time {
  position: absolute;
  top: 12px;
  right: 16px;
  font-size: 12px;
  color: var(--text-dim);
}
#chat-list li .badge {
  top: auto;
  bottom: 12px;
  transform: none;
}

/* Alte Einzellisten: stecken jetzt in der vereinten Chatliste.
   Das Kontakte-Verzeichnis bleibt als eigener Tab am Handy. */
.groups-title, #group-list { display: none; }
.contacts-title, #contact-list { display: none; }
/* Die Vorschlaege gehoeren zum Kontakte-Verzeichnis und folgen ihm:
   standardmaessig aus, im Kontakte-Bereich wieder da. Ohne das
   standen sie auch im Chat-Tab. */
#vorschlag-kopf, #vorschlag-liste { display: none; }

/* ---------- Tipp-Anzeige mit hüpfenden Punkten ---------- */
#typing-indicator {
  /* inline-flex statt flex: Die Blase soll nur so breit sein wie ihr
     Text, nicht wie der ganze Chat. Kein Abstand zwischen Text und
     Punkten - die Punkte stehen fuer die Auslassungspunkte und
     gehoeren direkt ans Wort. */
  display: inline-flex;
  align-items: baseline;
  gap: 0;
  width: auto;
}
#typing-indicator.hidden { display: none; }
/* Die Punkte sind bewusst klein: Sie ersetzen die drei
   Auslassungspunkte hinter "tippt" und sollen wie Satzzeichen
   wirken, nicht wie eine eigene Grafik. */
.ty-dots {
  display: inline-flex;
  gap: 2px;
  margin-left: 3px;
  align-items: flex-end;
  padding-bottom: 1px;      /* sitzt auf der Grundlinie des Textes */
}
.ty-dots span {
  width: 3.5px;
  height: 3.5px;
  border-radius: 50%;
  background: currentColor;  /* dieselbe Farbe wie der Text daneben */
  animation: ty-bounce 1.2s infinite;
}
.ty-dots span:nth-child(2) { animation-delay: 0.15s; }
.ty-dots span:nth-child(3) { animation-delay: 0.3s; }
@keyframes ty-bounce {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.45; }
  30%           { transform: translateY(-2.5px); opacity: 1; }
}

/* ---------- Composer: runde Knöpfe außen (wie im Design) ---------- */
#send-form {
  /* flex-end, damit die runden Knöpfe neben der Pille UNTEN bleiben,
     wenn das Textfeld mitwächst. Bei "center" schwebten sie mitten
     neben einem mehrzeiligen Feld. */
  align-items: flex-end;
  gap: 8px;
}
#btn-attach {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--hover);
  border: 1px solid var(--border);
  color: var(--text-dim);
  flex-shrink: 0;
}
#btn-attach:hover { background: var(--selected); color: var(--accent); }
#btn-mic {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  flex-shrink: 0;
}
#btn-mic:hover { background: var(--accent-hover); color: var(--on-accent); }
#send-btn {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
}

/* ---------- Chat-Kopfzeile: Avatar + Name ---------- */
#chat-title {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
#chat-title .avatar { width: 32px; height: 32px; font-size: 13px; }

/* ---------- Bottom-Navigation: aktiver Tab als Lavender-Pille ---------- */
.nav-btn {
  border-radius: 14px;
  margin: 0 4px;
}
.nav-btn.active { background: rgba(145, 136, 216, 0.15); }

/* ---------- Tablet: schmale Seitenleiste ---------- */
@media (min-width: 701px) and (max-width: 1024px) {
  /* Nur das Maskottchen als Logo, sonst wird die Kopfzeile zu eng */
  #brand-name { display: none; }
  .hdr-btn { width: 34px; height: 34px; }
  #sidebar header { padding: 12px 10px; }
}

/* ---------- Schmale Web-Leiste ganz links (WhatsApp-Web-Stil) ---------- */
#left-rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 64px;
  flex-shrink: 0;
  padding: 12px 0 14px;
  background: var(--list-bg);
  border-right: 1px solid var(--border);
}
.rail-btn {
  width: 40px;
  height: 40px;
  padding: 0;
  border-radius: 50%;
  background: transparent;
  border: none;
  box-shadow: none;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Kein Kreis im Ruhezustand - beim Drueberfahren nur heller werden */
.rail-btn:hover { color: var(--accent-hover); }
/* NUR das aktive Icon bekommt den leuchtenden Lavendel-Kreis
   (nach Fabians Schallwellen-Vorlage) */
.rail-btn.active {
  background: linear-gradient(145deg, #8F84E8, #6F63C8);
  color: #E9E4FF;
  border: 1px solid rgba(220, 210, 255, 0.45);
  box-shadow: 0 0 16px rgba(145, 136, 216, 0.55);
}
.rail-btn.active:hover { color: #FFFFFF; box-shadow: 0 0 22px rgba(165, 156, 236, 0.75); }
.rail-spacer { flex: 1; }

/* Server-Bereich in der Seitenleiste */
#server-pane {
  display: none;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}
#server-list-view, #channel-view {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}
#server-list-view.hidden, #channel-view.hidden { display: none; }
/* Leerzustand: Maskottchen mittig, wenn es noch keine Server gibt */
#server-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex: 1;
  padding: 28px 22px;
  text-align: center;
  color: var(--text-dim);
  font-size: 14px;
  line-height: 1.5;
}
#server-empty.hidden { display: none; }
#server-empty .server-mascot { width: 110px; }
/* Serverliste: gleiche Glaskarten wie die Chatliste */
#server-list, #channel-list { list-style: none; padding: 8px 12px 0; }
#server-list li {
  padding: 12px 14px;
  cursor: pointer;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 16px;
  margin-bottom: 8px;
  transition: background 200ms ease;
}
#server-list li:hover { background: var(--hover); }
/* Kanal-Kopf: ← + Servername */
#channel-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px 6px;
  font-weight: 600;
  position: relative;          /* Anker für das Zahnrad-Menü */
}
#channel-title { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }
/* Zahnrad-Menü: gleiches Glas wie die anderen Menüs */
#server-menu {
  position: absolute;
  top: calc(100% - 2px);
  right: 10px;
  background: var(--glass-strong);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  padding: 6px;
  z-index: 30;
  min-width: 190px;
}
#server-menu.hidden { display: none; }
#channel-title .avatar { width: 30px; height: 30px; font-size: 13px; }
/* Kanäle: schlichte #-Zeilen wie bei Discord */
.channel-item {
  display: flex;
  align-items: center;
  padding: 11px 14px;
  padding-right: 48px;      /* Platz für das Ungelesen-Badge */
  margin: 0 12px 6px;
  border-radius: 12px;
  cursor: pointer;
  font-weight: 500;
  position: relative;
}
.channel-item:hover { background: var(--hover); }
/* Lange Kanalnamen kuerzen statt umbrechen. Nachgemessen: Die Zeile
   mit dem langen Namen war 64 Pixel hoch, die anderen 43 - am
   Rechner wie am Handy. Das Ungelesen-Zeichen bleibt aussen vor, es
   liegt ohnehin ueber der Zeile. */
.channel-item > span:not(.badge) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Beim Sprachkanal ist das aeussere span selbst ein Flex-Behaelter
   (Lautsprecher + Name) - dort kuerzt der Name im inneren span. */
.channel-item.voice-channel > span > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Server-Zeile in der Gruppeninfo: wie eine Einstellungs-Kategorie,
   mit dem Schallwellen-Logo in Lavender */
#btn-gi-upgrade { margin-top: 6px; }
/* Umschalter: Server-Modus blendet die Chat-Elemente aus */
#sidebar.mode-server .lists,
#sidebar.mode-server .search-box,
#sidebar.mode-server #header-actions { display: none; }
#sidebar.mode-server #server-pane { display: flex; }
/* Eigenes Profilbild unten: gleiche Größe wie die Leisten-Icons */
#rail-me .avatar { width: 40px; height: 40px; font-size: 15px; }
/* Profil-Menü, wenn es vom Leisten-Avatar unten geöffnet wurde */
#profile-menu.from-rail {
  position: fixed;
  left: 70px;
  bottom: 14px;
  top: auto;
  right: auto;
}
/* Am Handy klappt es über der Bottom-Leiste an der rechten Kante auf -
   direkt über dem Bild, das es geöffnet hat */
#profile-menu.from-nav {
  position: fixed;
  right: 12px;
  bottom: calc(72px + env(safe-area-inset-bottom));
  top: auto;
  left: auto;
}
/* Kopf des Profilmenues: eigenes Bild, Name, fester @handle.
   Keine Schaltflaeche - eine Auskunft. Deshalb ohne Hover-Effekt. */
#menu-me {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px 13px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
#menu-me-avatar .avatar,
#menu-me-avatar img { width: 40px; height: 40px; font-size: 16px; }
#menu-me-text { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
#menu-me-name {
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#menu-me-handle { font-size: 12.5px; color: var(--text-dim); }

/* Pflichtseiten am Fuß des Menüs (am Handy der einzige Weg dorthin) */
.menu-legal {
  margin: 6px 0 2px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}
/* Auf dem Web sitzt das Profil unten in der Leiste -
   der Avatar oben in der Kopfzeile verschwindet dort */
@media (min-width: 701px) {
  /* Emoji-Leiste: kompaktes Feld statt voller Chatbreite.
     Rechts ausgerichtet, weil dort der Emoji-Knopf sitzt. */
  #emoji-panel {
    max-width: 420px;
    margin-left: auto;
    border-left: 1px solid var(--border);
    border-top-left-radius: 14px;
  }

  #me-box { display: none; }
}

/* ---------- Handy-Feinschliff ---------- */
@media (max-width: 700px) {
  /* Am Handy sieht man immer nur EINE Ansicht: Geht man vom Chat
     zurueck zur Liste, ist gar kein Chat mehr offen - die
     Markierung blieb aber kleben und sah aus wie ein versehentlich
     hervorgehobener Eintrag. Am grossen Bildschirm stimmt sie,
     weil der Chat daneben wirklich offen ist. */
  #chat-list li.active,
  :root[data-theme="dark"] #chat-list li.active,
  :root[data-theme="auto"].sys-dark #chat-list li.active,
  :root:not([data-theme]).sys-dark #chat-list li.active {
    background: transparent;
  }

  /* Am Handy übernimmt die Bottom-Navigation - keine Web-Leiste */
  #left-rail { display: none; }

  /* Das eigene Bild sitzt jetzt unten rechts in der Leiste -
     oben in der Kopfzeile wäre es doppelt */
  #me-box { display: none; }

  /* Am Handy endet der Scrollbereich ÜBERM Eingabefeld (statt
     dahinter durchzulaufen) - so hört auch die Scrollleiste genau
     am sichtbaren Chatfenster auf und die letzte Blase hat Luft.
     70px = Composer-Höhe, plus iPhone-Home-Balken (safe-area). */
  #messages {
    /* Gemessen statt geraten - siehe tastatur.js. Die 70 hier
       waren einmal die Hoehe der Schreibzeile; als die kuerzer
       wurde, blieb ein toter Streifen stehen. */
    /* OHNE env(): --composer-hoehe ist die GEMESSENE Hoehe der
       Schreibzeile, und deren Polsterung enthaelt den Home-Balken
       bereits. Ihn hier noch einmal zu addieren zaehlte ihn
       doppelt. */
    /* Der Rueckfallwert MUSS den Home-Balken enthalten: Bis die
       Messung greift (die Schreibzeile ist beim ersten Zeichnen noch
       versteckt und damit 0 hoch), gilt er - und mit bloss 70 lag das
       untere Stueck der letzten Blase hinter der Zeile. */
    bottom: var(--composer-hoehe, calc(70px + env(safe-area-inset-bottom, 0px)));
    /* Seitlich knapper: 24 links und rechts sind auf 375 px Breite
       fast fuenfzig, die den Blasen fehlen. */
    padding: 78px 12px 14px;
  }
  /* Scrollbahn: oben weiter an der Glas-Kopfzeile enden,
     unten ist jetzt nichts mehr im Weg */
  #messages::-webkit-scrollbar-track {
    margin-top: 65px;
    margin-bottom: 0;
  }

  /* Gleiche Einrückung wie die übrigen Handy-Regeln */
  #chat-filters { padding: 10px 16px 4px; }
  #chat-list { padding: 8px 16px 0; }
  #chat-list li { padding: 10px 16px; padding-right: 62px; }

  /* Server-Tab: Leerzustand nicht hinter der Bottom-Nav verstecken */
  #server-pane { padding-bottom: 96px; }

  /* Kontakte-Tab: Verzeichnis zeigen, Chatliste ausblenden */
  #sidebar.mode-contacts .contacts-title { display: flex; }
  #sidebar.mode-contacts #contact-list { display: block; }
  #sidebar.mode-contacts #vorschlag-kopf:not(.hidden) { display: flex; }
  #sidebar.mode-contacts #vorschlag-liste { display: block; }
  #sidebar.mode-contacts #chat-filters,
  #sidebar.mode-contacts #chat-list,
  #sidebar.mode-contacts #chat-empty,
  #sidebar.mode-contacts #story-strip { display: none; }
}

/* ============================================================
   App-eigener Dialog: ersetzt die nackten Browser-Popups
   (alert/confirm/prompt) durch den Wirio-Glas-Look
   ============================================================ */
#app-dialog {
  position: fixed;
  inset: 0;
  /* Nur so hoch wie das, was man SIEHT. Bei offener Tastatur reicht
     das feste Fenster darunter weiter - der Dialog zentrierte sich
     also mitten hinein und stand hinter den Tasten. Beim Beschriften
     eines Fotos tippte man dadurch blind: Das Eingabefeld lag unter
     der Tastatur. --app-hoehe misst tastatur.js. */
  height: var(--app-hoehe, 100dvh);
  z-index: var(--z-frage);
  /* Im Dark Mode liegt eine dunkle Abdunklung auf ohnehin fast
     schwarzem Grund und trennt deshalb kaum - der Dialog sah aus wie
     aufgeklebt, und Knoepfe dahinter wirkten weiter bedienbar. Ein
     leichter Weichzeichner trennt in beiden Modi zuverlaessig. */
  background: rgba(15, 12, 25, 0.62);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
#app-dialog.hidden { display: none; }
#ad-box {
  background: var(--glass-strong);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
  padding: 20px;
  width: min(92vw, 380px);
  animation: msg-in 180ms ease;
}
#ad-text {
  font-size: 15px;
  line-height: 1.5;
  white-space: pre-line;       /* \n im Text = Absatz */
  overflow-wrap: break-word;
}
#ad-input { width: 100%; margin-top: 14px; }
#ad-buttons {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 18px;
}
#ad-buttons button { min-width: 96px; }
/* Der Knopf, hinter dem etwas verschwindet: rot statt lavender. Er
   soll sich beim Ueberfliegen vom harmlosen "OK" unterscheiden. */
#ad-ok.gefahr { background: var(--danger); color: #fff; }
#ad-ok.gefahr:hover { background: #C96565; }

/* Kanal löschen steht jetzt im Menü (Rechtsklick / Langdruck), nicht
   mehr als Papierkorb in jeder Zeile. Damit braucht das Ungelesen-
   Zeichen auch keinen Platz mehr für ihn und sitzt wieder am Rand. */

/* Auswahlfelder im Wirio-Look. Eigener Pfeil als SVG, damit es in
   Hell und Dunkel gleich aussieht - Browser zeichnen ihren eigenen
   sonst weiß und reißen ein Loch in den Dunkelmodus.
   .wirio-select ist die allgemeine Klasse dafür (Sprachwahl war der
   erste Fall, der Marktplatz nutzt sie ebenfalls). */
#lang-select, .wirio-select {
  width: 100%;
  padding: 12px 40px 12px 14px;
  border-radius: 12px;
  background-color: var(--hover);
  border: 1px solid var(--input-border);
  color: var(--text);
  font-size: 15px;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239188D8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
}
#lang-select:hover, .wirio-select:hover { background-color: var(--selected); }
#lang-select:focus, .wirio-select:focus { outline: none; border-color: var(--accent); }
/* Die Klappliste selbst zeichnet das System - Farben mitgeben,
   damit sie im Dunkelmodus nicht weiß aufblitzt */
#lang-select option, .wirio-select option { background: var(--panel); color: var(--text); }

/* Rechte Spalte der Chatkarte: Zeit oben, darunter das kleine
   Schallwellen-Zeichen (= Gruppe ist auch ein Server) und die
   Ungelesen-Zahl. Ersetzt die frühere absolute Platzierung. */
#chat-list li { padding-right: 14px; }
.li-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
  gap: 6px;
  flex-shrink: 0;
  min-height: 40px;
  align-self: stretch;
}
.li-right .li-time {
  position: static;
  font-size: 12px;
  color: var(--text-dim);
  white-space: nowrap;
}
.li-marks {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* Badge sitzt jetzt IN der Spalte, nicht mehr absolut am Rand */
.li-marks .badge {
  position: static;
  transform: none;
  padding: 2px 7px;
  min-width: 20px;
}
/* Dezentes Lavender-Zeichen, bewusst klein */
.li-wave {
  display: flex;
  color: var(--accent);
  opacity: 0.85;
}

/* ============================================================
   Marktplatz-Chats: eigene Optik im Chatbereich
   Kein Profilbild (Datenschutz) - stattdessen ein Preisschild;
   darüber eine Leiste mit dem Verweis auf die Anzeige.
   ============================================================ */
.market-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(145, 136, 216, 0.18);
  border: 1px solid var(--border);
  color: var(--accent);
}
#chat-title .market-avatar { width: 32px; height: 32px; }

/* Leiste unter der Kopfzeile: welche Anzeige ist gemeint? */
#listing-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 20px;
  cursor: pointer;
  background: var(--glass-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
  position: relative;
  z-index: 6;
}
#listing-bar.hidden { display: none; }
/* Die Leiste soll direkt UNTER der Kopfzeile kleben. Normalerweise
   schiebt das margin-bottom:auto der Kopfzeile alles Weitere nach
   unten - ist die Leiste sichtbar, übernimmt sie diese Aufgabe. */
#chat-header:has(+ #listing-bar:not(.hidden)) { margin-bottom: 0; }
#listing-bar:not(.hidden) { margin-bottom: auto; }
#listing-bar:hover { background: var(--hover); }
#listing-bar-ico { display: flex; flex-shrink: 0; }
#listing-bar-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ============================================================
   Aktions-Blatt an einer Nachricht (WhatsApp-Muster)
   Ersetzt die frühere Leiste an der Blase, die bei schmalen
   Bildschirmen aus dem Bild lief. Emoji-Reihe oben, darunter
   die Aktionen als lesbare Liste - passt immer auf den Schirm.
   ============================================================ */
#msg-sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 45;
  background: rgba(12, 10, 20, 0.55);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0;
  animation: fade-in 160ms ease;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

#msg-sheet {
  width: 100%;
  max-width: 420px;
  background: var(--glass-strong);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--border);
  border-radius: 20px 20px 0 0;
  box-shadow: 0 -8px 34px rgba(0, 0, 0, 0.35);
  padding: 10px 10px calc(14px + env(safe-area-inset-bottom));
  animation: sheet-up 200ms ease;
}
@keyframes sheet-up {
  from { transform: translateY(18px); opacity: 0.6; }
  to   { transform: translateY(0); opacity: 1; }
}

/* Emoji-Reihe: verteilt sich über die volle Breite, nichts läuft raus */
.sheet-reactions {
  display: flex;
  justify-content: space-between;
  gap: 2px;
  padding: 6px 6px 10px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 6px;
}
.sheet-reactions button {
  flex: 1;
  min-width: 0;
  padding: 6px 0;
  font-size: 26px;
  line-height: 1;
  background: transparent;
  border: none;
  border-radius: 12px;
  transition: transform 140ms ease, background 140ms ease;
}
.sheet-reactions button:hover { background: var(--hover); transform: scale(1.12); }
.sheet-reactions button:active { transform: scale(0.95); }

/* Aktionen als Liste mit Beschriftung */
.sheet-actions { display: flex; flex-direction: column; }
.sheet-item {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 13px 14px;
  border-radius: 12px;
  background: transparent;
  border: none;
  color: var(--text);
  font-size: 15px;
  text-align: left;
}
.sheet-item:hover { background: var(--hover); }
.sheet-item .sheet-ico { display: flex; color: var(--accent); flex-shrink: 0; }
.sheet-item.danger { color: var(--danger); }
.sheet-item.danger .sheet-ico { color: var(--danger); }

/* Am PC schwebt das Blatt mittig statt unten zu kleben */
@media (min-width: 701px) {
  #msg-sheet-overlay { align-items: center; padding: 24px; }
  #msg-sheet { border-radius: 20px; box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35); }
}

/* Der Papierkorb in gelöschten Nachrichten. Der Hinweistext daneben
   bleibt kursiv, das Symbol steht gerade - als SVG von allein. */
.msg.deleted .del-ico {
  display: inline-flex;
  vertical-align: -2px;
  opacity: 0.7;
}

/* ============================================================
   Begrüßung beim Start
   Das Maskottchen winkt kurz, dann öffnet sich die App.
   Bewusst als CSS-Bewegung mit einem freigestellten Bild:
   so gibt es keinen Hintergrund-Kasten, es lädt sofort (32 KB)
   und bleibt auf jedem Bildschirm gestochen scharf.
   ============================================================ */
#splash {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Sanfter Lavender-Schimmer auf dem App-Hintergrund */
  background:
    radial-gradient(circle at 50% 42%, rgba(145, 136, 216, 0.22), transparent 62%),
    var(--bg);
  animation: splash-out 500ms ease 1700ms forwards;
}
/* Ist die Begrüßung durch, verschwindet sie ganz */
@keyframes splash-out {
  to { opacity: 0; visibility: hidden; }
}

#splash-mascot {
  width: min(52vw, 260px);
  height: auto;
  /* Die Bewegung steckt in der Bilddatei selbst - hier nur das
     sanfte Auftauchen */
  animation: splash-in 460ms cubic-bezier(0.34, 1.4, 0.64, 1) both;
}
/* Auftauchen: klein und leicht versetzt herein */
@keyframes splash-in {
  from { opacity: 0; transform: scale(0.72) translateY(14px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
/* Während des Flugs zur Markenzeile: Hintergrund weich auflösen,
   die Figur bleibt sichtbar und wandert nach oben links */
#splash.flying {
  animation: none;
  background: transparent;
  transition: background 600ms ease;
  pointer-events: none;
}
#splash.flying #splash-mascot { filter: none; }

#splash-name {
  transition: opacity 300ms ease;
  font-size: 26px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--accent);
  opacity: 0;
  animation: splash-name-in 460ms ease 380ms forwards;
}
@keyframes splash-name-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 0.95; transform: translateY(0); }
}

/* Wer Bewegungen reduziert haben möchte, sieht nur ein kurzes
   Standbild statt der Wackelbewegung */
@media (prefers-reduced-motion: reduce) {
  #splash-mascot, #splash-name { animation: none; opacity: 1; }
  #splash { animation: splash-out 300ms ease 1200ms forwards; }
}

/* ============================================================
   Begrüßung in der Anmeldemaske
   Das Maskottchen steht von Anfang an GENAU dort, wo es auch
   später steht, winkt einmal und bleibt stehen. Nur die Maske
   drumherum (Kasten, Titel, Felder) blendet danach ein.
   ============================================================ */
html.start-login #splash { display: none; }

/* Der Kasten selbst ist zunächst unsichtbar - man sieht nur die Figur */
html.start-login #login-box {
  background: transparent;
  border-color: transparent;
  box-shadow: none;
  animation: auth-box-in 620ms ease 1500ms forwards;
}
@keyframes auth-box-in {
  to {
    background: var(--panel);
    border-color: var(--border);
    box-shadow: 0 8px 30px rgba(45, 49, 66, 0.14);
  }
}

/* Alles außer dem Maskottchen blendet nach dem Winken ein */
html.start-login #login-box > *:not(.auth-mascot) {
  opacity: 0;
  animation: auth-parts-in 560ms ease 1500ms forwards;
}
@keyframes auth-parts-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Die Figur selbst: nur sanft auftauchen, danach steht sie */
html.start-login .auth-mascot {
  animation: mascot-appear 420ms ease both;
}
@keyframes mascot-appear {
  from { opacity: 0; transform: scale(0.9); }
  to   { opacity: 1; transform: scale(1); }
}

/* Wer Bewegung reduziert haben möchte, sieht alles sofort */
@media (prefers-reduced-motion: reduce) {
  html.start-login #login-box,
  html.start-login #login-box > *:not(.auth-mascot),
  html.start-login .auth-mascot { animation-delay: 0ms; animation-duration: 200ms; }
}

/* ============================================================
   Begrüßung im angemeldeten Zustand (grosser Bildschirm)
   Das Maskottchen winkt genau dort, wo es auch steht, wenn kein
   Chat gewählt ist. Die App blendet drumherum ein - gleiches
   Muster wie in der Anmeldemaske.
   ============================================================ */
html.start-app #splash { display: none; }

html.start-app #left-rail,
html.start-app #sidebar,
html.start-app #chat-header,
html.start-app #empty-text {
  opacity: 0;
  animation: app-parts-in 620ms ease 1500ms forwards;
}
@keyframes app-parts-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
/* Die Figur selbst taucht nur sanft auf und bleibt dann stehen */
html.start-app #empty-state .mascot {
  animation: mascot-appear 420ms ease both;
}

/* Am Handy ist dieser Platz beim Start nicht sichtbar - dort bleibt
   die kurze Begrüßung über der ganzen Fläche */
html.start-app-mobile #splash { display: flex; }

/* Solange die Begrüßung läuft, bleibt der Platz in der Leiste leer -
   die Figur soll dort erst durch ihre Landung auftauchen. Der Platz
   wird trotzdem freigehalten, damit nichts springt. */
html.start-app-mobile #brand-mascot { visibility: hidden; }

/* ============================================================
   Emoji-Vorschläge beim Schreiben (":lach" -> 😆 😂 🤣 ...)
   Erscheint direkt über der Eingabezeile.
   ============================================================ */
#emoji-suggest {
  position: fixed;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  max-height: 132px;
  overflow-y: auto;
  padding: 8px;
  border-radius: 14px;
  background: var(--glass-strong);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 1px solid var(--border);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.32);
  animation: msg-in 140ms ease;
}
#emoji-suggest.hidden { display: none; }
.emoji-suggest-item {
  width: 40px;
  height: 40px;
  padding: 0;
  border: none;
  border-radius: 10px;
  background: transparent;
  font-size: 24px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.emoji-suggest-item:hover { background: var(--hover); }
/* Der gerade gewählte Vorschlag (Pfeiltasten) */
.emoji-suggest-item.active {
  background: var(--selected);
  box-shadow: inset 0 0 0 1px var(--accent);
}


/* ============================================================
   Kamera für Status-Beiträge (story-camera.js)
   Vollbild, dunkel, alles Wichtige unten in Daumennähe.
   ============================================================ */
#story-camera {
  position: fixed;
  inset: 0;
  z-index: 120;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}
#story-camera.hidden { display: none; }

#cam-vorschau {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Die Frontkamera zeigt spiegelverkehrt - so kennt man sich selbst */
#cam-vorschau.gespiegelt { transform: scaleX(-1); }
/* Ohne Kamerazugriff bleibt der Weg über Bibliothek und Text */
#story-camera.ohne-kamera #cam-vorschau { display: none; }
#story-camera.ohne-kamera #cam-wechseln { display: none; }
#story-camera.ohne-kamera #cam-ausloeser { opacity: 0.35; pointer-events: none; }
/* Der Hinweis ohne Kamera beschreibt einen Zustand und bleibt
   deshalb stehen. Er braucht mehr Platz als eine kurze Quittung. */
#cam-hinweis.dauerhaft {
  max-width: min(300px, 82vw);
  line-height: 1.45;
  white-space: normal;
  text-align: center;
}

/* Runde Knöpfe oben */
.cam-rund {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 14px);
  width: 40px; height: 40px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 18px;
  backdrop-filter: blur(6px);
}
#cam-schliessen { left: 14px; }
#cam-wechseln  { right: 14px; font-size: 22px; }

/* Untere Leiste: Bibliothek - Auslöser - Text */
#cam-leiste {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 26px);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  justify-items: center;
  padding: 0 26px;
}
.cam-eck {
  width: 48px; height: 48px;
  border: none;
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.42);
  color: #fff;
  font-size: 17px;
  font-weight: 600;
  display: grid;
  place-items: center;
  backdrop-filter: blur(6px);
}
#cam-galerie { justify-self: start; }
#cam-text    { justify-self: end; }

/* Der Auslöser: tippen macht ein Foto, halten nimmt Video auf */
#cam-ausloeser {
  position: relative;
  width: 76px; height: 76px;
  border-radius: 50%;
  border: 4px solid rgba(255, 255, 255, 0.9);
  background: rgba(255, 255, 255, 0.22);
  padding: 0;
  transition: transform 160ms ease, background 160ms ease;
}
#cam-ausloeser:active { transform: scale(0.94); }

/* Während der Videoaufnahme wächst ein roter Ring um den Auslöser */
#cam-ring {
  position: absolute;
  inset: -10px;
  border-radius: 50%;
  border: 4px solid transparent;
}
#story-camera.nimmt-auf #cam-ausloeser {
  background: #E05A5A;
  transform: scale(1.08);
}
#story-camera.nimmt-auf #cam-ring {
  border-color: #E05A5A;
  animation: cam-ring-drehen 1.1s linear infinite;
}
@keyframes cam-ring-drehen {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Kurze Meldung, wenn etwas nicht geht */
#cam-hinweis {
  position: absolute;
  left: 50%;
  bottom: 130px;
  transform: translateX(-50%);
  max-width: 78%;
  padding: 9px 16px;
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.72);
  color: #fff;
  font-size: 13px;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
}
#cam-hinweis.sichtbar { opacity: 1; }

/* Solange die Kamera offen ist, soll nichts dahinter scrollen */
html.kamera-offen, html.kamera-offen body { overflow: hidden; }

/* Video im Status und in der Vorschau füllt den Rahmen wie ein Foto */
#composer-preview video,
.story-media-wrap video {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* ============================================================
   Bühne für Status-Beiträge (story-effects.js)
   Bild/Video, darüber Filterschleier, Körnung und die Texte.
   Wird beim Bearbeiten UND beim Ansehen benutzt - so sieht der
   Status beim Empfänger genauso aus wie beim Erstellen.
   ============================================================ */
.story-buehne {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000;
  container-type: size;        /* für Schriftgrößen in cqh */
  touch-action: none;          /* Gesten gehören uns */
}
.story-medien {
  position: absolute;
  inset: 0;
  transform-origin: center;
  will-change: transform;
}
.story-medien > img,
.story-medien > video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.story-schleier, .story-korn {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.story-korn {
  opacity: 0;
  background-size: 140px 140px;
  mix-blend-mode: overlay;
}
.story-texte {
  position: absolute;
  inset: 0;
}

/* Ein Textstück: frei platziert oder als Band über die ganze Breite */
.story-text-stueck {
  position: absolute;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  white-space: pre-wrap;
  word-break: break-word;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
  padding: 4px 10px;
  max-width: 86%;
}
.story-text-stueck.band {
  left: 0; right: 0;
  max-width: none;
  transform: translateY(-50%);
  background: rgba(0, 0, 0, 0.42);
  backdrop-filter: blur(3px);
  padding: 10px 16px;
}
.story-text-stueck.mit-hintergrund:not(.band) {
  background: rgba(0, 0, 0, 0.34);
  border-radius: 10px;
  backdrop-filter: blur(3px);
}
.story-text-stueck.gewaehlt {
  outline: 2px dashed rgba(255, 255, 255, 0.75);
  outline-offset: 3px;
}

/* ============================================================
   Editor: Bild bewegen, Filter wischen, Texte setzen
   ============================================================ */
#story-editor {
  position: fixed;
  inset: 0;
  z-index: 130;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}
#story-editor.hidden { display: none; }

#ed-buehne-halter {
  width: 100%;
  height: 100%;
  max-width: min(100vw, calc(100vh * 9 / 16));
  aspect-ratio: 9 / 16;
  max-height: 100vh;
}

.ed-rund {
  width: 42px; height: 42px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.48);
  color: #fff;
  font-size: 17px;
  font-weight: 600;
  backdrop-filter: blur(6px);
  display: grid;
  place-items: center;
}
.ed-rund.verborgen { display: none; }

#ed-zurueck {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 14px);
  left: 14px;
}
#ed-werkzeuge {
  position: absolute;
  top: calc(env(safe-area-inset-top, 0px) + 14px);
  right: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Name des Filters blitzt beim Wechsel kurz auf */
#ed-filtername {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 10px 22px;
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.4px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 260ms ease;
  backdrop-filter: blur(8px);
}
#ed-filtername.sichtbar { opacity: 1; }

#ed-fuss {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 18px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 0 18px;
}
#ed-filterpunkte { display: flex; gap: 6px; }
.ed-punkt {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
  transition: background 200ms ease, transform 200ms ease;
}
.ed-punkt.aktiv { background: #fff; transform: scale(1.4); }

#ed-fertig {
  border: none;
  border-radius: 22px;
  padding: 11px 26px;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
  font-size: 15px;
}

/* Texteingabe: alles andere tritt zurück */
#ed-texteingabe {
  position: absolute;
  inset: 0;
  z-index: 4;
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(4px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  padding: 24px;
}
#ed-texteingabe.hidden { display: none; }
#ed-eingabefeld {
  min-width: 60%;
  max-width: 90%;
  min-height: 1.4em;
  font-size: 26px;
  font-weight: 700;
  text-align: center;
  color: #fff;
  outline: none;
  padding: 8px 14px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.35);
}
#ed-farben { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
.ed-farbe {
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.75);
}
#ed-text-fertig {
  border: none;
  border-radius: 22px;
  padding: 10px 30px;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
}

/* ============================================================
   Status ansehen: gleiche Bühnenform wie beim Erstellen
   Sonst würde am breiten Bildschirm ein anderer Ausschnitt zu
   sehen sein als der, den man beim Bearbeiten gewählt hat.
   ============================================================ */
#viewer-content .story-buehne {
  width: auto;
  height: 100%;
  aspect-ratio: 9 / 16;
  max-width: 100%;
  margin: 0 auto;
  border-radius: 12px;
}
/* Innerhalb der Bühne gilt deren eigene Regel, nicht die alte
   Bildregel des Betrachters */
#viewer-content .story-buehne img { max-width: none; max-height: none; }

/* Der Löschen-Knopf hatte seinen Text neben sich statt darin */
#btn-story-delete {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 14px;
  font-size: 13px;
  line-height: 1;
  white-space: nowrap;
  width: auto;
  height: auto;
}
#btn-story-delete svg { flex: 0 0 auto; }

/* ============================================================
   Kamera: nichts markieren beim Halten
   Langes Drücken löst sonst die Textauswahl des Browsers aus -
   dann färbt sich das halbe Bild blau, während man filmt.
   ============================================================ */
#story-camera,
#story-camera *,
#story-editor .story-buehne,
#story-editor .story-buehne * {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;      /* kein "Bild sichern"-Menü */
}
/* Beim Schreiben muss Auswahl natürlich erlaubt bleiben */
#ed-eingabefeld {
  -webkit-user-select: text;
  user-select: text;
}
/* Der Auslöser bekommt alle Fingerbewegungen selbst - sonst scrollt
   das Ziehen zum Zoomen die Seite statt zu zoomen */
#cam-ausloeser { touch-action: none; }

/* Zoomstufe während der Aufnahme */
#cam-zoom {
  position: absolute;
  left: 50%;
  bottom: 140px;
  transform: translateX(-50%);
  padding: 6px 14px;
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease;
  backdrop-filter: blur(6px);
}
#cam-zoom.sichtbar { opacity: 1; }

/* ============================================================
   Kamera- und Editorknöpfe: Symbole sauber mittig
   Die allgemeine Knopfregel gibt allen Knöpfen einen Innenabstand.
   Bei den runden Knöpfen mit fester Größe schiebt der die Symbole
   aus der Mitte - deshalb hier ausdrücklich zurücksetzen.
   ============================================================ */
.cam-rund, .cam-eck, .ed-rund, #cam-ausloeser {
  box-sizing: border-box;
  padding: 0;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
/* Die Symbole selbst mittig ausrichten (Zeichen wie ✖ und ⟳ sitzen
   je nach Schriftart etwas tief) */
.cam-rund, .ed-rund {
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
}
.cam-rund svg, .cam-eck svg, .ed-rund svg { display: block; }

/* Ton-Knopf im Editor: stumm wird deutlich markiert */
#ed-ton.aus {
  background: rgba(217, 120, 120, 0.85);
}

/* ============================================================
   Reaktionen sitzen auf dem Rand der Blase
   Vorher hingen sie innen und machten die Blase höher. Jetzt liegt
   der untere Rand der Blase genau durch die Mitte der Reaktion -
   so kennt man es von anderen Messengern.
   ============================================================ */
.msg { position: relative; }

.msg .reactions {
  position: absolute;
  bottom: -13px;                   /* sitzt unter der Blase, nicht darin */
  right: -4px;                     /* und ragt an der Ecke leicht heraus */
  left: auto;
  margin: 0;
  z-index: 2;
  gap: 3px;
}
/* Die Reaktion haengt an der unteren rechten Ecke - sie liegt
   ausserhalb der Blase und kommt der Uhrzeit deshalb nicht ins Gehege. */

/* Damit die überstehende Hälfte nicht in die nächste Nachricht ragt,
   bekommt eine Blase mit Reaktionen unten etwas Luft. */
.msg:has(.reactions:not(.hidden)) { margin-bottom: 20px; }

/* ============================================================
   Wischen zum Antworten: Während der Finger zieht, wächst links
   neben der Blase ein Antwort-Pfeil heraus. --wisch geht von 0
   bis 1 (gesetzt in app.js) und steuert Größe und Deckkraft -
   bei 1 ist die Schwelle erreicht und es wird geantwortet.
   ============================================================ */
.msg.wisch-antwort { will-change: transform; }
.msg.wisch-antwort::after {
  content: '';
  position: absolute;
  left: -42px;
  top: 50%;
  width: 30px; height: 30px;
  margin-top: -15px;
  border-radius: 50%;
  background: var(--accent);
  opacity: calc(var(--wisch, 0) * 0.9);
  transform: scale(calc(0.5 + var(--wisch, 0) * 0.5));
  /* Antwort-Pfeil, gezeichnet als Maske - kein extra Element nötig */
  -webkit-mask: var(--wisch-pfeil) center / 17px 17px no-repeat;
  mask: var(--wisch-pfeil) center / 17px 17px no-repeat;
  box-shadow: 0 1px 6px rgba(22, 25, 36, 0.25);
  /* Die Deckkraft folgt dem Finger sofort, die Größe einen Hauch
     verzögert - dadurch wirkt der Pfeil "lebendig" statt starr */
  transition: transform 90ms ease-out;
}
/* Schwelle erreicht: der Pfeil schnappt einmal auf und wird satt.
   Man sieht am Daumen, dass jetzt zitiert wird - vor dem Loslassen. */
.msg.wisch-bereit::after {
  animation: wisch-schnapp 260ms cubic-bezier(0.34, 1.56, 0.64, 1);
  opacity: 1;
}
@keyframes wisch-schnapp {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.28); }
  100% { transform: scale(1.1); }
}
/* Zurückfedern nach dem Loslassen: kurz übers Ziel hinaus und
   zurück - das fühlt sich nach Gummiband an, nicht nach Rutsche. */
.msg.wisch-zurueck {
  transition: transform 300ms cubic-bezier(0.22, 1.2, 0.36, 1);
}

/* Langdrücken: die Blase "gibt nach", solange der Finger hält.
   Bewusst über brightness statt transform - so kommt es der
   Wisch-Verschiebung nicht in die Quere. */
.msg.gedrueckt {
  filter: brightness(0.93) saturate(1.1);
  transition: filter 160ms ease;
}
:root {
  --wisch-pfeil: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' \
stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'>\
<path d='M9 17 4 12 9 7'/><path d='M20 18v-2a4 4 0 0 0-4-4H4'/></svg>");
}

.msg .reaction-chip {
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
  /* eng ums Emoji herum - nur bei mehreren gleichen wird es breiter */
  padding: 2px 5px;
  line-height: 1.2;
  font-size: 14px;
}
.msg .reaction-chip.mine {
  background: var(--selected);
  border-color: var(--accent);
}

/* ============================================================
   Melden (melden.js)
   Erscheint nur, wenn jemand wirklich meldet - sonst ist davon
   nichts zu sehen.
   ============================================================ */
.melde-overlay {
  position: fixed;
  inset: 0;
  z-index: 140;
  background: rgba(10, 10, 20, 0.55);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.melde-kasten {
  width: min(420px, 100%);
  max-height: 86vh;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 22px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35);
  animation: popup-in 200ms ease both;
}
.melde-kasten h3 {
  margin: 0 0 4px;
  font-size: 18px;
  color: var(--text);
}
.melde-frage {
  margin: 0 0 14px;
  font-size: 14px;
  color: var(--text-dim);
}
.melde-gruende {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}
.melde-grund {
  background: var(--hover);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 14px;
}
.melde-grund.aktiv {
  background: var(--selected);
  border-color: var(--accent);
}
.melde-notiz {
  width: 100%;
  min-height: 64px;
  resize: vertical;
  background: var(--hover);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 12px;
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
}
.melde-sperre {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 14px;
  font-size: 14px;
  color: var(--text);
  cursor: pointer;
}
.melde-sperre input { width: 17px; height: 17px; accent-color: var(--accent); }
.melde-hinweis {
  margin: 14px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-dim);
}
.melde-knoepfe {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 18px;
}
.melde-ab {
  background: var(--hover);
  border: 1px solid var(--border);
  color: var(--text);
}
.melde-ok { background: var(--danger); }
.melde-ok:disabled { opacity: 0.5; }
.melde-ok:hover:not(:disabled) { background: #c96a6a; }

/* Fahne in der Verkäuferzeile einer Anzeige */
.ad-melden {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--text-dim);
  padding: 6px;
  border-radius: 8px;
}
.ad-melden:hover { background: var(--hover); color: var(--text); }

/* Fahne im Status-Betrachter */
#btn-story-report {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  border: none;
  padding: 6px 10px;
  border-radius: 12px;
  font-size: 15px;
}
#btn-story-report.hidden { display: none; }

/* Blockierte Personen in den Einstellungen.
   Gleicher Einzug wie die anderen Abschnitte dort. */
#blocked-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 16px 14px;
}
#blocked-empty { font-size: 14px; color: var(--text-dim); line-height: 1.5; margin: 0; }
#blocked-empty.hidden { display: none; }
#blocked-list { display: flex; flex-direction: column; gap: 8px; }
.blocked-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  background: var(--hover);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.blocked-who { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; }
.blocked-name { font-size: 14px; color: var(--text); }
.blocked-handle { font-size: 12px; color: var(--text-dim); }

/* Zustimmung zu den Nutzungsbedingungen bei der Registrierung */
#reg-terms {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 4px 0 2px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--text-dim);
  cursor: pointer;
  text-align: left;
}
#reg-terms input {
  width: 17px; height: 17px;
  margin-top: 1px;
  flex: 0 0 auto;
  accent-color: var(--accent);
}
#reg-terms a { color: var(--accent); }

/* Fenster, das bestehenden Konten die Bedingungen vorlegt */
.agb-kasten h3 { margin-bottom: 10px; }
.agb-kasten .melde-hinweis { font-size: 14px; }
.agb-kasten .melde-hinweis a { color: var(--accent); }


/* ============================================================
   Kopfzeile eines Chats
   Name oben, darunter eine ruhige Zeile mit @handle bzw. dem
   Online-Zustand. Vorher stand beides nebeneinander und der
   Handle wurde mitten im Wort abgeschnitten.
   ============================================================ */
#chat-title {
  flex-wrap: wrap;
  align-items: center;
  line-height: 1.25;
  min-width: 0;
}
/* Der Name in der Kopfzeile kuerzt jetzt selbst (siehe nameText in
   app.js). Er muss dafuer den uebrigen Platz nehmen duerfen - und
   ihn wieder hergeben, wenn die Knoepfe daneben ihn brauchen. */
#chat-title .name-text { flex: 0 1 auto; }
/* Neben der Raute eines Kanals gilt etwas anderes: Dort stand die
   Raute allein in der ersten Zeile und der Name darunter. Ein
   Flex-Kind bricht naemlich um, wenn seine GRUNDBREITE nicht mehr in
   die Zeile passt - geschrumpft wird erst innerhalb der Zeile. Bei
   'auto' ist die Grundbreite die volle Textbreite, also brach der
   Name um, statt neben der Raute zu kuerzen. Grundbreite 0 passt
   immer.

   Nur hier, nicht ueberall: Beim Kontakt kostete dieselbe Regel den
   Namen Platz (91 statt 135 Pixel), weil er sich dann die Zeile mit
   dem Bild teilt, statt sie zu fuellen. */
#chat-title .kanal-raute + .name-text { flex: 1 1 0; }
#chat-title .handle-tag,
#chat-title .peer-state {
  flex-basis: 100%;
  /* Sich selbst begrenzen und kuerzen. Die Zeile lief nicht ueber
     ihren EIGENEN Kasten - sie war schlicht breiter als das
     Titelfeld und wurde von dessen overflow abgeschnitten. Ein
     text-overflow am Titelfeld hilft dagegen nicht; es muss hier
     stehen. Vorher endete die Zeile mitten im Handle ("@probo"). */
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-left: 40px;        /* auf Höhe des Namens, neben dem Bild */
  /* Der Name sitzt mittig neben dem 40 Pixel hohen Bild - darunter
     bleibt Luft. Die zweite Zeile ruecken wir deshalb wieder heran. */
  margin-top: -5px;
  line-height: 1.2;
}
.peer-state {
  font-size: 12px;
  color: var(--text-dim);
}
.peer-state.online { color: #6FCF97; }


/* ============================================================
   Es klingelt: ein ruhiger Puls um das Bild
   Ohne ihn wirkt der Bildschirm eingefroren - man sieht nicht,
   dass gerade etwas passiert.
   ============================================================ */
#call-overlay.klingelt #call-avatar .avatar {
  animation: call-puls 1.8s ease-out infinite;
}
@keyframes call-puls {
  0%   { box-shadow: 0 0 0 0 rgba(145, 136, 216, 0.55); }
  70%  { box-shadow: 0 0 0 22px rgba(145, 136, 216, 0); }
  100% { box-shadow: 0 0 0 0 rgba(145, 136, 216, 0); }
}
@media (prefers-reduced-motion: reduce) {
  #call-overlay.klingelt #call-avatar .avatar { animation: none; }
}


/* ============================================================
   Anrufknöpfe im Aus-Zustand
   Symbol allein reicht nicht - bei 24 Pixeln sieht man den
   Durchstrich kaum. Deshalb zusätzlich ein kräftiger roter Knopf
   und ein kurzes Wort darunter.
   ============================================================ */
.call-buttons button {
  position: relative;
  flex-direction: column;
  gap: 2px;
}
.knopf-wort {
  font-size: 9.5px;
  line-height: 1;
  font-weight: 600;
  letter-spacing: 0.2px;
  white-space: nowrap;
}
/* Im Aus-Zustand wird der Knopf höher, damit das Wort Platz hat */
.call-buttons button.active-off { padding-top: 4px; padding-bottom: 4px; }

/* Lautsprecher an ist ein gewollter Zustand, kein Fehlzustand -
   deshalb lavendel und nicht rot wie bei stumm/Kamera aus. */
.call-buttons button.speaker-on { padding-top: 4px; padding-bottom: 4px; }

/* ---------- Eigenes Rechtsklick-Menue ---------- */
/* Das Menue des Browsers sieht nach Betriebssystem aus und kennt
   die App nicht. Dieses hier passt zum Rest und bietet an, was an
   der angeklickten Stelle wirklich Sinn ergibt. */
.kmenue {
  position: fixed;
  z-index: 60;                 /* auch ueber dem schwebenden Fenster */
  /* Am Handy oeffnet ein langer Druck dieses Menue - der Finger
     liegt beim Loslassen also darauf. Ohne das hier markiert er
     das Wort unter sich, und man sieht statt des Menues eine blaue
     Auswahl mit Kopieren-Blase. */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  min-width: 190px;
  padding: 5px;
  border-radius: 11px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.36);
  animation: km-auf 110ms ease;
}
@keyframes km-auf {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}
.km-eintrag {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text);
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}
.km-eintrag:hover { background: var(--hover); }
/* Daumengroesse am Handy: Nachgemessen waren die Zeilen 31 Pixel
   hoch. Am Handy oeffnet man dieses Menue mit einem langen Druck,
   und direkt unter "Thema festlegen" steht "Kanal loeschen" - zu
   eng fuer etwas, das nicht zurueckzuholen ist. Am Rechner bleibt es
   schlank, dort zielt man mit der Maus.

   NUR hier, nicht auch .menu-item: Das Profilmenue hat elf
   Eintraege und waere auf 608 Pixel gewachsen - auf einem 667 Pixel
   hohen Bildschirm ragte es dann oben heraus (gemessen: Oberkante
   -13), und scrollen kann es nicht.

   min-height, nicht height: Der Eintrag "Benachrichtigungen" traegt
   einen Zusatz und ist von sich aus hoeher. */
@media (max-width: 700px) {
  .km-eintrag { min-height: 44px; }
}
.km-eintrag svg { flex-shrink: 0; color: var(--text-dim); }
.km-eintrag:hover svg { color: var(--text); }
/* Loeschen und Verlassen in Rot - man soll kurz zoegern */
.km-eintrag.gefahr { color: var(--danger, #e5484d); }
.km-eintrag.gefahr svg { color: var(--danger, #e5484d); }
.km-eintrag.gefahr:hover { background: rgba(229, 72, 77, 0.12); }
.km-trenner {
  height: 1px;
  margin: 4px 6px;
  background: var(--border);
}

/* ---------- Kein Zoom der ganzen App ---------- */
/* Eine App soll sich nicht aufziehen lassen wie eine Webseite -
   sonst verrutscht beim Tippen alles. Gezoomt wird nur dort, wo es
   gemeint ist: im Bild-Editor und in der Kamera, und die machen
   das selbst (eigene Zwei-Finger-Behandlung bzw. Kamera-Zoom). */
/* Seit der Koerper am Sichtfenster haengt (position: fixed), gibt er
   seine Hintergrundfarbe nicht mehr an die Seite weiter. Um ihn
   herum - und damit hinter Uhr, WLAN und Akku - stand dann das
   Weiss des Browsers. */
html { background: var(--bg); }

html, body {
  touch-action: pan-x pan-y;   /* Wischen ja, Aufziehen nein */
  -ms-touch-action: pan-x pan-y;
}
/* Doppeltipp vergroessert sonst den Bereich unter dem Finger */
button, .chip, li, .msg, .km-eintrag { touch-action: manipulation; }

/* Die Schreibzeile ist kein Verlauf - auf ihr gibt es nichts zu
   scrollen. Ein Wisch darauf schob am iPhone das Sichtfenster ueber
   die Seite; die App zog zwar nach, aber man sah es ruckeln und
   zurueckspringen. Besser, die Geste kommt gar nicht erst zustande.

   Das Feld selbst ist ausgenommen: Ein langer, mehrzeiliger Text
   laeuft darin ueber und muss sich blaettern lassen. */
#send-form, #send-form * { touch-action: none; }
/* Zwei Kennungen, damit diese Regel sicher gewinnt - sonst
   entscheidet die Reihenfolge im Stil. */
#send-form #send-input {
  touch-action: pan-y;
  /* Am Ende des Textes hoert es auf - nicht weiterreichen. */
  overscroll-behavior: contain;
}

/* Ausnahme: Hier ist Zoomen die eigentliche Funktion. Der Editor
   wertet die Finger selbst aus, deshalb muss der Browser hier die
   Gesten komplett durchlassen. */
#ed-buehne-halter, #ed-buehne-halter *,
.story-buehne, .story-buehne *,
#cam-vorschau, #cam-vorschau video {
  touch-action: none;
}

/* ---------- Status: online, abwesend, beschaeftigt ---------- */
/* Vier Zustaende statt zwei. Die Farben sind die gewohnten -
   gruen da, gelb kurz weg, rot nicht stoeren, grau nicht da. */
.dot.idle { background: #f0b232; }
.dot.dnd  { background: #f23f43; }

/* Beschaeftigt bekommt bei Discord einen Balken statt eines
   vollen Kreises. Das unterscheidet es fuer alle, die Rot und
   Gruen schlecht auseinanderhalten - Farbe allein genuegt nicht. */
.dot.dnd::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: 56%; height: 2px;
  border-radius: 2px;
  background: var(--panel, #fff);
  transform: translate(-50%, -50%);
}
.dot.dnd { position: relative; }

/* Abwesend ist ein Mond - also ein Kreis mit einer Delle */
.dot.idle { position: relative; overflow: hidden; }
.dot.idle::after {
  content: '';
  position: absolute;
  left: -28%; top: -28%;
  width: 78%; height: 78%;
  border-radius: 50%;
  background: var(--panel, #fff);
}

/* Die Wahl im Profilmenue */
#menu-status {
  display: flex;
  flex-direction: column;
  padding: 4px 0;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.status-wahl {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 14px;
  border: none;
  background: transparent;
  color: var(--text);
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}
.status-wahl:hover { background: var(--hover); }
.status-wahl.aktiv { background: var(--selected); font-weight: 600; }
.status-wahl .dot { width: 11px; height: 11px; flex-shrink: 0; }
/* Auch der graue Punkt bei "Unsichtbar" muss stehen bleiben, sonst
   rutscht die Zeile ohne Symbol nach links. Die allgemeine Regel
   blendet offline-Punkte aus - diese hier ist genauer. */
.status-wahl .dot.offline { display: block; }

/* Der Punkt an den Bildern in der Mitgliederliste - er sitzt wie
   bei Discord unten rechts AM Bild, mit einem Ring in der Farbe
   des Hintergrunds, damit er sich abhebt. */
.mp-person { position: relative; }
.mp-punkt {
  position: absolute;
  left: 26px; top: 26px;
  width: 12px; height: 12px;
  border-radius: 50%;
  border: 2.5px solid var(--panel);
  box-sizing: content-box;
}

/* Der Anwesenheitspunkt gehoert nur in die Mitgliederliste eines
   Servers. In der Chat- und Kontaktliste steht der Name fuer sich -
   dort war er mehr Unruhe als Auskunft. */
.dot.versteckt { display: none; }

/* In der Mitgliederliste bleibt auch der graue Punkt stehen: Dort
   ist "nicht da" eine Auskunft, die man sehen will - anders als in
   der Chatliste, wo eine allgemeine Regel offline-Punkte ausblendet
   (".dot.offline"). Diese Regel ist genauer und gewinnt deshalb. */
.mp-punkt.dot.offline { display: block; }

/* Die Formen fuer "abwesend" (Mond) und "beschaeftigt" (Balken)
   brauchen einen positionierten Punkt und setzen dafuer
   "position: relative". Genau das nimmt dem Punkt am Bild aber
   seinen Platz - und weil ".dot.idle" genauer ist als
   ".mp-punkt", gewann es. Hier steht beides in einer Regel mit
   zwei Klassen, damit die Lage wieder gilt. */
.mp-punkt.dot { position: absolute; }

/* ---------- Zurueck zur neuesten Nachricht ---------- */
/* Schwebt ueber dem Verlauf, knapp ueber dem Schreibfeld. Wer
   weit oben im Verlauf steht, kommt so mit einem Griff zurueck,
   statt lange zu wischen. */
#btn-runter {
  position: absolute;
  right: 18px;
  /* Auf dem iPhone liegt unten die Home-Leiste. Ohne env() rutscht
     der Knopf dort hinein und wird angeschnitten - die uebrigen
     schwebenden Elemente rechnen sie schon mit ein. */
  bottom: calc(84px + env(safe-area-inset-bottom, 0px));
  z-index: 5;
  width: 40px;
  height: 40px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  transition: opacity 160ms ease, transform 160ms ease;
}
#btn-runter:hover { background: var(--hover); }
/* Es gibt nur einen Chevron nach oben - gedreht zeigt er nach unten.
   Gedreht wird das Symbol, nicht der Knopf: dessen transform
   gehoert der Ein- und Ausblendung. */
#btn-runter svg { transform: rotate(180deg); }
#btn-runter.hidden {
  /* Nicht display:none - so kann es weich verschwinden */
  display: flex;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
}

/* ---------- Wer sitzt im Sprachkanal ---------- */
/* Eingerueckt unter dem Kanal, kleines rundes Bild, gedaempfter
   Name - wie in der Kanalliste von Discord. */
.voice-members {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 7px 0 0 8px;
}
.voice-member {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 6px;
  border-radius: 7px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-dim);
  cursor: pointer;
}
.voice-member:hover { background: var(--border); color: var(--text); }
.voice-member .avatar {
  width: 21px;
  height: 21px;
  min-width: 21px;
  font-size: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}
.vm-name {
  min-width: 0;              /* sonst kuerzt es nicht, sondern draengt */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Wer stumm ist, tritt zurueck - das Symbol steht rechts daneben */
.voice-member svg { flex-shrink: 0; opacity: 0.8; margin-left: auto; }
.voice-member.stumm, .voice-member.taub { opacity: 0.55; }
.voice-member.taub svg, .voice-member.stumm svg { color: var(--danger, #e5484d); opacity: 1; }

/* ---------- Der eigene Status am eigenen Bild ---------- */
/* Unten links, damit er nicht mit dem Ungelesen-Zeichen kollidiert,
   das oben rechts sitzt. */
/* Der Punkt richtet sich am Bild aus, nicht am Knopf - der ist
   am Handy deutlich groesser als das Bild darin. */
.punkt-traeger { position: relative; display: inline-flex; }
/* Das Profilbild ist rund - in der unteren linken ECKE ist gar
   kein Bild mehr. Ein Punkt genau dort haengt sichtbar daneben und
   sieht aus, als klebe er am Knopf. Er sitzt deshalb ein Stueck
   nach innen versetzt, wo er den Kreis wirklich beruehrt. */
/* Das Profilbild ist RUND - in der unteren linken Ecke des
   Quadrats ist gar kein Bild mehr. Ein Punkt genau dort haengt
   sichtbar daneben und wirkt, als klebe er am Knopf. Er sitzt
   deshalb nach innen versetzt, wo er den Kreis wirklich beruehrt. */
.eigen-punkt {
  /* Diese Werte stammen vom Rechner, wo der Punkt richtig sass.
     Sie gelten jetzt fuer beide Groessen - der Traeger ist an
     beiden Stellen genau so gross wie das Bild, also sitzt der
     Punkt auch ueberall gleich. */
  position: absolute;
  left: -1px;
  bottom: -1px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2.5px solid var(--bg);
  box-sizing: content-box;
  pointer-events: none;
}
/* Auch grau muss hier stehen bleiben: Wer sich unsichtbar gemacht
   hat, soll genau das sehen. Die allgemeine Regel blendet
   offline-Punkte sonst aus. */
.eigen-punkt.dot.offline { display: block; }
.eigen-punkt.dot { position: absolute; }

/* Die Zustandszeile im Chat-Kopf kennt jetzt dieselben vier
   Zustaende wie der Punkt - der Text allein ("abwesend") ist die
   Auskunft, die Farbe unterstuetzt sie nur. */
.peer-state.idle { color: #f0b232; }
.peer-state.dnd  { color: #f23f43; }

/* Die Raute vor dem Kanalnamen im Kopf. Sie steht fuer "Textkanal"
   und ersetzt dort das Bild - in jedem Kanal desselben Servers
   waere es ohnehin dasselbe. */
.kanal-raute {
  font-size: 21px;
  font-weight: 400;
  color: var(--text-dim);
  line-height: 1;
}

/* ---------- Meldung bei einer neuen Nachricht ---------- */
/* Oben rechts: Dort verdeckt sie weder die Kanalliste links noch
   die Mitgliederliste rechts, und man sucht Meldungen dort. Sie
   klappt von oben herein und nach ein paar Sekunden wieder hoch. */
#nachricht-banner {
  position: fixed;
  top: 14px;
  right: 18px;
  z-index: 80;
  display: flex;
  align-items: center;
  gap: 11px;
  max-width: 340px;
  padding: 11px 13px;
  border-radius: 13px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.42);
  cursor: pointer;
  transition: transform 280ms cubic-bezier(0.2, 0.9, 0.3, 1.2), opacity 220ms ease;
}
/* Zugeklappt sitzt sie ueber dem oberen Rand - dadurch faehrt sie
   herunter statt einfach aufzutauchen. */
#nachricht-banner.zu {
  transform: translateY(calc(-100% - 20px));
  opacity: 0;
  pointer-events: none;
}
#nachricht-banner:hover { background: var(--hover); }

#nb-bild .avatar { width: 34px; height: 34px; min-width: 34px; font-size: 13px; }
#nb-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
#nb-name {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#nb-teaser {
  font-size: 12.5px;
  color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#nb-zu {
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px;
  padding: 0;
  flex-shrink: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
#nb-zu:hover { background: var(--border); color: var(--text); }

/* Am Handy gibt es dafuer die Benachrichtigungen des Geraets -
   ein zweites Banner obendrauf waere doppelt. */
@media (max-width: 700px) {
  #nachricht-banner { display: none; }
}

/* ---------- Angeheftete Server ---------- */
/* Sie stehen ohnehin oben - ein kleiner Reissnagel sagt, warum.
   Ohne ihn waere die Reihenfolge willkuerlich. */
/* Kein Emoji: Das zeichnet jedes Geraet anders - am Handy sah es
   aus wie ein fremdkoerperliches Bildchen. Stattdessen dasselbe
   gezeichnete Zeichen wie in der Schmalleiste. */
.liste-pin {
  display: inline-flex;
  align-items: center;
  margin-left: 7px;
  color: var(--accent);
  vertical-align: middle;
}
.liste-pin svg { width: 12px; height: 12px; }
/* Die Pinnadel sitzt oben rechts am Bild. Bewusst ein eigenes
   Element und kein ::before - daran haengt schon der Balken, der
   den offenen Server anzeigt. Beides an einem Pseudoelement
   heisst: eines von beiden verschwindet. */
.rail-pin {
  position: absolute;
  /* Nicht ueber den oberen Rand hinaus: Die Leiste darueber
     schneidet oben und unten ab (clip-path), damit sie beim
     Zuklappen nichts stehen laesst. Ein negativer Wert waere hier
     also abgeschnitten - die Nadel sitzt deshalb knapp innerhalb. */
  top: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--panel);
  color: var(--accent);
  box-shadow: 0 0 0 2px var(--bg);
  pointer-events: none;
}
.rail-pin svg { width: 10px; height: 10px; }

/* ---------- Mitgliederliste am Handy ---------- */
/* Dort legt sie sich ueber den Chat, statt daneben zu stehen -
   fuer beides ist kein Platz. Damit man wieder herauskommt, traegt
   sie oben einen Pfeil, und ein Tipp daneben schliesst sie auch. */
.mp-kopf {
  display: none;
  align-items: center;
  gap: 10px;
  padding: 4px 2px 10px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.mp-kopf-titel {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.mp-zurueck {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.mp-zurueck:hover { background: var(--hover); }

@media (max-width: 700px) {
  .mp-kopf { display: flex; }
  /* Lage und Ein-/Ausfahren stehen schon weiter oben - hier nur
     der abgedunkelte Hintergrund: Er zeigt, dass darunter der Chat
     weitergeht, und schliesst beim Tippen. */
  body.mp-offen::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 23;
    background: rgba(0, 0, 0, 0.45);
  }
}
/* ---------- Kontakte: nach Buchstaben unterteilt ---------- */
/* Gilt auf beiden Groessen - bei vielen Kontakten findet man so
   schneller, wen man sucht. */
/* Die Buchstaben sind Ueberschriften, keine Eintraege - ohne die
   Kachel, den Rahmen und die Abstaende der Listenelemente. Der
   Selektor nennt die Liste mit, sonst gewinnt deren eigene Regel. */
#contact-list li.kontakt-buchstabe {
  padding: 14px 6px 4px;
  margin: 0;
  min-height: 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  cursor: default;
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
}
#contact-list li.kontakt-buchstabe:hover { background: none; }
.kontakt-buchstabe.hidden { display: none; }

.kontakt-suche { display: none; padding: 8px 12px 4px; }
.kontakt-suche input {
  width: 100%;
  padding: 9px 12px;
  border-radius: 10px;
  border: 1px solid var(--input-border);
  background: var(--bg);
  color: var(--text);
  font-size: 13.5px;
  outline: none;
}
.kontakt-suche input:focus { border-color: var(--accent); }
#contact-empty { padding: 18px 16px; color: var(--text-dim); font-size: 13.5px; }

/* Im Kontakte-Bereich: Suche zeigen, Chatliste und Gruppen weg */
#sidebar.mode-contacts .kontakt-suche { display: block; }
/* Kontaktliste und ihre Ueberschrift sind grundsaetzlich
   ausgeblendet (".contacts-title, #contact-list { display: none }") -
   am Handy holt eine Media-Query sie im Kontakte-Bereich wieder
   hervor. Am Rechner gab es diese Gegenregel nicht: Die Eintraege
   standen im Dokument, waren aber unsichtbar. */
#sidebar.mode-contacts .contacts-title { display: flex; }
#sidebar.mode-contacts #contact-list { display: block; }
#sidebar.mode-contacts #vorschlag-kopf:not(.hidden) { display: flex; }
#sidebar.mode-contacts #vorschlag-liste { display: block; }
/* Der Hinweis der leeren Chatliste gehoert zur Chatliste - ohne
   ihn hier stand er auch im Kontakte-Tab (selbst gebaut, selbst
   gefunden). */
#sidebar.mode-contacts #chat-list,
#sidebar.mode-contacts #chat-empty,
#sidebar.mode-contacts #chat-filters,
#sidebar.mode-contacts .groups-title,
#sidebar.mode-contacts #group-list { display: none; }

/* ---------- Wer gerade redet ---------- */
/* Gruener Ring um das Bild, wie bei Discord. Er wird eingeblendet
   statt ein- und ausgeschaltet: Sonst zuckt er bei jeder Silbe. */
.voice-member .avatar {
  box-shadow: 0 0 0 0 rgba(111, 207, 151, 0);
  transition: box-shadow 140ms ease;
}
.voice-member.redet .avatar {
  box-shadow: 0 0 0 2px #6fcf97;
}
.voice-member.redet .vm-name { color: var(--text); }

/* ---------- Schieberegler im Rechtsklick-Menue ---------- */
/* Fuer die Lautstaerke einer Person im Sprachkanal. Er schliesst
   das Menue nicht - man schiebt hin und her und hoert dabei zu. */
.km-regler { padding: 8px 10px 10px; }
.km-regler-kopf {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 7px;
  font-size: 13.5px;
  color: var(--text);
}
.km-regler-wert {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;   /* springt nicht beim Ziehen */
}
.km-regler input[type=range] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  outline: none;
  cursor: pointer;
}
.km-regler input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  cursor: grab;
  border: none;
}
.km-regler input[type=range]::-webkit-slider-thumb:active { cursor: grabbing; }
.km-regler input[type=range]::-moz-range-thumb {
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: none;
  cursor: grab;
}

/* ---------- Thema eines Kanals ---------- */
/* Steht hinter dem Namen, durch einen senkrechten Strich getrennt.
   Bewusst zurueckhaltend: Der Name ist die Hauptsache, das Thema
   die Erlaeuterung. */
.kanal-thema-strich {
  display: inline-block;
  width: 1px;
  height: 16px;
  margin: 0 12px;
  background: var(--border);
  vertical-align: middle;
}
.kanal-thema {
  font-size: 13.5px;
  font-weight: 400;
  color: var(--text-dim);
  vertical-align: middle;
}
/* Am Handy ist kein Platz fuer beides - dort zaehlt der Name */
@media (max-width: 700px) {
  .kanal-thema, .kanal-thema-strich { display: none; }
}

/* ---------- Untermenues im Rechtsklick-Menue ---------- */
/* Klappen zur Seite auf, nicht nach unten - so bleibt die
   Hauptliste kurz. Dasselbe Muster wie im Mitglieder-Menue. */
.km-unter { position: relative; }
.km-pfeil > span:first-of-type { flex: 1; }
.km-pfeil-zeichen {
  color: var(--text-dim);
  font-size: 16px;
  line-height: 1;
}
.km-unterinhalt {
  display: none;
  position: absolute;
  /* Zwei Pixel Ueberlappung: Sonst reisst der Zeigerkontakt ab,
     wenn die Maus vom Eintrag zum Untermenue wandert. */
  left: calc(100% - 2px);
  top: -5px;
  min-width: 180px;
  padding: 5px;
  border-radius: 11px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.36);
  z-index: 1;
}
.km-unter:hover .km-unterinhalt,
.km-unter.offen .km-unterinhalt { display: block; }

/* Kein Platz nach rechts? Dann nach links aufklappen. */
.kmenue.eng .km-unterinhalt { left: auto; right: calc(100% - 2px); }

/* ---------- Anruf verkleinern ---------- */
/* Der Anruf laeuft weiter, nimmt aber nur noch eine Leiste ein -
   so kann man daneben schreiben, ohne aufzulegen. */
#btn-call-min {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 34px;
  padding: 0 13px;
  font-size: 13px;
  font-weight: 600;
  border: none;
  border-radius: 17px;
  background: var(--bg-soft, rgba(127, 127, 127, 0.14));
  color: var(--text-dim);
  cursor: pointer;
}
#btn-call-min:hover { background: rgba(127, 127, 127, 0.26); color: var(--text); }
/* Nach unten heisst kleiner, nach oben wieder gross. Ein Pfeil, gedreht. */
#btn-call-min.runter svg { transform: rotate(180deg); }

#call-overlay.klein {
  /* Aus dem Vollbild wird eine Leiste. Sie sitzt ueber dem
     Schreibfeld, nicht darauf - sonst verdeckt sie genau das, wofuer
     man verkleinert hat. */
  inset: auto 18px calc(96px + env(safe-area-inset-bottom, 0px)) auto;
  width: min(320px, 88vw);
  height: auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45);
  cursor: pointer;
  padding: 10px 12px;
}
#call-overlay.klein .call-box {
  /* Zwei Spalten: links Name und Stand untereinander, rechts die
     Knoepfe. Nebeneinander gingen beide Texte nicht aus - fuer sie
     zusammen blieben 90 Pixel, und "Eingehender Anruf" braucht
     allein 84. */
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0 10px;
  padding: 0;
  background: none;
  box-shadow: none;
  width: 100%;
}
#call-overlay.klein #call-videos,
#call-overlay.klein #call-avatar { display: none; }
/* Name und Stand untereinander, damit beides lesbar bleibt */
#call-overlay.klein #call-name {
  font-size: 13.5px; font-weight: 600; margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#call-overlay.klein #call-status {
  font-size: 11.5px; color: var(--text-dim); margin: 2px 0 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Die beiden Textzeilen teilen sich den Platz links - und geben ihn
   wieder her, wenn die Knoepfe ihn brauchen.

   Hier stand einmal flex: 0 0 auto, also "nicht wachsen, nicht
   schrumpfen". Ein langer Name nahm damit seine volle Breite (208
   Pixel gemessen) und schob die Knoepfe aus der Leiste: Kamera,
   Lautsprecher, Auflegen und Wiederherstellen lagen bei 374 bis 524,
   der Bildschirm ist 375 breit. Erreichbar war nur das Mikrofon -
   auflegen konnte man nicht mehr.

   Das Kuerzen war zwei Zeilen darueber laengst angeordnet, konnte
   aber nie greifen: Was nicht schrumpfen darf, wird auch nicht
   gekuerzt.

   Beide stehen jetzt in der linken Spalte untereinander und haben
   dort die volle Breite - vorher teilten sie sich eine Zeile und
   kuerzten sich gegenseitig zu "Maximili..." neben "V...". */
#call-overlay.klein .call-box > #call-name { grid-column: 1; grid-row: 1; min-width: 0; }
#call-overlay.klein .call-box > #call-status { grid-column: 1; grid-row: 2; min-width: 0; }
#call-overlay.klein .call-buttons {
  grid-column: 2; grid-row: 1 / span 2;
  gap: 6px; flex-shrink: 0;
}
#call-overlay.klein .call-buttons button { width: 32px; height: 32px; font-size: 14px; }
/* Der Verkleinern-Knopf wandert nach rechts zu den anderen */
#call-overlay.klein #btn-call-min {
  /* Ganz rechts, ueber beide Zeilen - im Gitter zaehlt "order"
     nicht mehr, er bekommt seine eigene Spalte. */
  position: static; grid-column: 3; grid-row: 1 / span 2;
  /* Feste Breite: Als Gitter-Kind zieht kein flex mehr, und die
     Spalte quetschte ihn auf 16 Pixel.*/
  width: 28px; height: 28px;
  padding: 0; border-radius: 50%;
  background: transparent; color: var(--text-dim);
}
/* In der Leiste ist kein Platz fuer das Wort */
#call-overlay.klein #btn-call-min span { display: none; }

/* Beim Ziehen: kein Textmarkieren, und der Zeiger zeigt es an */
#call-overlay.klein { cursor: grab; touch-action: none; }
#call-overlay.klein.zieht { cursor: grabbing; user-select: none; }

/* ---------- Geschickte Audio- und Videodateien ---------- */
/* Der Dateiname ueber dem Player: Bei einer Sprachnachricht weiss
   man, was kommt - bei einer Datei aus dem Anhang-Menue nicht. */
.medien-datei { display: flex; flex-direction: column; gap: 5px; }
.md-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-dim);
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Im kleinen Chatfenster: nur das Wort, etwas zurueckgenommen */
/* "Audio", "Foto": im kleinen Fenster wird nichts abgespielt,
   dort steht nur, WAS gekommen ist. Als kleine Marke statt kursivem
   Grau - so liest es sich als Angabe und nicht als halber Satz. */
.po-medien {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px 2px 6px;
  border-radius: 8px;
  background: rgba(127, 127, 127, 0.18);
  font-size: 12.5px;
  font-style: italic;
}
/* Emoji werden NIE kursiv. Sie haben keine schraege Schnittform -
   der Browser kippt sie nur schief, und das sieht kaputt aus. */
.zeichen, .emoji, .msg.deleted .zeichen {
  font-style: normal;
  display: inline-block;
}

/* ---------- Anruffenster schwebt ---------- */
/* Beim Sprachanruf liegt kein Vorhang mehr ueber der App: Man kann
   waehrend des Gespraechs weiterlesen und in anderen Chats
   nachsehen. Nur das Fenster selbst nimmt Klicks an.
   Beim Videoanruf bleibt es beim Vollbild - da SOLL das Bild
   den Schirm fuellen. */
#call-overlay:not(.video) {
  background: transparent;
  pointer-events: none;
}
#call-overlay:not(.video) .call-box,
#call-overlay.klein { pointer-events: auto; }

/* Verschieben: ueberall im Fenster anfassen, nur nicht auf Knoepfen */
#call-overlay:not(.video):not(.klein) .call-box { cursor: grab; touch-action: none; }
#call-overlay:not(.video):not(.klein) .call-box.zieht { cursor: grabbing; user-select: none; }
#call-overlay .call-box button { cursor: pointer; }

/* ---------- Formatierung im Text ---------- */
/* *fett* _kursiv_ ~durchgestrichen~ `code` - wie bei WhatsApp.
   Umgewandelt wird erst beim ANZEIGEN; gespeichert und verschickt
   werden die Zeichen mit, damit der Text bleibt, was er ist. */
.msg strong { font-weight: 700; }
.msg em { font-style: italic; }
.msg s { opacity: 0.75; }
.msg code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.92em;
  padding: 1px 5px;
  border-radius: 5px;
  background: rgba(127, 127, 127, 0.16);
}
/* Links in der Blase: unterstrichen, Farbe der Blase folgend */
.msg a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  word-break: break-word;
}
.msg a:hover { text-decoration-thickness: 2px; }

/* "Entwurf:" in der Chatliste - in Warnfarbe, damit man sieht,
   wo noch etwas Halbfertiges liegt. */
.li-entwurf { color: var(--danger); font-weight: 600; }

/* Angehefteter Chat: kleine Nadel rechts, zurueckhaltend. */
.li-nadel {
  display: inline-flex;
  align-items: center;
  color: var(--text-dim);
  opacity: 0.75;
}

/* ---------- Gemerkte Nachrichten ---------- */
/* Kleiner Stern an der Blase: Er sagt "die findest du wieder",
   mehr nicht - deshalb zurueckhaltend und ausserhalb des Textes. */
.msg.gemerkt::before {
  content: '★';
  position: absolute;
  top: 4px;
  right: 7px;
  font-size: 11px;
  line-height: 1;
  color: var(--accent, #b9a7ff);
  opacity: 0.85;
  pointer-events: none;
}
.msg { position: relative; }

.gemerkt-karte {
  position: relative;
  padding: 10px 34px 10px 12px;
  margin-bottom: 8px;
  border-radius: 12px;
  background: var(--hover);
  border: 1px solid var(--border);
}
.gk-kopf {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
  font-size: 12px;
}
.gk-woher { font-weight: 600; color: var(--text); }
.gk-zeit { color: var(--text-dim); flex-shrink: 0; }
.gk-text { font-size: 14px; color: var(--text); word-break: break-word; }
.gk-weg {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
.gk-weg:hover { background: rgba(127, 127, 127, 0.2); color: var(--text); }

/* ---------- Link-Vorschau ---------- */
/* Die Karte steckt komplett IN der Nachricht - Bild als Datenblock,
   nichts wird nachgeladen. Deshalb sieht sie auch offline noch so
   aus wie beim Verschicken. */
.link-karte {
  display: block;
  margin-top: 6px;
  border-radius: 10px;
  overflow: hidden;
  background: rgba(127, 127, 127, 0.13);
  text-decoration: none !important;
  color: inherit;
  max-width: 320px;
}
.link-karte:hover { background: rgba(127, 127, 127, 0.2); }
.lk-bild {
  display: block;
  width: 100%;
  max-height: 170px;
  object-fit: cover;
  cursor: pointer;
}
.lk-text { padding: 8px 10px; }
.lk-host {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  opacity: 0.7;
  margin-bottom: 2px;
}
.lk-titel {
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.25;
  /* Hoechstens zwei Zeilen - eine Karte, keine zweite Nachricht */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.lk-text-klein {
  font-size: 12px;
  opacity: 0.8;
  margin-top: 3px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Ablaufende Nachrichten: Der Knopf faellt nur auf, wenn eine Frist
   laeuft - sonst ist er einer von vielen im Kopf. */
#btn-ablauf.aktiv { color: var(--accent, #b9a7ff); }

/* Aus dem schwebenden Fenster zu einer Nachricht gesprungen: Sie
   leuchtet kurz auf, sonst sucht man die Stelle selbst. */
.msg.hervor {
  animation: hervor-blitz 1.6s ease;
}
@keyframes hervor-blitz {
  0%, 100% { box-shadow: 0 1px 3px rgba(45, 49, 66, 0.07); }
  25%      { box-shadow: 0 0 0 3px var(--accent, #b9a7ff); }
}
/* Die Medien-Marke im kleinen Fenster fuehrt in den Chat */
.po-medien { cursor: pointer; }
.po-medien:hover { background: rgba(127, 127, 127, 0.3); }

/* ---------- Umfragen ---------- */
/* Die Karte sitzt in der Blase. Der Balken liegt HINTER dem Text,
   damit die Zahl nicht allein steht und man das Verhaeltnis sieht,
   ohne rechnen zu muessen. */
.umfrage { margin-top: 4px; min-width: 210px; }
.uf-frage { font-weight: 600; margin-bottom: 2px; }
.uf-art {
  font-size: 11.5px;
  opacity: 0.65;
  margin-bottom: 7px;
}
.uf-option {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  margin-bottom: 5px;
  padding: 7px 10px;
  border: 1px solid var(--bubble-edge, var(--border));
  border-radius: 10px;
  background: transparent;
  color: inherit;
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}
.uf-option:hover { border-color: var(--accent, #b9a7ff); }
.uf-option.gewaehlt { border-color: var(--accent, #b9a7ff); font-weight: 600; }
.uf-balken {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  background: rgba(127, 127, 127, 0.22);
  transition: width 260ms ease;
  pointer-events: none;
}
.uf-option.gewaehlt .uf-balken { background: rgba(185, 167, 255, 0.28); }
.uf-text { position: relative; flex: 1; word-break: break-word; }
.uf-zahl { position: relative; opacity: 0.75; font-variant-numeric: tabular-nums; }
.uf-fuss { font-size: 11.5px; opacity: 0.65; margin-top: 2px; }

/* ---- Umfrage erstellen ---- */
#umfrage-modal {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(22, 25, 36, 0.55);
}
#umfrage-modal.hidden { display: none; }
#umfrage-box {
  width: min(400px, 92vw);
  max-height: 86vh;
  overflow-y: auto;
  padding: 18px;
  border-radius: 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.4);
}
#umfrage-kopf { font-size: 16px; font-weight: 600; margin-bottom: 12px; }
#umfrage-frage, .uo-zeile input {
  width: 100%;
  padding: 9px 11px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--hover);
  color: var(--text);
  font-size: 14px;
}
#umfrage-frage { margin-bottom: 12px; }
.uo-zeile { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.uo-weg {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px;
  flex-shrink: 0;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
.uo-weg:hover { background: var(--hover); color: var(--text); }
#umfrage-mehr { margin: 2px 0 12px; }
#umfrage-mehrfach {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
  font-size: 13.5px;
  cursor: pointer;
}
#umfrage-knoepfe { display: flex; justify-content: flex-end; gap: 8px; }

/* Preisspanne im Marktplatz-Filter: zwei Felder mit Gedankenstrich
   dazwischen, in einer Zeile - so liest es sich als EINE Angabe. */
#mf-price-box {
  display: flex;
  align-items: center;
  gap: 8px;
}
#mf-price-box input {
  flex: 1;
  min-width: 0;
  padding: 9px 11px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--hover);
  color: var(--text);
  font-size: 14px;
}
#mf-price-bis { color: var(--text-dim); flex-shrink: 0; }
#market-sort { width: 100%; }

/* Reserviert: gelb statt rot. Es ist kein Schlussstrich wie
   "verkauft", sondern ein Zwischenstand - die Anzeige bleibt
   sichtbar und kann zurueckkommen. */
.ad-sold-tag.ad-reserved-tag { background: #d9a441; color: #2a2013; }
#ad-d-sold.is-reserved { background: #d9a441; color: #2a2013; }
#mf-hide-reserved {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  width: 100%;
  margin: 10px 0 14px;
  font-size: 14px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
/* Das Kaestchen zeichnet der Browser sonst weiss - im Dunkelmodus
   reisst das ein Loch. Also selbst zeichnen, wie die Auswahlfelder. */
#mf-hide-reserved input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin: 0;
  border: 1px solid var(--input-border);
  border-radius: 6px;
  background: var(--hover);
  cursor: pointer;
}
#mf-hide-reserved input[type="checkbox"]:checked {
  background-color: var(--accent);
  border-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
}
#mf-hide-reserved span { flex: 1; }

/* Verkaeuferzeile: seit wann dabei, und wie viele Anzeigen noch.
   Beides zurueckhaltend - es soll den Namen ergaenzen, nicht mit
   ihm konkurrieren. */
.ad-seller-since {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 1px;
}
.ad-seller-mehr {
  margin-top: 4px;
  padding: 0;
  border: none;
  background: none;
  color: var(--accent, #b9a7ff);
  font-size: 12.5px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.ad-seller-mehr:hover { text-decoration: underline; }

/* Zahlen zur eigenen Anzeige. Zurueckhaltend: eine Auskunft fuer
   den Verkaeufer, keine Beliebtheitsanzeige - fremde sehen sie
   ohnehin nicht. */
#ad-stats {
  margin: 10px 0 2px;
  font-size: 12.5px;
  color: var(--text-dim);
}
#ad-stats.hidden { display: none; }

/* "Liste leeren" ueber dem Verlauf. Steht ueber der ganzen Breite,
   damit es nicht wie eine Anzeigenkarte aussieht. */
.zuletzt-leeren {
  grid-column: 1 / -1;
  justify-self: start;
  margin-bottom: 4px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text-dim);
  font-size: 12.5px;
  cursor: pointer;
}
.zuletzt-leeren:hover { color: var(--danger); text-decoration: underline; }

/* Gespeicherte Suchen im Filter-Blatt: Name antippen wendet sie an,
   Glocke schaltet die Meldung, X wirft sie weg. */
.gs-zeile {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 5px;
}
.gs-name {
  flex: 1;
  min-width: 0;
  padding: 8px 11px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--hover);
  color: var(--text);
  font-size: 13.5px;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}
.gs-name:hover { border-color: var(--accent, #b9a7ff); }
.gs-glocke, .gs-weg {
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  flex-shrink: 0;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
.gs-glocke.an { color: var(--accent, #b9a7ff); }
.gs-glocke:hover, .gs-weg:hover { background: var(--hover); }
.gs-weg:hover { color: var(--danger); }
#btn-mf-save { width: 100%; margin-bottom: 10px; }

/* ---------- Bewertungen ---------- */
.ad-seller-bew {
  margin-top: 4px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text-dim);
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
}
.ad-seller-bew:hover { color: var(--text); text-decoration: underline; }

.bew-kasten { max-width: 460px; width: min(460px, 92vw); }
.bew-kopf { font-size: 13.5px; color: var(--text-dim); margin-bottom: 12px; }
.bew-form {
  padding: 12px;
  margin-bottom: 14px;
  border-radius: 12px;
  background: var(--hover);
}
.bew-wahl { display: flex; gap: 6px; margin-bottom: 8px; }
.bew-knopf {
  flex: 1;
  padding: 8px 6px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  font-size: 13px;
  cursor: pointer;
}
.bew-knopf.aktiv { border-color: var(--accent); background: var(--selected); font-weight: 600; }
.bew-form textarea {
  width: 100%;
  padding: 9px 11px;
  margin-bottom: 8px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel);
  color: var(--text);
  font-size: 13.5px;
  resize: vertical;
}
.bew-liste { max-height: 40vh; overflow-y: auto; margin-bottom: 12px; }
.bew-zeile {
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
}
.bew-zeile:last-child { border-bottom: none; }
.bew-oben { display: flex; align-items: center; gap: 7px; font-size: 13px; }
.bew-zeichen { font-size: 15px; }
.bew-von { font-weight: 600; flex: 1; }
.bew-datum { color: var(--text-dim); font-size: 11.5px; }
.bew-weg {
  display: flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0;
  border: none; border-radius: 50%;
  background: transparent; color: var(--text-dim); cursor: pointer;
}
.bew-weg:hover { background: var(--hover); color: var(--danger); }
.bew-text { font-size: 13.5px; margin-top: 3px; word-break: break-word; }
.bew-anzeige { font-size: 11.5px; color: var(--text-dim); margin-top: 2px; }

/* Mehrere Nachrichten am Stueck von derselben Person ruecken
   zusammen und bilden einen Block: Der Name steht nur ueber der
   ersten, der Zipfel nur an der letzten. Sonst liest sich ein
   dreiteiliger Gedanke wie drei Wortmeldungen. */
.msg.folgt { margin-top: -5px; }
.msg.mine.hat-folger { border-bottom-right-radius: 18px; }
.msg.theirs.hat-folger { border-bottom-left-radius: 18px; }

/* ---------- Suche in diesem Chat ---------- */
/* Die Leiste haengt unter der Kopfzeile - wie die angepinnte
   Nachricht. In der Reihenfolge des Dokuments zu bleiben half
   nicht: Die Kopfzeile hat margin-bottom:auto, damit alle weiteren
   Leisten (Bearbeiten, Antworten) nach UNTEN ans Eingabefeld
   rutschen. Die Suche gehoert aber nach oben, also nimmt sie
   dieselbe Machart wie #pinned-bar. */
#chat-suche-leiste {
  position: absolute;
  top: 65px; left: 0; right: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--glass-bg);
  backdrop-filter: blur(18px) saturate(1.25);
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
  z-index: 7;
}
#chat-suche-leiste.hidden { display: none; }
#chat-suche-feld {
  flex: 1;
  min-width: 0;
  padding: 8px 12px;
  border-radius: 10px;
  border: 1px solid var(--input-border);
  background: var(--hover);
  color: var(--text);
  font-size: 14px;
}
#chat-suche-stand {
  font-size: 12.5px;
  color: var(--text-dim);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
#chat-suche-runter.runter svg { transform: rotate(180deg); }
#chat-suche-mehr { white-space: nowrap; font-size: 12.5px; padding: 7px 11px; }

/* Treffer: alle leicht hervorgehoben, der aktuelle deutlich. So
   sieht man auf einen Blick, wie oft das Wort vorkommt - und wo man
   gerade steht. */
.msg.treffer { box-shadow: 0 0 0 1px var(--accent, #b9a7ff); }
.msg.treffer-aktiv {
  box-shadow: 0 0 0 2px var(--accent, #b9a7ff);
  background: var(--bubble-sheen), var(--selected);
}

/* Ist die Suche offen, kommt oben eine Leiste dazu (51 px). Der
   Verlauf braucht dann mehr Polster, damit die oberste Nachricht
   nicht dahinter klebt - und eine angepinnte Nachricht rutscht
   darunter statt sich zu ueberlagern. */
#chat-area.suche-offen #messages { padding-top: 129px; }
#chat-area.suche-offen #pinned-bar { top: 116px; }

/* Nachrichten, die nur aus Emoji bestehen: keine Blase, grosse
   Zeichen. Es ist eine Geste, kein Satz - und in Textgroesse in
   einer Blase ginge sie unter. */
.msg.nur-emoji {
  background: none;
  border-color: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  padding: 2px 6px;
}
.emoji-gross { font-size: 34px; line-height: 1.15; }
.emoji-einzeln { font-size: 46px; }
/* Die Uhrzeit bleibt klein und ruecht naeher heran */
.msg.nur-emoji .time { margin-top: 1px; }

/* Chat ohne Nachrichten: ein ruhiger Hinweis in der Mitte statt
   einer leeren Flaeche. Er sagt auch gleich, warum es sich lohnt. */
.chat-leer {
  margin: auto;
  padding: 22px 26px;
  max-width: 320px;
  border-radius: 16px;
  text-align: center;
  background: var(--glass-bg);
  backdrop-filter: blur(18px) saturate(1.25);
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
}
.chat-leer-titel { font-weight: 600; margin-bottom: 4px; }
.chat-leer-text { font-size: 13.5px; color: var(--text-dim); line-height: 1.4; }

/* Zahl am Knopf "nach unten": So viele Nachrichten sind gekommen,
   waehrend man Aelteres gelesen hat. */
.runter-zahl {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 9px;
  background: var(--danger);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}
/* Hier stand einmal "#btn-runter { position: relative; }", damit die
   Zahl darueber einen Bezugspunkt hat. Den gab es laengst: Der Knopf
   ist weiter oben schon "absolute", und das ist ebenfalls einer.
   Die Zeile hat dafuer die Verankerung ueberschrieben - aus "18
   Pixel vom rechten Rand" wurde "18 Pixel nach links geschoben", und
   am Handy lag der Knopf damit ausserhalb des Bildes (linke Kante
   bei -18). Bitte nicht wieder einfuegen. */

/* Der Tag schwebt beim Blaettern oben mit. Sieht aus wie ein
   Datums-Trenner, sitzt aber fest unter der Kopfzeile. */
#datum-schwebend {
  position: absolute;
  top: 74px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: 12px;
  color: var(--text-dim);
  background: var(--glass-bg);
  backdrop-filter: blur(18px) saturate(1.25);
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
  pointer-events: none;
  transition: opacity 200ms ease;
}
#datum-schwebend.hidden { display: block; opacity: 0; }
/* Steht die Suche offen, rutscht das Schild darunter */
#chat-area.suche-offen #datum-schwebend { top: 126px; }

/* Die Uhrzeit einer geloeschten Nachricht war kursiv mitgezogen -
   eine Zeit in Schraegschrift liest sich wie ein Zitat. */
.msg.deleted .time { font-style: normal; }

/* Der Mehr-Knopf gehoert dem Handy: Am Rechner ist Platz fuer
   alle Knoepfe einzeln, dort waere er nur ein Umweg. */
#btn-chat-mehr { display: none; }
@media (max-width: 700px) {
  #btn-chat-mehr:not(.hidden) { display: flex; }
  /* Was in den Mehr-Knopf gewandert ist, verschwindet aus der
     Zeile - sonst blieben fuer den Namen 22 Pixel. */
  #btn-chat-suche, #btn-mute-chat, #btn-ablauf, #btn-members,
  #btn-add-member { display: none; }
  /* Und der Name bekommt, was frei wird */
  #chat-title { flex: 1; min-width: 0; overflow: hidden;
                text-overflow: ellipsis; white-space: nowrap; }
}

/* Tippflaechen am Handy -----------------------------------
   Am Rechner zielt man mit dem Mauszeiger, da genuegen 34 px.
   Mit dem Daumen trifft man das nicht zuverlaessig - Apple
   nennt 44 px, Google 48. In der Kopfzeile ist jetzt Platz
   dafuer, seit das Selten-Gebrauchte im Mehr-Knopf sitzt. */
@media (max-width: 700px) {
  #chat-header button.small {
    width: 40px;
    height: 40px;
  }
}

/* Kein Hineinzoomen beim Antippen -------------------------
   Safari am iPhone zoomt in JEDES Eingabefeld hinein, dessen
   Schrift kleiner als 16 px ist - und zoomt danach nicht von
   allein wieder heraus. Die Seite steht dann schief, bis man
   sie von Hand zurueckzieht.

   Das Nachrichtenfeld hatte darum schon 16 px. Alle anderen
   zwanzig Felder (Suche, Marktplatz-Filter, Anzeigenformular,
   Umfrage ...) hatten 13,5 bis 15 px. Am Handy bekommen sie
   alle 16 px - am Rechner bleibt es beim feineren Satz.

   Das !important ist hier noetig und kein Schlendrian: Fast alle
   dieser Felder werden ueber ihre ID angesprochen (#market-zip,
   #contact-search ...), und eine ID schlaegt jede Regel, die nur
   "input" nennt. Ohne !important griffe die Regel bei genau
   einem der zwanzig Felder. */
@media (max-width: 700px) {
  input, textarea, select { font-size: 16px !important; }
}

/* Die Zeile der Chat-Suche ist am Handy die einzige Stelle,
   an der man mit dem Daumen zwischen Treffern springt -
   26 px hohe Pfeile trifft man dabei nicht zuverlaessig. */
@media (max-width: 700px) {
  #chat-suche-leiste button { min-height: 38px; }
}

/* Suchzeile am Handy: der Knopf bekommt eine eigene Zeile ---
   Sobald "Ältere durchsuchen" auftaucht, teilten sich Feld,
   Trefferzaehler, drei Pfeile UND der Knopf eine Zeile von
   375 px. Fuer das Eingabefeld blieben davon 47 px - man tippt
   dann in einen Schlitz, in dem drei Zeichen stehen.

   Am Rechner ist die Zeile breit genug, dort bleibt alles
   nebeneinander. */
@media (max-width: 700px) {
  #chat-suche-leiste { flex-wrap: wrap; }
  /* Grundbreite 0, damit das Feld nachgibt: Mit "auto" schob es
     das Schliesskreuz in eine eigene dritte Zeile. */
  #chat-suche-feld { flex: 1 1 0; min-width: 0; }
  #chat-suche-mehr:not(.hidden) {
    flex: 1 0 100%;      /* eigene Zeile, ueber die volle Breite */
    order: 9;            /* und zwar unter den Pfeilen */
  }
}

/* Warum bleibt der Verlauf zu? ------------------------------
   Die Leiste bleibt beim Scrollen oben stehen. Wer nach unten
   wischt, um zu sehen, WAS alles verschlossen ist, soll den
   Grund nicht aus den Augen verlieren - und der Knopf, der es
   behebt, soll in Reichweite bleiben. */
.schluessel-not {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 10px;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--glass-strong);
  border: 1px solid var(--border);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .08);
  font-size: 13.5px;
  line-height: 1.4;
}
.schluessel-not-text { flex: 1 1 220px; }
.schluessel-not-knopf {
  /* Eigener Flex-Behaelter: Als blosses Flex-Kind wurde er von
     seiner Zeile auf Inhaltsgroesse gestellt, und min-height blieb
     wirkungslos (gemessen 37,24 statt 38). */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 7px 14px;
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}
.schluessel-not-knopf:hover { filter: brightness(1.08); }

/* Das Kreuz sitzt rechts aussen, unaufdringlich - es raeumt eine
   Erklaerung weg, es ist keine Handlung am Chat. */
.schluessel-not-zu {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
}
.schluessel-not-zu:hover { background: var(--hover); color: var(--text); }
@media (max-width: 700px) {
  .schluessel-not-zu { width: 38px; height: 38px; }
}

/* Fehlertafel im Chat: dieselbe Karte wie beim leeren Chat, nur
   mit einem Knopf darunter. */
.chat-fehler-knopf {
  margin-top: 12px;
  padding: 8px 18px;
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.chat-fehler-knopf:hover { filter: brightness(1.08); }

/* Zeilenumbrueche bleiben stehen ---------------------------
   Wer eine Einkaufsliste schickt, meint die Zeilen auch so.
   Vorher galt white-space: normal, und der Browser faltete
   jeden Umbruch zu einem Leerzeichen zusammen - aus acht
   Zeilen wurde eine. Im Text standen sie die ganze Zeit drin,
   sie wurden nur nicht gezeigt.

   pre-wrap statt pre: Lange Woerter sollen weiter umbrechen
   (overflow-wrap: break-word erbt die Blase). */
.msg-text, .po-text { white-space: pre-wrap; }

/* Unterwegs, aber noch nicht bestaetigt --------------------
   Blasser als eine bestaetigte Nachricht, mit einer kleinen Uhr
   statt eines Hakens. Verschwindet wieder, sobald die echte
   Nachricht vom Server zurueckkommt. */
/* Die Blaesse haengt an den Kindern, nicht an der Blase: .msg
   traegt animation: msg-in ... both, und deren Schluss-Bild
   (opacity: 1) schlaegt jede normale Regel auf .msg. An .msg-text
   und .time laeuft keine Animation - dort greift sie. */
.msg.wartet .msg-text, .msg.wartet .time { opacity: 0.6; }
.sende-stand { display: inline-flex; align-items: center; margin-left: 4px; }
.sende-stand svg { width: 12px; height: 12px; }

/* Nicht angekommen: Die Blase bleibt stehen, damit der Text
   nicht verloren ist, und sagt, was zu tun ist. */
.msg.fehlgeschlagen { opacity: 1; border: 1px solid var(--danger); }
.sende-fehler {
  margin-top: 4px;
  font-size: 12px;
  color: var(--danger);
}
.sende-nochmal {
  border: 0;
  padding: 0;
  background: none;
  color: var(--danger);
  font-size: 12px;
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
}

/* Sie stand schon als vorlaeufige Blase da - ein zweites
   Einblenden waere ein Blinken. */
.msg.ohne-einblenden { animation: none; }

/* Nach links wischen: Loeschen --------------------------------
   Die Huelle traegt Inhalt UND Knopf nebeneinander. Der Knopf
   steht rechts ausserhalb der Zeile; die Zeile schneidet ab, was
   ueberhaengt. Erst das Wischen holt ihn ins Bild. */
.wisch-huelle {
  display: flex;
  align-items: center;
  width: 100%;
  transition: transform 200ms ease;
}
/* Der Inhalt behaelt die volle Zeilenbreite - der Knopf haengt
   deshalb rechts darueber hinaus. */
.zeile-inhalt {
  display: flex;
  align-items: center;
  gap: 11px;
  flex: 0 0 100%;
  min-width: 0;
}
.wisch-loeschen {
  flex: 0 0 64px;
  align-self: stretch;
  border: 0;
  background: var(--danger);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.wisch-loeschen svg { width: 22px; height: 22px; }

/* Am Rechner gibt es das Wischen nicht - dort ist das
   Rechtsklick-Menue der Weg. Der Knopf bleibt unsichtbar, weil
   nichts ihn ins Bild faehrt; abgeschnitten wird er trotzdem,
   damit er nirgends hervorlugt. */
#chat-list li.wischbar { overflow: hidden; }

/* Die Polsterung wandert von der Zeile in den Inhalt - und zwar
   ueberall, nicht nur am Handy. Bleibt sie an der Zeile, endet der
   Inhalt (100 % der Innenbreite) schon vor dem Rand, und der rote
   Knopf lugt genau um die Polsterbreite hervor. Am Rechner war das
   ein roter Streifen an jeder Zeile. */
#chat-list li.wischbar { padding-left: 0; padding-right: 0; }
#chat-list li.wischbar .zeile-inhalt { padding: 0 14px 0 16px; }

/* Langes Druecken soll das Menue oeffnen und nicht den Text
   markieren. In der Mitgliederliste stand das schon so - in den
   Listen links fehlte es, und am Handy markierte jeder Langdruck
   erst einmal den Namen. */
#chat-list li, #channel-list li {
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

/* Tastatur offen: kein Platz mehr fuer den Home-Balken ---------
   Der liegt dann hinter der Tastatur. Die Polsterung dafuer
   stand als leerer Streifen zwischen Schreibfeld und Tastatur.
   Gesetzt wird die Klasse in tastatur.js. */
:root.tastatur-offen #send-form { padding-bottom: 5px; }
:root.tastatur-offen #bottom-nav { padding-bottom: 6px; }

/* Daumengroesse in der Chatliste ---------------------------
   Nachgemessen: Die Filter-Chips waren 31 px hoch, die beiden
   runden Knoepfe oben 38x38. Mit der Maus trifft man das, mit dem
   Daumen zielt man daneben - und beides sind Sachen, die man oft
   antippt. Am Rechner bleibt es schlank. */
@media (max-width: 700px) {
  .chip {
    min-height: 38px;
    display: inline-flex;
    align-items: center;
  }
  #btn-search-toggle, #btn-new-chat {
    width: 40px;
    height: 40px;
  }
}

/* Daumengroesse im Profilmenue ----------------------------
   Nachgemessen am Handy: die vier Statuszeilen
   (Online/Abwesend/...) je 31 hoch.

   Schliessen und Zurueck standen frueher hier mit 40x38. Sie
   sind weg: .settings-header button gibt ihnen jetzt 44x44 wie
   allen anderen Kopfzeilen-Knoepfen. Stuende die alte Zeile noch
   da, haette sie als ID-Selektor gewonnen und die 38 behalten. */
@media (max-width: 700px) {
  #profile-menu .status-wahl { min-height: 38px; }
}

/* Daumengroesse im Serverbereich ---------------------------
   Nachgemessen am Handy: Zurueck 35x25, Zahnrad 40x28 und das
   Plus neben "Textkanaele"/"Sprachkanaele" nur 22x22. Die Kanaele
   selbst sind mit 43 px in Ordnung.

   Zurueck und Zahnrad auf 44 wie die Kopfzeilen anderswo - der
   Zurueck-Pfeil ist auch hier der einzige Weg heraus. Das Plus
   bleibt bei 38: Es steht in einer Zeile mit Text, 44 wuerde die
   Ueberschrift auseinanderziehen; 38 trifft man immer noch. */
@media (max-width: 700px) {
  #btn-server-back, #btn-server-settings { min-width: 44px; min-height: 44px; }
  .ch-plus { width: 38px; height: 38px; }
}

/* Die Nachzuegler ---------------------------------------
   Eine Messung ueber alle Ansichten am Handy hat vier Knoepfe
   gefunden, die nie mitgezogen wurden - der Rest der App liegt bei
   38 oder 44:

     Plus neben "Kontakte"         32x32
     Rang hoch/runter, Entfernen   30x30 (Mitgliederliste)
     "Kontakt teilen"             176x34
     "Schluessel holen"           127x29

   38 statt 44 aus demselben Grund wie bei .ch-plus darueber: Alle
   vier stehen in einer Zeile MIT Text. Auf 44 gezogen wuerden sie
   die Zeile auseinanderziehen - 38 trifft der Daumen auch.

   Beim Entfernen aus der Gruppe kommt eine Rueckfrage, ein
   Fehlgriff ist also nicht endgueltig. */
@media (max-width: 700px) {
  #btn-add-contact-toggle { width: 38px; height: 38px; }
  .gi-promote, .gi-kick { width: 38px; height: 38px; }
  #btn-ac-teilen, .schluessel-not-knopf { min-height: 38px; }
}

/* Daumengroesse der Kaestchen-Zeilen ----------------------
   Alle acht Kaestchen der App stecken in einem <label>, der Text
   daneben zaehlt also mit - man muss nicht das kleine Quadrat
   treffen. Nur war die Zeile selbst zu flach.

   Gemessen am Handy: umfrage-mehrfach 18,
   ton-filter-zeile 21, mf-hide-reserved 22, reg-terms 36.

   ton-filter-zeile braucht zusaetzlich display: flex: Ein Label
   ist von Haus aus inline, und inline-Elemente ignorieren
   min-height. Alle fuenf stehen je auf einer eigenen Zeile,
   keins mitten in einem Satz - flex zieht dort nichts auseinander.

   Die drei Benachrichtigungs-Zeilen fehlen hier mit Absicht: Sie
   haben ihre 44 schon weiter oben, und zwar ohne Medienabfrage. */
@media (max-width: 700px) {
  #reg-terms, #ton-filter-zeile, #mf-hide-reserved,
  #umfrage-mehrfach {
    min-height: 44px;
    display: flex;
    align-items: center;
  }
}

/* Die letzten Knoepfe unter 44 --------------------------------
   Nachgemessen am Handy - alles Knoepfe, die man trifft, die aber
   knapper waren als noetig:

     Anruf verkleinern      36x36   (feste height: 34px)
     Anruf-Knopfreihe       51x40   (auflegen, stumm, Kamera ...)
     Story schliessen       42x38   (stand hier mal auf 38)
     Weiterleiten zu        40x29
     Sprachleiste           40x40   (feste Kreise)
     Bildschirm gross/zu    38x26

   Am Rechner bleibt alles wie es war: Mit der Maus zielt man
   genauer, und 44er Knoepfe wuerden die Leisten dort unnoetig
   aufblasen. Deshalb steht der ganze Block in der Medienabfrage.

   KEIN display hier - dieselbe Falle wie bei .settings-header
   button: Eine display-Angabe waere staerker als .hidden. Wo ein
   Symbol mittig sitzen muss, steht das display schon in der
   Grundregel des jeweiligen Knopfes. */
@media (max-width: 700px) {
  /* Der Verkleinern-Knopf hat weiter unten einen eigenen Block -
     dort steht seine 44. */
  /* Nur im grossen Anruffenster. Die zusammengeschobene Leiste
     (.klein) hat mit Absicht 32er Knoepfe - min-height sticht
     height, ohne :not haette meine 44 sie aufgeblasen. */
  #call-overlay:not(.klein) .call-buttons button {
    min-width: 44px;
    min-height: 44px;
  }
  #viewer-top button { min-width: 44px; min-height: 44px; }
  .forward-header button { min-width: 44px; min-height: 44px; }
  /* Feste Kreise, deshalb width/height statt min-*: Sonst bliebe
     der Kreis 40 breit und wuerde 44 hoch - also ein Ei. */
  #voice-bar button { width: 44px; height: 44px; }
  #btn-bildschirm-voll, #btn-bildschirm-zu {
    min-width: 44px;
    min-height: 44px;
  }
}

/* Nach rechts wischen: antworten ---------------------------
   Waehrend der Geste muss die Einblend-Animation weg: Ihr
   Schlussbild (fill: both) schlaegt sonst das transform, und die
   Blase bleibt stehen. */
.msg.wischt { animation: none; transition: transform 180ms ease; }

/* Das Zeichen liegt hinter der Blase und waechst beim Ziehen. */
.antwort-zeichen {
  position: absolute;
  left: 14px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--glass-bg);
  color: var(--accent);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
}

/* Sprachkanal-Leiste am Handy -----------------------------
   Auf 375 px bleiben dem Kanalnamen 97 Pixel: 24 gehen fuer die
   Polsterung drauf, 50 fuer die Abstaende zwischen sechs
   Elementen, 18 fuer das Symbol und 160 fuer die vier Knoepfe.
   "Feierabendrunde" passt damit nicht mehr hinein.

   Die Knoepfe bleiben bei 40 - daran wird nicht gespart. Enger
   zusammen duerfen sie aber ruecken. */
@media (max-width: 700px) {
  #voice-bar {
    gap: 6px;
    padding: 10px 8px;
  }
}

/* Die Reaktionsleiste sitzt am unteren Rand - dort laeuft auf dem
   iPhone der Home-Balken durch. */
#story-react-bar { padding-bottom: calc(10px + env(safe-area-inset-bottom)); }

/* Antwortzeile im Status-Betrachter ------------------------
   Sitzt unten, ueber der Emoji-Leiste. Solange sie steht,
   pausiert der Status - man soll in Ruhe tippen koennen. */
#story-antwort {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  background: rgba(22, 25, 36, 0.92);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
#story-antwort.hidden { display: none; }
#story-antwort-feld {
  flex: 1 1 0;
  min-width: 0;
  min-height: 40px;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
}
#story-antwort button { min-width: 40px; min-height: 40px; }

/* Status anlegen: daumengross am Handy --------------------
   Zwei gemessene Stellen im Weg zum eigenen Status:
   das Plus am eigenen Ring (26x26) und die Farbkreise im
   Text-Status (28x28). Beide trifft man mit der Maus, mit dem
   Daumen nicht zuverlaessig.

   Das Plus waechst nur nach aussen (es sitzt in der Ecke des
   Rings), die Farbkreise brauchen etwas mehr Abstand. */
@media (max-width: 700px) {
  .story-plus {
    width: 38px; height: 38px;
    right: -8px; bottom: -8px;
    font-size: 22px;
    line-height: 34px;
  }
  .color-chip { width: 38px; height: 38px; }
  #story-colors { gap: 8px; flex-wrap: wrap; }
}

/* Verkleinern-Knopf am Handy ------------------------------
   Gemessen 25x32 im Sprachanruf und 26x34 im Video. Das ist der
   Knopf, mit dem man den Anruf beiseiteschiebt, um nebenher etwas
   nachzusehen - und er war der kleinste in der ganzen Ansicht.

   Stand hier zuerst auf 38, jetzt 44 wie alle anderen Auswege.
   Der Radius muss mitwachsen: Der Knopf ist eine Pille mit fester
   height: 34px (min-height sticht height) und border-radius: 17px
   - bliebe der Radius stehen, waere aus der Pille bei 44 Hoehe ein
   Rechteck mit runden Ecken geworden.

   Der Satz "die uebrigen Anrufknoepfe sind mit 44 hoch genug"
   stand hier frueher und stimmte nicht mehr: Nachgemessen waren
   es 51x40. Sie stehen jetzt im Daumen-Block weiter oben. */
@media (max-width: 700px) {
  /* Ebenfalls nur gross: In der zusammengeschobenen Leiste ist
     der Knopf mit Absicht 28 und rund. */
  #call-overlay:not(.klein) #btn-call-min {
    min-width: 44px;
    min-height: 44px;
    border-radius: 22px;
  }
}

/* Am Handy markiert der lange Druck nichts -----------------
   Am Rechner ist Text in einer Blase markierbar, und das soll
   so bleiben. Am Handy ist der lange Druck aber die Geste fuer
   das Menue: Dort faengt der Browser sonst an, den Text zu
   markieren, und man steht mit blauer Schrift und der
   System-Blase da, waehrend das eigene Menue darueber liegt.

   Kopieren geht am Handy ueber den Menueeintrag - dafuer ist
   er da. */
@media (max-width: 700px) {
  .msg, .msg-text {
    user-select: none;
    -webkit-user-select: none;
    -webkit-touch-callout: none;
  }
}

/* Leere Chatliste (erste Anmeldung) -------------------------
   Sitzt mitten in der Spalte, nicht oben am Rand: Ein Hinweis,
   der sich an die Filterchips klebt, sieht aus wie ein Fehler.
   Nur so viel Text wie noetig, und ein Knopf, der weiterfuehrt. */
#chat-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 64px 28px 0;
  text-align: center;
}
#chat-empty.hidden { display: none; }
#chat-empty-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-dim);
}
#btn-chat-empty-add { min-height: 44px; }

/* Kontaktvorschlaege ---------------------------------------
   Sehen aus wie Kontaktzeilen, sind aber keine: Statt eines
   Chats fuehrt der Knopf rechts zur Anfrage. Deshalb kein
   Zeiger auf der ganzen Zeile - man klickt den Knopf, nicht
   die Person. */
.vorschlag {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
}
.vorschlag .li-text { flex: 1 1 auto; min-width: 0; }
/* Eine Zeile je Name, gekuerzt statt umgebrochen. Ohne das waren
   die Zeilen unterschiedlich hoch - gemessen 60 und 77 Pixel -,
   und eine Liste mit ungleichen Zeilen sieht kaputt aus. */
.vorschlag .contact-name,
.vorschlag .contact-last {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vorschlag-plus {
  flex-shrink: 0;
  min-width: 44px;
  min-height: 44px;
  color: var(--accent);
}
.vorschlag-plus svg { margin-inline: auto; }
.vorschlag-plus:disabled { opacity: 0.4; }
/* "Mehr anzeigen" - unauffaellig, es ist ein Angebot, keine
   Aufforderung. */
.vorschlag-mehr { padding: 4px 12px 10px; }
.vorschlag-mehr button {
  width: 100%;
  min-height: 40px;
  padding: 0;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}
.vorschlag-mehr button:hover { background: var(--hover); }

/* Wie #pw-card, #twofa-card und #key-card - dasselbe Mass, damit
   sich der Abschnitt nicht heraushebt. */
#vorschlag-card { padding: 4px 16px 14px; }

/* Schalter "Anderen vorschlagen duerfen" -------------------
   Gleiche Bauform wie die Benachrichtigungs-Zeilen: Das ganze
   Label ist die Tippflaeche, 44 Pixel hoch. */
#vorschlagbar-zeile {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  font-size: 14px;
  cursor: pointer;
}
#vorschlagbar-toggle {
  width: 22px; height: 22px;
  flex-shrink: 0;
  accent-color: var(--accent);
}
