:root {
    --primary: #6C5CE7;
    --secondary: #00B894;
    --bg: #0F1220;
    --surface: #1A1E33;
    --surface-alt: #242A47;
    --text: #F5F6FA;
    --muted: #A9AEC7;
    --accent: #FDCB6E;
    --border: #33395C;
    --radius: 14px;
    --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --danger: #FF7675;
    --success: #00B894;
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
    height: 100%;
    margin: 0;
    /* Zusätzlich zu .chat-body { overflow: hidden } - iOS Safari scrollt beim
       Fokussieren eines Eingabefelds manchmal trotzdem noch das html-Element
       selbst (nicht nur body), was zu einer großen leeren Lücke über dem
       Composer führt, sobald die Tastatur aufklappt. Siehe auch --app-height
       in assets/js/chat.js (hoh_apply_viewport_height) für den zugehörigen
       JS-Teil der Lösung. */
    overflow: hidden;
}

body {
    font-family: var(--font);
    background: var(--bg);
    color: var(--text);
    -webkit-font-smoothing: antialiased;
}

/* Ohne diese Regeln benutzt der Browser seinen hellen Standard-Scrollbar (weiße
   Spur mit grauem Griff), sobald ein Element wie die Nachrichtenliste überläuft -
   das sieht neben dem dunklen Theme wie ein Anzeigefehler aus. Firefox nutzt
   scrollbar-color/-width, Chrome/Safari/Edge die ::-webkit-scrollbar-Regeln. */
* {
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--border) 70%, black 20%) transparent;
}
*::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}
*::-webkit-scrollbar-track {
    background: transparent;
}
*::-webkit-scrollbar-thumb {
    background-color: color-mix(in srgb, var(--border) 70%, black 20%);
    border-radius: 999px;
}
*::-webkit-scrollbar-thumb:hover {
    background-color: var(--muted);
}

a { color: var(--primary); }

button {
    font-family: inherit;
}

/* ---------------- Login-Seite ---------------- */

.login-body {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    min-height: 100dvh;
    padding: max(24px, var(--safe-top)) 20px max(24px, var(--safe-bottom));
    background: var(--bg); /* Fallback für Browser ohne color-mix()-Unterstützung */
}
.login-body {
    background:
        radial-gradient(circle at 20% 15%, color-mix(in srgb, var(--primary) 25%, transparent) 0%, transparent 45%),
        radial-gradient(circle at 80% 85%, color-mix(in srgb, var(--secondary) 20%, transparent) 0%, transparent 45%),
        var(--bg);
}

.login-wrap { width: 100%; display: flex; justify-content: center; }

.login-card {
    width: 100%;
    max-width: 420px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: calc(var(--radius) + 4px);
    padding: 32px 28px;
    box-shadow: 0 25px 70px rgba(0,0,0,0.45);
}

.brand { text-align: center; margin-bottom: 24px; }

.brand-badge {
    width: 56px;
    height: 56px;
    border-radius: 16px;
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 14px;
    font-weight: 800;
    letter-spacing: 0.5px;
    color: white;
    font-size: 1rem;
}

.brand h1 { font-size: 1.3rem; margin: 0 0 4px; }
.brand p { color: var(--muted); margin: 0; font-size: 0.9rem; }

.login-form { display: flex; flex-direction: column; gap: 6px; }

.login-form label {
    font-size: 0.82rem;
    color: var(--muted);
    margin-top: 8px;
}

.login-form input {
    width: 100%;
    padding: 14px 16px;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    background: color-mix(in srgb, var(--bg) 70%, black 5%);
    color: var(--text);
    font-size: 1.05rem;
}

.code-input {
    text-align: center;
    letter-spacing: 12px;
    font-size: 1.6rem !important;
    font-weight: 700;
}

.login-form input:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 35%, transparent);
}

.login-form button {
    margin-top: 16px;
    padding: 14px;
    border: none;
    border-radius: var(--radius);
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    color: white;
    font-weight: 700;
    font-size: 1rem;
    cursor: pointer;
}

.login-form button:active { transform: scale(0.98); }

.hint { text-align: center; color: var(--muted); font-size: 0.82rem; margin-top: 18px; }

.lang-required-field {
    margin-top: 10px;
    padding: 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--bg) 70%, black 5%);
    max-height: 220px;
    overflow-y: auto;
}

.lang-required-field legend {
    padding: 0 4px;
    font-size: 0.82rem;
    color: var(--muted);
}

.lang-required-field {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px 10px;
}

.lang-required-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 4px;
    font-size: 0.92rem;
    color: var(--text);
    cursor: pointer;
}

.lang-required-option input { width: auto; padding: 0; flex-shrink: 0; }

@media (max-width: 420px) {
    .lang-required-field { grid-template-columns: 1fr; }
}

.badge-category {
    display: inline-block;
    background: var(--surface-alt);
    color: var(--accent);
    padding: 4px 12px;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 600;
    margin-bottom: 8px;
}

.alert {
    padding: 12px 14px;
    border-radius: var(--radius);
    font-size: 0.85rem;
    margin-bottom: 16px;
}
.alert-error { background: color-mix(in srgb, var(--danger) 18%, transparent); border: 1px solid var(--danger); color: #ffc2c1; }
.alert-success { background: color-mix(in srgb, var(--success) 18%, transparent); border: 1px solid var(--success); color: #9df3da; }

/* ---------------- Chat-Oberfläche ---------------- */

/* overflow:hidden auf der Chat-Seite verhindert, dass die ganze Browser-Seite
   zusätzlich zum internen Nachrichtenbereich (.messages) scrollt - dieser
   winzige Seiten-Überlauf war die Ursache für den hellen, nicht eingefärbten
   Scrollbalken ganz rechts am Fensterrand (der native Balken lässt sich per
   CSS nicht in jedem Browser umfärben, deshalb wird er hier komplett
   vermieden statt nur eingefärbt). Login-Seiten (index.php/admin/index.php)
   nutzen die Klasse chat-body nicht und scrollen weiterhin normal. */
.chat-body {
    background: var(--bg);
    overflow: hidden;
    /* Zusätzliche Verankerung gegen den iOS-Safari-"Sprung": ohne position:fixed
       kann Safari beim Fokussieren des Composer-Eingabefelds trotz overflow:hidden
       das gesamte Dokument nach oben scrollen, um das Feld "sichtbar" zu machen -
       dabei bleibt aber eine leere Lücke stehen, weil sich gleichzeitig die
       Tastatur öffnet. position:fixed nimmt body komplett aus dem normalen
       Dokumentfluss/Scrollverhalten heraus. */
    position: fixed;
    inset: 0;
    width: 100%;
}

.chat-shell {
    display: flex;
    flex-direction: column;
    /* Anker für .drag-drop-overlay (position:absolute), das beim Drag&Drop einer
       Bilddatei über dem gesamten Chatfenster eingeblendet wird. */
    position: relative;
    height: 100vh;
    height: 100dvh;
    /* --app-height wird per JS (assets/js/chat.js, hoh_apply_viewport_height)
       aus window.visualViewport.height berechnet und bei jeder Tastatur-
       Ein-/Ausblendung aktualisiert. Zuverlässiger als reines dvh, da manche
       iOS-Versionen dvh beim Öffnen der Tastatur nicht (rechtzeitig) neu
       berechnen. Fällt ohne JS-Unterstützung auf 100dvh zurück. */
    height: var(--app-height, 100dvh);
    max-width: 900px;
    margin: 0 auto;
    background: var(--surface);
    border-left: 1px solid var(--border);
    border-right: 1px solid var(--border);
}

.chat-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 12px;
    padding: max(14px, var(--safe-top)) 16px 14px;
    background: var(--surface-alt);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 5;
}

/* Blendet Inhalt nur visuell aus, bleibt aber für Screenreader vorhanden -
   genutzt z. B. für den Admin-Chat-Titel (admin/chat.php), der nicht mehr
   sichtbar angezeigt wird, weil der Kategoriename bereits im Auswahl-Dropdown
   im Header steht (vorher stand er dort doppelt). */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.chat-header-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.chat-header-info h1 { font-size: 1.02rem; margin: 0; display: flex; align-items: center; gap: 8px; min-width: 0; }
.chat-header-info h1 .title-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }

.unread-badge {
    background: var(--danger);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 800;
    line-height: 1;
    padding: 4px 8px;
    border-radius: 999px;
    flex-shrink: 0;
    box-shadow: 0 0 0 2px var(--surface-alt);
}

.chat-category-pill {
    align-self: flex-start;
    background: color-mix(in srgb, var(--primary) 25%, transparent);
    color: var(--text);
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 2px 9px;
    border-radius: 999px;
    white-space: nowrap;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* WICHTIG: flex-shrink hier NICHT auf 0 setzen (das war der eigentliche Bug,
   der zu abgeschnittenen Icons führte) - .chat-header-actions landet auf
   schmalen Handys als einzelnes Element in einer eigenen Zeile (siehe
   .chat-header { flex-wrap: wrap }), muss sich dort aber auf die tatsächlich
   verfügbare Breite zusammenschrumpfen können, damit .chat-header-icons
   (flex-wrap: wrap) seine Icons überhaupt in weitere Zeilen umbrechen kann,
   statt seitlich über den Bildschirmrand hinauszulaufen. */
.chat-header-actions { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; max-width: 100%; position: relative; }

/* Der Hamburger blendet den kompletten oberen Header (Titel, Kategorie-Pill, alle
   Icons) bis auf sich selbst aus/ein - schafft auf Wunsch mehr Platz für den
   eigentlichen Chatverlauf, auf jeder Bildschirmgröße (nicht nur Mobile). Anders
   als früher bleibt der Button deshalb immer sichtbar, nicht erst ab einer
   bestimmten Breite. Der Zustand wird von assets/js/chat.js in localStorage
   gemerkt und bleibt daher auch nach einem Reload erhalten (z. B. nach einem
   Kategorie-Wechsel im Admin-Bereich oder einer Sprachumschaltung). */
.chat-menu-toggle { display: flex; flex-shrink: 0; }
.chat-menu-toggle.active { background: color-mix(in srgb, var(--primary) 30%, transparent); }

/* flex-wrap bleibt als reines Sicherheitsnetz für absolute Extremfälle (sehr
   lange Kategorienamen, extrem schmale Displays) - im Normalfall sorgt die
   @media-Regel weiter unten dafür, dass Hamburger, Auswahl-Dropdown und alle
   Icons auf Handys durch kleinere Maße zusammen in eine einzige Zeile passen,
   statt in eine zweite Zeile umzubrechen. */
.chat-header-icons { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: flex-end; row-gap: 6px; flex: 1 1 auto; min-width: 0; }

.chat-picker-select {
    padding: 8px 10px;
    border-radius: 10px;
    border: 1px solid var(--border);
    background: var(--surface-alt);
    color: var(--text);
    max-width: 130px;
    min-width: 0;
}

/* Auf Handys (typ. 360-430px Breite) reichte der Platz trotz der obigen Fixes
   nicht für Hamburger + Dropdown + 5 Icons in einer Zeile - das Dropdown lief
   um, der Hamburger stand dadurch optisch "zu tief". Fix: alles in diesem
   Breitenbereich spürbar verkleinern (Icon-Kreise, Abstände, Dropdown-Breite),
   damit rechnerisch alles in eine Zeile passt, statt umzubrechen. */
@media (max-width: 600px) {
    .chat-header-actions { gap: 6px; }
    .chat-header-icons { gap: 6px; row-gap: 6px; }
    .chat-header .icon-btn {
        width: 32px;
        height: 32px;
        font-size: 0.88rem;
    }
    .chat-picker-select {
        max-width: 90px;
        padding: 6px 6px;
        font-size: 0.8rem;
    }
}

.chat-header.collapsed {
    padding-top: max(8px, var(--safe-top));
    padding-bottom: 8px;
}
.chat-header.collapsed .chat-header-info,
.chat-header.collapsed .chat-header-actions > *:not(.chat-menu-toggle) {
    display: none;
}

.me-badge {
    font-size: 0.78rem;
    color: var(--muted);
    display: none;
}
@media (min-width: 560px) {
    .me-badge { display: inline-block; }
}

.lang-picker {
    position: relative;
    flex-shrink: 0;
}
/* Im Chat-Header (siehe .chat-header-actions { position: relative }) bewusst
   KEINEN eigenen Positionierungskontext aufmachen: .lang-picker-menu (unten,
   right:0) soll sich am rechten Rand des GESAMTEN Header-Zeile ausrichten,
   nicht am kleinen 🌐-Button selbst. Sitzt der Button (wie z. B. bei mehreren
   Icons auf schmalen Handys) nicht ganz rechts, würde right:0 relativ zum
   Button sonst dazu führen, dass das mehrspaltige Sprachmenü nach links über
   den Bildschirmrand hinausläuft und die linke Spalte abgeschnitten wird. */
.chat-header .lang-picker {
    position: static;
}
.lang-picker-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    list-style: none;
    cursor: pointer;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 6px 12px;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text);
    user-select: none;
}
.lang-picker-btn::-webkit-details-marker { display: none; }
.lang-picker-btn:hover { border-color: var(--primary); }
.lang-picker[open] .lang-picker-btn { border-color: var(--primary); color: var(--secondary); }
.lang-picker-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    z-index: 40;
    display: grid;
    grid-template-columns: repeat(2, minmax(110px, 1fr));
    gap: 3px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 8px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
    max-height: 60vh;
    overflow-y: auto;
}
.lang-picker-option {
    display: block;
    padding: 7px 10px;
    border-radius: 8px;
    font-size: 0.84rem;
    color: var(--muted);
    text-decoration: none;
    white-space: nowrap;
    transition: background .15s, color .15s;
}
.lang-picker-option:hover { background: var(--surface-alt); color: var(--text); }
.lang-picker-option.active {
    background: var(--primary);
    color: #fff;
}
.login-card .lang-picker { position: absolute; top: 16px; right: 16px; }
.login-card { position: relative; }
@media (max-width: 420px) {
    .lang-picker-menu { grid-template-columns: 1fr; right: -16px; }
}

/* Auf schmalen Handys ist im Chat-Header (siehe .chat-header/.chat-header-icons)
   kaum Platz für Kategorie-Auswahl, Sprache und mehrere Icons nebeneinander -
   das Wort "Language" fällt hier weg, das 🌐-Icon allein bleibt verständlich
   und spart deutlich Breite. Die Sprachauswahl selbst funktioniert unverändert. */
@media (max-width: 480px) {
    .chat-header .lang-picker-label { display: none; }
    .chat-header .lang-picker-btn { padding: 6px 10px; }
}

.icon-btn {
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
    text-decoration: none;
    font-size: 1rem;
    cursor: pointer;
}
.icon-btn:active { transform: scale(0.94); }

.notes-panel {
    background: var(--surface-alt);
    border-bottom: 1px solid var(--border);
    padding: 10px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.notes-panel[hidden] { display: none; }

.notes-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 0.85rem;
    background: none;
    border: none;
    color: inherit;
    font-family: inherit;
    text-align: left;
    width: 100%;
    padding: 4px 0;
    cursor: pointer;
}
.notes-panel-head strong { flex-shrink: 0; }
.notes-meta { color: var(--muted); font-size: 0.72rem; margin-right: auto; margin-left: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notes-chevron { color: var(--muted); font-size: 0.75rem; flex-shrink: 0; transition: transform .15s; }
.notes-panel.expanded .notes-chevron { transform: rotate(180deg); }

.notes-preview {
    color: var(--muted);
    font-size: 0.82rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.notes-panel.expanded .notes-preview { display: none; }

.notes-body { display: none; flex-direction: column; gap: 8px; }
.notes-panel.expanded .notes-body { display: flex; }

.notes-panel textarea {
    width: 100%;
    min-height: 90px;
    max-height: 40vh;
    resize: vertical;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    padding: 10px 12px;
    font-family: inherit;
    font-size: 0.9rem;
}

.notes-panel button {
    align-self: flex-end;
    border: none;
    background: var(--primary);
    color: white;
    padding: 8px 16px;
    border-radius: var(--radius);
    font-weight: 600;
    cursor: pointer;
}

.messages {
    flex: 1;
    overflow-y: auto;
    padding: 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    -webkit-overflow-scrolling: touch;
}

/* /close: gesperrter Chat für Nicht-Administratoren - der Nachrichtenverlauf wird
   weiterhin komplett ausgeliefert (siehe api/get_messages.php), aber unscharf
   dargestellt statt einfach zu fehlen. pointer-events/user-select deaktiviert,
   damit sich hinter dem Weichzeichner kein Text markieren oder anklicken lässt. */
.messages.chat-blurred {
    filter: blur(6px);
    pointer-events: none;
    user-select: none;
}

/* Angeheftete Nachricht (siehe api/pin_message.php): fest sichtbare Leiste über
   dem Chatverlauf, unabhängig davon, ob die eigentliche Nachricht gerade in der
   geladenen Seite sichtbar ist. Ein Klick scrollt zur Originalnachricht (falls
   geladen), das ✕ (nur Admins) löst die Heftung. */
.pinned-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    background: color-mix(in srgb, var(--accent) 16%, var(--surface-alt));
    border-bottom: 1px solid var(--border);
    padding: 8px 16px;
    font-size: 0.82rem;
    cursor: pointer;
    flex-shrink: 0;
}
.pinned-bar[hidden] { display: none; }
.pinned-bar-icon { flex-shrink: 0; }
.pinned-bar-author { font-weight: 700; flex-shrink: 0; }
.pinned-bar-text {
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
}
/* Falls die angeheftete Nachricht ein *img*...*img* enthält, bleibt das Bild in
   der kompakten Leiste klein statt in voller Größe (siehe .msg-image) - die
   Leiste ist für kompakte Textvorschau gedacht, nicht als Bildanzeige. */
.pinned-bar-text .msg-image { max-height: 20px; max-width: 40px; width: auto; vertical-align: middle; border-radius: 4px; }
.pinned-bar-unpin {
    flex-shrink: 0;
    background: none;
    border: none;
    color: inherit;
    opacity: 0.6;
    cursor: pointer;
    font-size: 0.9rem;
    padding: 0 2px;
}
.pinned-bar-unpin:hover { opacity: 1; }

/* Angeheftete Nachricht im Verlauf selbst: dezente Hervorhebung, damit sie beim
   Scrollen zusätzlich zur Leiste oben auffällt. */
.msg-pinned {
    border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
    background: color-mix(in srgb, var(--accent) 10%, var(--surface-alt));
}
.msg-pin-btn.active { opacity: 1; filter: saturate(1.4); }

/* Kurzes Aufblitzen, wenn über die Leiste zur angehefteten Nachricht gescrollt wird. */
.msg-flash { animation: msg-flash-anim 1.2s ease-out; }
@keyframes msg-flash-anim {
    0% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 55%, transparent); }
    100% { box-shadow: 0 0 0 0 transparent; }
}

/* Statuszeile über dem Chatverlauf beim Nachladen älterer Nachrichten (Infinite-Scroll
   nach oben, siehe assets/js/chat.js loadOlderMessages()) bzw. sobald der Anfang der
   Unterhaltung erreicht ist - per Default per [hidden] ausgeblendet. */
.messages-top-note {
    text-align: center;
    font-size: 0.72rem;
    color: var(--muted);
    padding: 6px 12px;
    flex-shrink: 0;
}

.msg {
    max-width: 82%;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 8px 12px;
    align-self: flex-start;
}

.msg-admin {
    border-color: color-mix(in srgb, var(--accent) 60%, var(--border));
    background: color-mix(in srgb, var(--accent) 12%, var(--surface-alt));
}

/* /help-Übersicht: rein lokal, nie an den Server gesendet - optisch bewusst
   von normalen Nachrichten abgesetzt (zentriert, gestrichelter Rahmen). */
.msg-help {
    align-self: center;
    max-width: 92%;
    background: color-mix(in srgb, var(--primary) 12%, var(--surface-alt));
    border: 1px dashed var(--border);
}
.msg-help-title {
    font-weight: 700;
    margin-bottom: 6px;
}
.msg-help-list {
    margin: 0;
    padding-left: 18px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.86rem;
    color: var(--muted);
}

/* /online-Liste: teilt sich die Bubble-Optik mit .msg-help, bekommt aber
   grüne Punkte statt normaler Aufzählungszeichen ("online" = grün) und einen
   eigenen Leerlauf-Hinweis, wenn gerade niemand da ist. */
.msg-online-list {
    list-style: none;
    padding-left: 0;
    color: var(--text);
}
.msg-online-list li::before {
    content: '';
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--success, #2ecc71);
    margin-right: 8px;
}
/* /away [Grund]: gelber statt grüner Punkt + gedämpfte Schrift, damit
   Abwesende auf einen Blick von wirklich aktiven Personen zu unterscheiden sind. */
.msg-online-list li.msg-online-away {
    color: var(--muted);
    font-style: italic;
}
.msg-online-list li.msg-online-away::before {
    background: var(--accent, #f1c40f);
}
.msg-online-empty {
    font-size: 0.86rem;
    color: var(--muted);
    font-style: italic;
}

.msg-meta {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    font-size: 0.72rem;
    color: var(--muted);
    margin-bottom: 3px;
}

.msg-author-wrap { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.msg-author { font-weight: 700; color: var(--primary); }
.msg-admin .msg-author { color: var(--accent); }

.msg-alliance {
    background: color-mix(in srgb, var(--secondary) 22%, transparent);
    color: var(--text);
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 2px 7px;
    border-radius: 999px;
}

.msg-meta-right { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }

.msg-edited {
    font-size: 0.66rem;
    font-style: italic;
    color: var(--muted);
    opacity: 0.8;
}

.msg-action-btn {
    background: none;
    border: none;
    padding: 0 2px;
    font-size: 0.82rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.55;
    color: inherit;
}
.msg-action-btn:hover, .msg-action-btn:active { opacity: 1; }
.msg-translated-btn.active { opacity: 1; filter: saturate(1.4); }

.msg-bold { font-weight: 800; }

/* Leichte Inline-Formatierung per Chat-Befehl (siehe assets/js/chat.js
   renderFormattedText): *Text* fett, #Text# kursiv, _Text_ unterstrichen,
   *red*Text*red* rot, *blink*Text*blink* blinkend. */
.msg-fmt-bold { font-weight: 800; }
.msg-fmt-italic { font-style: italic; }
.msg-fmt-underline { text-decoration: underline; }
.msg-fmt-red { color: var(--danger); }
.msg-fmt-blink { animation: msg-blink-anim 1s step-start infinite; }
@keyframes msg-blink-anim {
    50% { opacity: 0; }
}
/* Weniger Bewegung/Blinken für Nutzer, die das per Betriebssystem so
   eingestellt haben (Barrierefreiheit) - Text bleibt einfach dauerhaft sichtbar. */
@media (prefers-reduced-motion: reduce) {
    .msg-fmt-blink { animation: none; }
}

/* *marquee*Text*marquee* - Laufschrift von rechts nach links, siehe
   assets/js/chat.js appendFormattedSegments (Wrapper msg-marquee-wrap/-inner).
   Klassischer CSS-Trick: .inner startet per padding-left:100% außerhalb des
   sichtbaren (durch overflow:hidden begrenzten) .wrap-Bereichs rechts und
   wandert per Transform komplett bis hinter den linken Rand. */
.msg-marquee-wrap {
    display: inline-block;
    overflow: hidden;
    white-space: nowrap;
    vertical-align: bottom;
    max-width: 100%;
}
.msg-marquee-inner {
    display: inline-block;
    white-space: nowrap;
    padding-left: 100%;
    animation: msg-marquee-anim 8s linear infinite;
}
@keyframes msg-marquee-anim {
    from { transform: translateX(0); }
    to { transform: translateX(-100%); }
}
@media (prefers-reduced-motion: reduce) {
    .msg-marquee-inner { animation: none; padding-left: 0; }
}

/* Automatisch verlinkte http(s)-URLs innerhalb einer Nachricht (siehe
   assets/js/chat.js appendTextWithLinks()) - eigene Farbe/Unterstreichung statt
   Browser-Standard, damit Links auch innerhalb roter/fetter Abschnitte klar als
   Link erkennbar bleiben. */
.chat-link {
    color: var(--primary);
    text-decoration: underline;
    word-break: break-all;
}
.chat-link:hover { opacity: 0.85; }

/* *counter 60* - live herunterzählendes Sekunden-Badge, siehe
   assets/js/chat.js createCounterBadge(). */
.msg-counter {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 9px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 20%, var(--surface-alt));
    border: 1px solid var(--border);
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 0.88em;
    white-space: nowrap;
}
.msg-counter-expired {
    background: color-mix(in srgb, var(--danger) 25%, var(--surface-alt));
    border-color: var(--danger);
}

/* *img*https://.../bild.jpg*img* - verkleinertes Vorschaubild im Chatverlauf,
   siehe assets/js/chat.js createImageElement(). Klick öffnet die größere
   Ansicht in der Lightbox (.img-lightbox-overlay weiter unten). */
.msg-image {
    display: block;
    max-width: 220px;
    max-height: 220px;
    width: auto;
    height: auto;
    margin-top: 4px;
    border-radius: 10px;
    border: 1px solid var(--border);
    cursor: zoom-in;
    object-fit: cover;
}
.msg-image-broken {
    min-width: 120px;
    min-height: 60px;
    background: var(--surface-alt);
    cursor: default;
}

.msg-body {
    font-size: 0.94rem;
    line-height: 1.4;
    white-space: pre-wrap;
    word-break: break-word;
}

/* Zitat-Vorschau über einer Antwort-Nachricht (siehe assets/js/chat.js renderMessage). */
.msg-reply-quote {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-bottom: 4px;
    padding: 3px 8px;
    border-left: 3px solid var(--primary);
    border-radius: 4px;
    background: color-mix(in srgb, var(--primary) 8%, transparent);
    font-size: 0.78rem;
    overflow: hidden;
}
.msg-reply-quote.clickable { cursor: pointer; }
.msg-reply-quote.clickable:hover { background: color-mix(in srgb, var(--primary) 16%, transparent); }
.msg-reply-quote-author { font-weight: 700; color: var(--primary); flex-shrink: 0; }
.msg-reply-quote-text {
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.msg-reply-quote-deleted {
    border-left-color: var(--border);
    background: transparent;
    font-style: italic;
}
.msg-reply-quote-deleted .msg-reply-quote-author { color: var(--muted); font-weight: 400; }

/* Kurzes Hervorheben, wenn per Klick auf eine Zitat-Vorschau zur Originalnachricht
   gescrollt wird. */
.msg-highlight {
    animation: hoh-msg-highlight 1.5s ease-out;
}
@keyframes hoh-msg-highlight {
    0% { box-shadow: 0 0 0 2px var(--primary); }
    100% { box-shadow: 0 0 0 2px transparent; }
}

.msg-edit-textarea {
    width: 100%;
    min-height: 60px;
    resize: vertical;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 10px;
    color: var(--text);
    font-family: inherit;
    font-size: 0.9rem;
    padding: 8px 10px;
}

.msg-edit-actions {
    display: flex;
    gap: 8px;
    margin-top: 6px;
}

.typing-indicator {
    padding: 4px 16px;
    font-size: 0.8rem;
    font-style: italic;
    color: var(--muted);
    background: var(--surface-alt);
    border-top: 1px solid var(--border);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.typing-indicator[hidden] { display: none; }

.readonly-notice {
    text-align: center;
    padding: 14px;
    color: var(--muted);
    font-size: 0.85rem;
    border-top: 1px solid var(--border);
    padding-bottom: max(14px, var(--safe-bottom));
}

/* /close, /open: Hinweisleiste zum Schließungsstatus (siehe assets/js/chat.js
   applyCloseState()). Zwei Varianten je nach dem, was gerade zutrifft:
   - "blocking": Chat für Nicht-Administratoren tatsächlich gesperrt (rot/danger).
   - "info": nur ein Hinweis (Admin-Ansicht bzw. "schließt bald"), Chat bleibt nutzbar. */
.chat-closed-banner {
    text-align: center;
    padding: 10px 16px;
    font-size: 0.85rem;
    font-weight: 600;
    flex-shrink: 0;
}
.chat-closed-banner[hidden] { display: none; }
.chat-closed-banner-blocking {
    background: color-mix(in srgb, var(--danger) 20%, transparent);
    border-top: 1px solid var(--danger);
    border-bottom: 1px solid var(--danger);
    color: #ffc2c1;
    padding-bottom: max(10px, var(--safe-bottom));
}
.chat-closed-banner-info {
    background: color-mix(in srgb, var(--accent) 16%, transparent);
    border-top: 1px solid var(--border);
    color: var(--text);
}

/* Fortschrittsanzeige beim Vorab-Übersetzen fehlender Nachrichten (siehe
   assets/js/chat.js, primeTranslations()) - erscheint nur kurz direkt nach
   einem Sprachwechsel bzw. beim erstmaligen Öffnen eines Chats mit einer
   bislang ungenutzten Sprache, wenn dafür wirklich mehrere Übersetzungen
   nachgeholt werden müssen. */
.lang-loading-overlay {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: color-mix(in srgb, var(--bg) 78%, transparent);
    backdrop-filter: blur(2px);
}
.lang-loading-overlay[hidden] { display: none; }
.lang-loading-box {
    width: 100%;
    max-width: 320px;
    padding: 20px 22px;
    border-radius: 14px;
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
    text-align: center;
}
.lang-loading-title {
    font-weight: 700;
    font-size: 0.95rem;
    margin-bottom: 14px;
}
.lang-loading-bar-track {
    height: 10px;
    border-radius: 999px;
    background: var(--surface-alt);
    border: 1px solid var(--border);
    overflow: hidden;
}
.lang-loading-bar-fill {
    height: 100%;
    width: 0%;
    border-radius: 999px;
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    transition: width 0.25s ease;
}
.lang-loading-detail {
    margin-top: 10px;
    font-size: 0.8rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* Lightbox für per *img*URL*img* geteilte Bilder (siehe assets/js/chat.js
   openImageLightbox/closeImageLightbox) - vergrößerte Ansicht direkt auf der
   Seite, kein neuer Tab/kein neues Fenster. Schließen per Klick irgendwo im
   Overlay (auch neben dem Bild) oder per Escape-Taste. */
.img-lightbox-overlay {
    position: fixed;
    inset: 0;
    z-index: 70;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: color-mix(in srgb, black 82%, transparent);
    cursor: zoom-out;
}
.img-lightbox-overlay[hidden] { display: none; }
.img-lightbox-img {
    max-width: 100%;
    max-height: 100%;
    border-radius: 10px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
    cursor: default;
}

/* Vorschau-Leiste über dem Composer, solange gerade auf eine Nachricht
   geantwortet wird (siehe assets/js/chat.js startReply/clearReply). */
.reply-preview {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 8px 14px;
    border-top: 1px solid var(--border);
    border-left: 3px solid var(--primary);
    background: var(--surface-alt);
}
.reply-preview[hidden] { display: none; }
.reply-preview-info {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
    font-size: 0.82rem;
}
.reply-preview-author { font-weight: 700; color: var(--primary); flex-shrink: 0; }
.reply-preview-snippet {
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.reply-preview-cancel { flex-shrink: 0; }

/* Vorschau-Leiste über dem Composer für ein per 📎-Button gewähltes, aber noch
   nicht hochgeladenes Bild (siehe assets/js/chat.js setPendingImage/clearPendingImage) -
   der eigentliche Upload passiert erst beim Absenden, sodass man vorher noch ganz
   normal einen begleitenden Text ins Eingabefeld schreiben kann. */
.image-preview-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 14px;
    border-top: 1px solid var(--border);
    border-left: 3px solid var(--primary);
    background: var(--surface-alt);
}
.image-preview-bar[hidden] { display: none; }
.image-preview-thumb {
    width: 40px;
    height: 40px;
    object-fit: cover;
    border-radius: var(--radius);
    border: 1px solid var(--border);
    flex-shrink: 0;
}
.image-preview-hint {
    color: var(--muted);
    font-size: 0.82rem;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.image-preview-cancel { flex-shrink: 0; }

/* Vollflächige Einblendung über .chat-shell, solange eine Bilddatei (per
   Drag & Drop) über das Chatfenster gezogen wird - siehe assets/js/chat.js
   dragenter/dragover/dragleave/drop-Listener auf "shell". Rein visuelles
   Feedback, das eigentliche "Fallenlassen" übernimmt setPendingImage()/
   setPendingImageUrl() genau wie beim 📎-Button. */
.drag-drop-overlay {
    position: absolute;
    inset: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    border: 3px dashed var(--primary);
    pointer-events: none;
}
.drag-drop-overlay[hidden] { display: none; }
.drag-drop-overlay-text {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--primary);
    background: var(--surface);
    padding: 14px 22px;
    border-radius: var(--radius);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.25);
    text-align: center;
}

.composer {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    padding: 12px 14px;
    padding-bottom: max(12px, var(--safe-bottom));
    border-top: 1px solid var(--border);
    background: var(--surface-alt);
}

/* Umschließt Ziehen-Griff + Eingabefeld, damit der Griff per position:absolute
   exakt an dessen oberem Rand sitzen kann (siehe .message-resize-handle unten). */
.message-input-wrap {
    flex: 1;
    position: relative;
    display: flex;
}

/* Kleiner Ziehen-Griff oben am Eingabefeld (siehe assets/js/chat.js
   onResizeStart/onResizeMove) statt der nativen CSS-"resize"-Ecke unten rechts -
   die sitzt browserseitig fest direkt neben dem Senden-Button und lässt sich dort
   nur schwer treffen. Der eigene Griff oben ist deutlich einfacher zu packen. */
.message-resize-handle {
    position: absolute;
    top: -3px;
    left: 50%;
    transform: translateX(-50%);
    width: 36px;
    height: 6px;
    border-radius: 3px;
    background: var(--border);
    cursor: ns-resize;
    z-index: 2;
    touch-action: none;
}
.message-resize-handle:hover,
.message-resize-handle.active { background: var(--primary); }

.composer textarea {
    flex: 1;
    /* max-height deutlich über den 140px des automatischen Mitwachsens, damit
       manuelles Ziehen am Griff oben (siehe .message-resize-handle) auf eine
       größere Höhe möglich ist. Kein natives CSS "resize" mehr - der eigene
       Ziehen-Griff ersetzt es vollständig. */
    resize: none;
    max-height: 50vh;
    min-height: 44px;
    padding: 11px 14px;
    border-radius: 20px;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text);
    font-family: inherit;
    font-size: 0.95rem;
    line-height: 1.35;
    /* Eingabefeld bleibt scrollbar, die Leiste selbst wird komplett
       ausgeblendet (statt nur umgefärbt) - so verschwindet auch der
       native, unfarbige Scrollbalken zuverlässig in jedem Browser. */
    scrollbar-width: none;
}
.composer textarea::-webkit-scrollbar { display: none; }
.composer textarea:focus { outline: none; border-color: var(--primary); }

.composer button {
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    border-radius: 50%;
    border: none;
    background: linear-gradient(135deg, var(--primary), var(--secondary));
    color: white;
    font-size: 1.1rem;
    cursor: pointer;
}
.composer button:active { transform: scale(0.94); }

/* Emoji-Auswahl-Button: bewusst neutral gehalten (wie die übrigen .icon-btn im
   Header), nicht wie der auffällige Senden-Button - deshalb die generische
   ".composer button"-Regel oben hier gezielt überschreiben. */
.composer button.emoji-toggle {
    width: 38px;
    height: 38px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 1.15rem;
}
.composer button.emoji-toggle.active {
    background: color-mix(in srgb, var(--primary) 22%, var(--surface));
    border-color: var(--primary);
}

/* Bild-Upload-Button (📎, /upload-Befehl bzw. Klick öffnet die native
   Dateiauswahl - siehe assets/js/chat.js uploadAndSendImage()). Gleiche
   neutrale Optik wie der Emoji-Button, deshalb dieselbe Überschreibung der
   generischen ".composer button"-Regel. Während des Hochladens (Klasse
   "uploading") halbtransparent + Wartezeiger als einzige Rückmeldung, dass
   gerade etwas passiert - der Button selbst bleibt bewusst klickbar, statt
   sich per disabled zu sperren, damit kein zweiter Klick einfach "verschluckt"
   wirkt, sondern uploadAndSendImage() selbst (Flag "uploading") Mehrfachstarts
   verhindert. */
.composer button.upload-toggle {
    width: 38px;
    height: 38px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 1.05rem;
}
.composer button.upload-toggle.uploading {
    opacity: 0.55;
    cursor: wait;
}

/* Formatierungs-Button (Aa, öffnet .format-picker) - gleiche neutrale Optik wie
   Emoji-/Upload-Button, deshalb dieselbe Überschreibung der generischen
   ".composer button"-Regel. Kleinere Schrift als der Standard-Button, damit
   "Aa" bei 38px Durchmesser nicht gequetscht wirkt. */
.composer button.format-toggle {
    width: 38px;
    height: 38px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 0.95rem;
    font-weight: 700;
}
.composer button.format-toggle.active {
    background: color-mix(in srgb, var(--primary) 22%, var(--surface));
    border-color: var(--primary);
}

/* Popup-Panel mit der Emoji-Auswahl, öffnet sich oberhalb des Composers (siehe
   assets/js/chat.js, buildEmojiPicker()/insertEmojiAtCursor()). Nutzt normale
   Unicode-Emoji-Zeichen statt Bilddateien, deshalb hier auch keine Bild-Assets -
   nur Layout für ein Buttons-Raster. */
.emoji-picker {
    border-top: 1px solid var(--border);
    background: var(--surface-alt);
    max-height: 220px;
    overflow-y: auto;
}
.emoji-picker[hidden] { display: none; }
.emoji-picker-body {
    padding: 10px 14px;
}
.emoji-picker-heading {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
    margin: 12px 0 6px;
}
.emoji-picker-heading:first-child { margin-top: 0; }
.emoji-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(36px, 1fr));
    gap: 2px;
}
.emoji-picker-item {
    border: none;
    background: transparent;
    border-radius: 8px;
    font-size: 1.3rem;
    line-height: 1;
    padding: 6px 0;
    cursor: pointer;
}
.emoji-picker-item:hover,
.emoji-picker-item:focus-visible {
    background: color-mix(in srgb, var(--primary) 16%, transparent);
    outline: none;
}

/* Popup-Panel mit der Formatierungs-Auswahl (Aa-Button), öffnet sich wie
   .emoji-picker oberhalb des Composers - siehe assets/js/chat.js,
   buildFormatPicker()/applyFormatMarker(). Jede Option bekommt eine Vorschau
   im eigenen Stil (fett/kursiv/rot/beides), damit auf einen Blick klar ist,
   was der jeweilige Button bewirkt. */
.format-picker {
    border-top: 1px solid var(--border);
    background: var(--surface-alt);
}
.format-picker[hidden] { display: none; }
.format-picker-body {
    padding: 10px 14px;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.format-picker-item {
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text);
    border-radius: 8px;
    font-size: 0.9rem;
    padding: 8px 14px;
    cursor: pointer;
}
.format-picker-item:hover,
.format-picker-item:focus-visible {
    background: color-mix(in srgb, var(--primary) 16%, var(--surface));
    outline: none;
}
.format-picker-item-bold { font-weight: 700; }
.format-picker-item-italic { font-style: italic; }
.format-picker-item-underline { text-decoration: underline; }
.format-picker-item-bold_italic { font-weight: 700; font-style: italic; }
.format-picker-item-red { color: var(--danger); font-weight: 600; }
.format-picker-item-bold_red { color: var(--danger); font-weight: 700; }
.format-picker-item-blink { animation: msg-blink-anim 1s step-start infinite; }
.format-picker-item-marquee { font-style: italic; }

@media (max-width: 599px) {
    .chat-shell { border-left: none; border-right: none; }
    .msg { max-width: 90%; }
    .emoji-picker { max-height: 180px; }
    .emoji-picker-grid { grid-template-columns: repeat(auto-fill, minmax(32px, 1fr)); }
    .emoji-picker-item { font-size: 1.15rem; }
    .msg-image { max-width: 160px; max-height: 160px; }
    .img-lightbox-overlay { padding: 12px; }
    .format-picker-item { font-size: 0.85rem; padding: 7px 12px; }
}
