#msgDialog {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 10;
    background-color: #00000016;
}
body#page_connectivityCenter:not(.isMobile) #msgDialog {
    background-color: unset;
    top: 7rem;
    margin-top: -7rem;
    pointer-events: none;
}

/* Nur auf index.php ist das Hauptmenü-Grid (#menuBackground, z-index:1000)
   dauerhaft offen — showMenu() läuft beim Laden und die Schließen-Handler
   werden in bodyHeader.tpl entfernt. Das Menü verdeckt damit die Kopfzeile
   inkl. Chat-Icon. Das Icon wird dort bewusst NICHT über das Overlay gehoben:
   auf der Menüseite soll nichts über dem Menü schweben. Ohne die Regel bliebe
   es als abgedunkelter Fleck hinter dem Blur sichtbar, deshalb display:none.

   Wichtig: nur der CONTAINER wird ausgeblendet, das <img id="mailboxIcon">
   bleibt im DOM. mailbox.js hängt seinen kompletten document.ready-Block
   (initMailbox, Nachrichten-Polling, initWebPushNotifications) an
   doesElementExist("#mailboxIcon") — eine reine .length-Prüfung. Würde das
   Element auf index.php gar nicht gerendert, liefe auf der Landeseite nach dem
   Login keine Push-Registrierung. Der Chat ist von jeder anderen Seite aus
   erreichbar (dort ist das Menü geschlossen und die Kopfzeile sichtbar).

   Auf allen anderen Seiten (inkl. connectivityCenter, eingebettet) NICHT
   anfassen — deshalb strikt auf body#page_index gescoped. */
body#page_index #mailboxIconContainer {
    display: none;
}

/* ST11a (#15, 2026-06-29): Höhen wachsen mit der Viewport, statt fixe
   45rem/40rem stehen zu bleiben. Auf großen Bildschirmen wird der Chat
   spürbar höher, ohne dass kleine Bildschirme leiden (max-height schützt). */
#chatList {
    width: 24rem;
    height: calc(100vh - 12rem);
    max-height: 75rem;
    overflow-y: auto;
    overflow-x: hidden;
    flex: 0 0 auto;
}

/* Push-Opt-in-Leiste über der Chatliste. Bedienelemente baugleich zum PWA-Hinweis
   im Menü (#pwaInstallHint, fullMenu.css): gleiche Touch-Targets, gleiches Dismiss-×.
   Textfarbe bewusst anthracite statt blue-text — blue-text auf blue-trans käme nur
   auf ~3,6:1 und verfehlte die 4,5:1 für Fließtext (WCAG 1.4.3). */
#pushOptInBar {
    display: none;   /* renderPushOptInBar() schaltet auf flex */
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    box-sizing: border-box;
    margin-bottom: 0.5rem;
    padding: 0 0.25rem 0 0.75rem;
    border-radius: 1rem;
    background-color: var(--atlantis-blue-trans);
    color: var(--atlantis-anthracite);
    font-size: 1rem;
}

#pushOptInAction {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 3.15rem;   /* Touch-Target 44,1px — Root-Font ist 14px (design_2026.css:53) */
}
#pushOptInAction:hover,
#pushOptInAction:focus-visible {
    text-decoration: underline;
}

#pushOptInAction img {
    width: 1.5rem;
    height: 1.5rem;
    flex-shrink: 0;
}

#pushOptInDismiss {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    min-width: 3.15rem;    /* Touch-Target 44,1px, Aktion ist permanent (localStorage) */
    min-height: 3.15rem;
    color: #8a8d90;        /* >=3:1 auf dem hellen Grund (WCAG 1.4.11) */
    font-size: 1.25rem;
    line-height: 1;
}
#pushOptInDismiss:hover {
    color: var(--atlantis-anthracite);
}

/* Tap-Rückmeldung: auf Touch gibt es keinen :hover, ohne :active bliebe der Tap
   bis zum Öffnen des Dialogs bzw. des nativen Prompts völlig unquittiert. */
#pushOptInAction:active,
#pushOptInDismiss:active {
    opacity: 0.6;
}
#pushOptInAction:focus-visible,
#pushOptInDismiss:focus-visible {
    outline: 0.25rem solid #1f6feb;   /* wie .menuItemTile:focus-visible */
    outline-offset: 0.25rem;
}

/* ST11a (#1a, 2026-06-29): Suche + "Neuer Chat" brauchten gap. */
#chatListToolbar {
    gap: 0.5rem;
    margin-bottom: 0.5rem;
    padding-right: 0.5rem;
}

#chatListSearch {
    background-color: unset;
    height: 100%;
    padding: 0 0.5rem;
    border-radius: 1rem;
}

/* ST11a (AK6): Hierarchie Name vs. Lastmsg. */
#chatList .chatGroupNameList {
    font-weight: bold;
    font-size: 1rem;
    color: var(--atlantis-anthracite);
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

#chatList .chatListItem {
    box-sizing: border-box;
    width: 100%;
    min-height: 3rem;
    padding: 0.5rem;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    border-radius: 0.75rem;
}
/* ST11a (2026-06-30): Name+LastMsg-Spalte (2. child) bekommt flex:1,
   damit alle Namen linksbündig an derselben Stelle starten. Der ursprüngliche
   :first-child-Selector hatte gar nicht gematcht — Avatar ist erstes Kind. */
#chatList .chatListItem > .flexBetweenColumn:nth-child(2) {
    flex: 1;
    min-width: 0;
}
/* ST11a (AK7): Trennlinien zwischen Listen-Items entfernt — Hover + Selected
   liefern die Trennung jetzt rein über Hintergrund-Farben. */
body:not(.isMobile) #chatList .chatListItem:hover {
    background-color: var(--atlantis-blue-trans);
}
#chatList .chatListItem.selected {
    background-color: var(--atlantis-blue-trans);
    border-left: 0.1875rem solid var(--atlantis-blue-text);
}

/* ST11a (AK6): Sekundäre Lastmsg-Zeile (regular, gedämpft). */
#chatList .lastMsg {
    font-size: 0.875rem;
    color: var(--atlantis-anthracite);
    opacity: 0.65;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

#chatList .lastMsgDateTime {
    min-width: 4rem;
    flex: 0 0 auto;
    white-space: nowrap;
    text-align: right;
}

/* ST11a (2026-06-29): Bottom-Row für Unread-Counter + Mute/Block-Indikatoren.
   Verhindert vertikales Übereinander-Stapeln im flexBetweenColumn und lässt
   die Datum-Zeile oben sauber abgesetzt. Items sind rechtsbündig in einer Zeile. */
#chatList .chatListItemBottomRow {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    gap: 0.375rem;
}
#chatList .chatListItem.hasNewMsg .lastMsgDateTime {
    font-weight: bold;
}

/* ST5: Per-item muted-indicator (bell_off icon on chat list rows).
   ST11a fix (2026-06-29): aus absolute Position raus — überdeckte sonst die
   Uhrzeit. Jetzt als normales flex-item rechts unten gestapelt unter dem
   unreadCounter. */
#chatList .chatMutedIndicator {
    display: none;
    height: 0.875rem;
    width: 0.875rem;
    opacity: 0.6;
}
#chatList .chatListItem.muted .chatMutedIndicator {
    display: unset;
}

/* ST5: Chat-header bell-toggle. */
#chatMuteToggle {
    width: 1.25rem;
    height: 1.25rem;
    margin-left: auto;
    margin-right: 0.5rem;
    cursor: pointer;
}
#chatMuteToggle.disabled {
    opacity: 0.4;
    pointer-events: none;
}

/* ST6: Per-item blocked-by-me indicator (block icon on chat list rows).
   ST11a fix (2026-06-29): aus absolute Position raus, gleiche Logik wie
   chatMutedIndicator. Beide stapeln sich rechts unten als flex-items. */
#chatList .chatBlockedByMeIndicator {
    display: none;
    height: 0.875rem;
    width: 0.875rem;
    opacity: 0.6;
}
#chatList .chatListItem.blockedByMe .chatBlockedByMeIndicator {
    display: unset;
}

/* ST-Avatar: pupil photo inside the list avatar circle. Scoped to #chatList so
   the shared global .avatarCircle (header + participant avatars) stays intact.
   The photo overlays the initials (which remain as onerror fallback). */
#chatList .avatarCircle {
    position: relative;
    overflow: hidden;
}
#chatList .avatarPhoto {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
}

/* ST6: Chat-header block-toggle. Sits right of #chatMuteToggle when both
   visible (1-on-1 with pupil/parent opposite). */
#chatBlockToggle {
    width: 1.25rem;
    height: 1.25rem;
    margin-right: 0.5rem;
    cursor: pointer;
}
#chatBlockToggle.disabled {
    opacity: 0.4;
    pointer-events: none;
}

#chatMsgContainer {
    width: 44rem;
    border-left: var(--atlantis-std-border);
    padding: 0 0.5rem;
}

/* Close-X icon top-right of a dialog header (used in main + sub-dialogs). */
.dialogCloseIcon {
    height: 2rem;
    position: absolute;
    right: 0;
}

/* Group-info header section. */
.chatGroupNameClickable {
    width: -webkit-fill-available;
    width: -moz-available;
}

.chatGroupSubHeading {
    font-size: 1.2em;
}

/* Teilnehmer-Name einzeilig mit Ellipsis. Bewusst NICHT global auf
   .noBreakEllipsis, weil die Klasse (undefiniert) auch in Klassenbuch/
   abwesenheit.js genutzt wird — Scope hier auf die Chat-Teilnehmer. */
.chatParticipantMain .noBreakEllipsis {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.participantContainerScroll {
    height: 40rem;
    overflow-y: auto;
    overflow-x: hidden;
}

/* ST12: File-Preview-Strip — Chips der zum Versand vorgemerkten Anhänge. */
.filePreviewHeader {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.5rem;
}
.previewLabel {
    font-size: 0.8125rem;
    color: var(--atlantis-anthracite);
    opacity: 0.7;
}
.filePreviewCloseIcon {
    height: 1rem;
    width: 1rem;
}

/* Unread notification badge on the mailbox icon (bottom-right). */
#mailboxIconContainer {
    position: relative;
    align-self: center;
    line-height: 0;
}
.notificationBadge {
    position: absolute;
    /* In der Icon-Ecke statt darunter: als Überhang war das Badge das am
       weitesten unter die Kopfzeilenkante ragende Element. */
    bottom: 0;
    right: -0.25rem;
    min-width: 1rem;
    height: 1rem;
    padding: 0 0.25rem;
    background-color: var(--atlantis-red);
    color: white;
    border-radius: 0.5rem;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1rem;
    text-align: center;
    box-sizing: border-box;
}

/* Empty-state shown when the chat list has no groups. */
.chatListEmptyState {
    width: 24rem;
    padding: 2rem;
    text-align: center;
    color: var(--atlantis-anthracite);
    font-style: italic;
}

/* CSS-only spinner replacing the 2010-era loading.gif. */
.atlSpinner {
    display: inline-block;
    width: 3rem;
    height: 3rem;
    border: 0.25rem solid var(--atlantis-lightgrey);
    border-top-color: var(--atlantis-blue-text);
    border-radius: 50%;
    animation: atlSpin 0.8s linear infinite;
    box-sizing: border-box;
}
@keyframes atlSpin {
    to { transform: rotate(360deg); }
}

/* Loading spinner overlay (centered in chat container). */
.loadingSpinnerCentered {
    height: 4rem;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;
}
.loadingSpinnerInline {
    height: 4rem;
}

/* New-chat filter dialog: search input + selection table. */
/* Task-1: Fenster auf den border-radius clippen — sonst stehen Titelleiste /
   Inhalt über die Rundung und die Ecken wirken eckig. */
#newChatFilterDialog .dialogWindow {
    overflow: hidden;
}
.newChatSelectionSearchInput {
    line-height: 1.5em;
    margin-bottom: 0.75rem;
    width: 100%;
    box-sizing: border-box;
    border: var(--atlantis-std-border);
    border-radius: 1rem;
    padding: 0.5rem 0.75rem;
    font-family: inherit;
    font-size: 1rem;
}
.newChatSelectionContainerScroll {
    max-height: 70vh;
    overflow-y: auto;
}
.newChatSelectionTable {
    border-collapse: separate;
    border-spacing: 0 2px;
    min-width: 16rem;
    width: 100%;
}

/* Override Picmo emoji-picker positioning: the library adds an inline
   transform: translate(...) that shifts the picker off-screen relative
   to the viewport. Force a fixed position above the typing area and
   disable the library's transform. */
.emoji-picker {
    position: fixed !important;
    transform: none !important;
    z-index: 100;
}
/* F5: Die frühere index-spezifische Anhebung des Emoji-Pickers (z:1002 über dem
   angehobenen Chat-Stack) ist entfallen — der Dialog liegt jetzt auf seinem
   natürlichen z (#msgDialog:10), der an <body> gehängte Picker (z:100) darüber. */
/* content läuft ~18px über seine Box (picmo-Layout) und spillt mit
   overflow:visible in den Preview-Footer → dessen border-top schneidet die
   letzte Emoji-Zeile. clippen (NICHT scrollen, sonst 2. Scrollbar neben der
   inneren .emoji-picker__emojis-Scrollbar). */
.emoji-picker__content {
    overflow: hidden;
}
/* Lupe im Such-Feld vertikal zentrieren — der block-Span erbt eine große
   line-height, die das inline-SVG nach unten drückt. */
.emoji-picker__search-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
}

/* Avatar-Initialen-Kreis (Fallback, wenn kein User-Foto vorhanden).
   ST11a (AK1): default-color bleibt --atlantis-blue-text; deterministisch
   überschrieben durch eine .hue1..8-Klasse aus dem getAvatarHueForId-Hash. */
.avatarCircle {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    background-color: var(--atlantis-blue-text);
    color: white;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 2.5rem;
    text-align: center;
    text-transform: uppercase;
    flex: 0 0 auto;
}
.avatarCircle.hue1 { background-color: var(--avatarHue1); }
.avatarCircle.hue2 { background-color: var(--avatarHue2); }
.avatarCircle.hue3 { background-color: var(--avatarHue3); }
.avatarCircle.hue4 { background-color: var(--avatarHue4); }
.avatarCircle.hue5 { background-color: var(--avatarHue5); }
.avatarCircle.hue6 { background-color: var(--avatarHue6); }
.avatarCircle.hue7 { background-color: var(--avatarHue7); }
.avatarCircle.hue8 { background-color: var(--avatarHue8); }

.chatBubble {
    max-width: 75%;
    align-self: flex-start;
    margin: 0.25rem 0;
}
.chatBubble .msgContainer {
    padding: 0.75rem 1rem;
    background-color: var(--atlantis-lightgrey);
    color: var(--atlantis-anthracite);
    /* ST11a (AK10): Other-Bubble Tail unten-links. */
    border-radius: 1rem 1rem 1rem 0.25rem;
    white-space: pre-wrap;
}
.chatBubble .attachment {
    text-align: center;
}
.chatBubble .attachment .imgAttachment {
    object-fit: contain;
    max-width: 100%;
}
.chatBubble.self {
    align-self: flex-end;
}
/* ST11a (AK9): Self-Bubble in sattem Atlantis-Blau mit weisser Schrift.
   AK10: Tail unten-rechts. Token `--atlantis-blue-text` als Spec-Default
   (WCAG-AA gegen weiss, ~4.6:1) — UI-Experten-Review T2-6. */
.chatBubble.self .msgContainer {
    background-color: var(--atlantis-blue-text);
    color: white;
    border-radius: 1rem 1rem 0.25rem 1rem;
}

/* ST11a (AK8): .msgMeta lebt JETZT IN .msgContainer (siehe Template). */
.chatBubble .msgContainer .msgMeta {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.25rem;
    font-size: 0.75rem;
    color: var(--atlantis-anthracite);
    opacity: 0.7;
}
.chatBubble.self .msgContainer .msgMeta {
    color: rgba(255, 255, 255, 0.85);
    opacity: 1;
}

/* ST11a (AK12): Sender-Header über Other-Bubbles in Gruppen-Chats. */
.bubbleSenderHeader {
    font-size: 0.75rem;
    font-weight: 600;
    margin-bottom: 0.25rem;
    color: var(--avatarHue1);
}
.bubbleSenderHeader.hue1 { color: var(--avatarHue1); }
.bubbleSenderHeader.hue2 { color: var(--avatarHue2); }
.bubbleSenderHeader.hue3 { color: var(--avatarHue3); }
.bubbleSenderHeader.hue4 { color: var(--avatarHue4); }
.bubbleSenderHeader.hue5 { color: var(--avatarHue5); }
.bubbleSenderHeader.hue6 { color: var(--avatarHue6); }
.bubbleSenderHeader.hue7 { color: var(--avatarHue7); }
.bubbleSenderHeader.hue8 { color: var(--avatarHue8); }

/* ST11a (AK13): Read-Status-Häkchen in Self-Bubbles.
   Icon via mask + background-color:currentColor, damit das Häkchen in der
   Bubble-Textfarbe (weiß auf Atlantis-Blau) rendert — die SVGs sind farbig
   bzw. currentColor und kämen als background-image nicht in der Textfarbe.
   sent = einfacher Haken, seen/all = Doppelhaken; all = volle Deckkraft. */
.readStatus {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    vertical-align: middle;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
    -webkit-mask-size: contain;
            mask-size: contain;
}
.readStatus[data-read-state=""]      { display: none; }
.readStatus[data-read-state="sent"]  {
    -webkit-mask-image: url("../images/2025/check.svg");
            mask-image: url("../images/2025/check.svg");
    opacity: 0.6;
}
.readStatus[data-read-state="seen"]  {
    -webkit-mask-image: url("../images/2025/check_double.svg");
            mask-image: url("../images/2025/check_double.svg");
    opacity: 0.6;
}
.readStatus[data-read-state="all"]   {
    -webkit-mask-image: url("../images/2025/check_double.svg");
            mask-image: url("../images/2025/check_double.svg");
    opacity: 1;
}

/* ST11a (AK11): Tages-Trenner. */
.dayDivider {
    display: flex;
    justify-content: center;
    margin: 0.5rem 0;
}
.dayDividerPill {
    padding: 0.25rem 0.75rem;
    background-color: var(--atlantis-lightgrey);
    color: var(--atlantis-anthracite);
    border-radius: 1rem;
    font-size: 0.75rem;
}

/* ST11a (AK3): Numerischer Unread-Counter rechts. Pill mit voll-runden Enden:
   bei 1 Ziffer (min-width = height) ergibt border-radius: 999px einen runden
   Kreis; bei mehrstelligen Zahlen wird die Pille horizontal länger, behält
   aber halbkreis-förmige Enden. Kein box-sizing-Trick nötig — content-box
   lässt das Padding korrekt wirken. */
.unreadCounter {
    display: none;
    min-width: 1.25rem;
    width: fit-content;
    height: 1.25rem;
    padding: 0 0.375rem;
    background-color: var(--atlantis-blue-text);
    color: white;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.25rem;
    text-align: center;
    box-sizing: border-box;
}
#chatList .chatListItem.hasNewMsg .unreadCounter,
.unreadCounter.show {
    display: inline-block;
}

/* ST11a (AK4): Empty-Lastmsg italic-gedämpft. */
.lastMsg .emptyLastmsg {
    font-style: italic;
    opacity: 0.65;
}

/* ST11a (AK14): MIME-Icon-Hook für File-Attachments. */
.fileAttachmentIcon img {
    width: 2rem;
    height: 2rem;
}

/* ST11a (#18, 2026-06-29): Chat-Header höher mit Avatar 3rem (vorher 2.5rem)
   und 2-Zeilen-Text-Stack (Name + Sub-Zeile mit Rolle/Klasse bzw. Teilnehmer-
   Zahl). Vertikales padding + min-height geben dem Header sichtbar mehr
   Präsenz; align-items center hält Avatar/Stack/Actions auf einer Linie. */
#chatHeader {
    border-bottom: var(--atlantis-std-border);
    padding: 0.5rem 0.5rem;
    min-height: 4rem;
    align-items: center;
    box-sizing: border-box;
    gap: 0.5rem;
}

#backToChatistButton {
    height: 2rem;
    width: 2rem;
    padding-right: 1rem;
    margin-right: 1rem;
    border-right: var(--atlantis-std-border);
    display: none;
}

/* ST11a (#18, 2026-06-29): Avatar im Header. 3rem-Kreis, image-Variante
   ebenso quadratisch + abgerundet, beide vertikal zentriert. */
#chatHeaderAvatarWrapper {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
}
#chatHeader #chatHeaderAvatar.avatarCircle {
    width: 3rem;
    height: 3rem;
    line-height: 3rem;
    font-size: 1rem;
}
#customPupilChatImage {
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    object-fit: cover;
}

/* ST11a (#18/#20, 2026-06-29): Name oben, Sub-Zeile (Rolle/Klasse bzw.
   "N Teilnehmer") darunter. Kein Margin am Stack — Padding/Gap regeln
   den Abstand zum Avatar links und den Actions rechts. */
#chatHeaderTextStack {
    flex: 1;
    min-width: 0;
    margin-left: 0.75rem;
    gap: 0;
}

/* Der Textstapel ist so hoch wie der Avatar daneben. Mit flex-start klebt sein
   Inhalt oben — bei zwei Zeilen (Name + Subline) faellt das nicht auf, weil sie
   die Hoehe fuellen, bei leerer Subline (#chatHeaderSubline:empty ist display:
   none) sass der Name dagegen 12px ueber der Avatar-Mitte. Zentriert sitzt er
   in beiden Faellen richtig. */
#chatHeaderTextStack {
    justify-content: center;
}

#chatGroupNameHeader {
    font-weight: bold;
    font-size: 1.0625rem;
    line-height: 1.25rem;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

#chatHeaderSubline {
    font-size: 0.8125rem;
    line-height: 1.125rem;
    color: var(--atlantis-anthracite);
    opacity: 0.65;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}
#chatHeaderSubline:empty {
    display: none;
}

/* ST11a (#19, 2026-06-29): 3-Punkt-Menü-Popup im Header. */
#chatHeaderMenuToggle {
    width: 1.5rem;
    height: 1.5rem;
    margin-right: 0.5rem;
    cursor: pointer;
}
.chatHeaderMenuPopup {
    position: absolute;
    top: 2rem;
    right: 0.5rem;
    background-color: white;
    border: var(--atlantis-std-border);
    border-radius: 0.5rem;
    box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.15);
    z-index: 20;
    min-width: 12rem;
    padding: 0.25rem 0;
}
.chatHeaderMenuItem {
    padding: 0.5rem 1rem;
    cursor: pointer;
    white-space: nowrap;
    font-size: 0.9375rem;
}
.chatHeaderMenuItem:hover {
    background-color: var(--atlantis-blue-trans);
}

#chatGroupInfo {
    width: 16rem;
    border-right: var(--atlantis-std-border);
    margin: 0.5rem 0.5rem 4.5rem 0;
    padding-right: 0.5rem;
}

.chatGroupParticipantsContainer {
    margin-top: 0.5rem;
}

.chatGroupParticipants {
    margin-left: 0.5rem;
}

.chatGroupParticipants>div {
    margin-top: 0.5rem;
}

/* ST11a redesign: Teilnehmer-Zeile — Avatar-Kreis + Name links, Aktions-Icons
   rechts. Flex statt float; Name mit min-width:0 → Ellipsis statt H-Überlauf. */
.chatParticipantRow {
    align-items: center;
    gap: 0.5rem;
    padding: 0.25rem 0;
}
.chatParticipantMain {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    flex: 1 1 auto;
}
.participantAvatar {
    width: 1.75rem;
    height: 1.75rem;
    line-height: 1.75rem;
    font-size: 0.7rem;
}
.chatParticipantActions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    flex: 0 0 auto;
}
/* Alle Aktions-Icons gleich groß + ohne Alt-Margins → die Spalten (Krone /
   Stift / Entfernen) richten sich sauber aus; der Self-Platzhalter matcht die
   Breite des Entfernen-X (überschreibt die Legacy-.placeholderIcon-Regel). */
.chatParticipantActions > img,
.chatParticipantActions > .placeholderIcon {
    width: 1.25rem;
    height: 1.25rem;
    margin: 0;
    flex: 0 0 auto;
}
/* Krone: Admin voll sichtbar, Nicht-Admin gedimmt (Klick = zum Admin machen). */
.chatGroupNoAdminIcon {
    opacity: 0.3;
}
#chatMsgContainer[isAdmin='true'] .chatGroupAdminIcon,
#chatMsgContainer[isAdmin='true'] .chatGroupNoAdminIcon {
    cursor: pointer;
}

/* F19: totes float:right entfernt — die Icons sind flex-Kinder von
   .chatParticipantActions (siehe .chatParticipantActions > img), float wirkt
   dort nicht. */
#chatMsgContainer[isAdmin='true'] .chatGroupCommentingAllowedIcon,
#chatMsgContainer[isAdmin='true'] .chatGroupCommentingDisallowedIcon {
    cursor: pointer;
}
/* Gesperrt zusätzlich zum durchgestrichenen Stift gedimmt — gleiche Sprache wie
   bei der Krone (gedimmt = Recht nicht erteilt) und wie im Neuen-Chat-Dialog. */
.chatGroupCommentingDisallowedIcon {
    opacity: 0.7;
}

.removeParticipantIcon {
    margin-left: 0.5rem;
    cursor: pointer;
    display: none;
}
#chatMsgContainer[isAdmin='true'] .removeParticipantIcon,
#chatMsgContainer[isAdmin='true'] .placeholderIcon,
#chatMsgContainer[isAdmin='true'] #addParticipantButton {
    display: unset;
}

#addParticipantButton {
    display: none;
}

.placeholderIcon {
    height: 1rem;
    width: 1rem;
    margin-left: 0.5rem;
    display: none;
}

#filePreview {
    border-top: var(--atlantis-std-border);
    padding: 0.5rem;
}

#filePreviewStrip {
    display: flex;
    gap: 0.5rem;
    overflow-x: auto;
    padding-bottom: 0.25rem;
}
.filePreviewItem {
    position: relative;
    flex: 0 0 auto;
    width: 5rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
}
.filePreviewItemThumb,
.filePreviewItemIcon {
    width: 4rem;
    height: 4rem;
    object-fit: contain;
    border: var(--atlantis-std-border);
    border-radius: 0.5rem;
    background-color: white;
}
.filePreviewItemName {
    width: 100%;
    font-size: 0.75rem;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.filePreviewItemRemove {
    position: absolute;
    top: -0.375rem;
    right: 0.25rem;
    height: 1rem;
    width: 1rem;
    padding: 0.125rem;
    background-color: white;
    border: var(--atlantis-std-border);
    border-radius: 50%;
}
.filePreviewItemRemove:hover,
.filePreviewCloseIcon:hover {
    background-color: var(--atlantis-blue-trans);
    border-color: var(--atlantis-blue-text);
}
/* Größere Touch-Fläche für die destruktiven Entfernen-Icons auf Mobile. */
body.isMobile .filePreviewItemRemove {
    padding: 0.5rem;
    box-sizing: content-box;
    top: -0.5rem;
}
body.isMobile .filePreviewCloseIcon {
    padding: 0.5rem;
    box-sizing: content-box;
}

/* ST13: Drag&Drop-Overlay über dem Chat-Panel. */
#chatContentContainer {
    position: relative;
}
#chatDropOverlay {
    display: none;
    position: absolute;
    inset: 0;
    z-index: 5;
    /* Overlay darf keine Drag-Events schlucken, sonst flackert dragleave/drop. */
    pointer-events: none;
    align-items: center;
    justify-content: center;
    background-color: var(--atlantis-blue-trans);
    border: 2px dashed var(--atlantis-blue-text);
    border-radius: 1rem;
}
#chatDropOverlay.visible {
    display: flex;
}
.chatDropOverlayInner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    color: var(--atlantis-blue-text);
    font-size: 1rem;
    pointer-events: none;
    /* Eigene Karte, damit Icon/Text auch über blauen Self-Bubbles lesbar bleiben. */
    background-color: white;
    padding: 1.5rem 2rem;
    border-radius: 1rem;
    box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.15);
}
.chatDropOverlayIcon {
    height: 3rem;
    width: 3rem;
}

#chatContent {
    height: calc(100vh - 17rem);
    max-height: 70rem;
    overflow-y: auto;
    margin: 2px 0;
    padding: 0 0.5rem;
}

/* ST11a (2026-06-29): Empty-State für komplett leere Chats — zentrierte
   dezente Hinweis-Box anstelle einer komplett weißen Fläche. */
#chatContent .chatEmptyState {
    margin: auto;
    text-align: center;
    color: var(--atlantis-anthracite);
    opacity: 0.6;
    padding: 1.5rem;
    font-size: 0.9375rem;
    line-height: 1.4;
}
#chatContent .chatEmptyState .chatEmptyStateCreated {
    margin-bottom: 0.5rem;
}
#chatContent .chatEmptyState .chatEmptyStatePrompt {
    font-style: italic;
}

/* ST11a (2026-06-30): Hinweistext für nicht-mehr-verfügbare Anhänge in
   einer Bubble (Server lieferte 404/Error). Keine Klickfläche mehr,
   nur dezenter italic-Text mit Dateinamen. */
.chatBubble .attachmentUnavailable {
    font-style: italic;
    opacity: 0.7;
    padding: 0.5rem;
    cursor: default;
}
#chatContent.previewOpen {
    height: calc(50vh - 8rem);
    max-height: 32rem;
}

/* ST11a (AK8/AK12): The old pipe-separator `.chatBubble:not(.self) .msgSender`
   has been removed — sender names now live in `.bubbleSenderHeader` ABOVE the
   bubble for Other-Bubbles in group chats, and `.msgMeta` sits INSIDE the
   bubble for the timestamp + read-status. */

/* Chat typing area: emoji + attach + textarea + send-button in one row.
   ST11a (#24, 2026-06-30): Klare Trennung zum Chat-Bereich über border-top —
   kein zusätzlicher Hintergrund-Strip, der mit den runden Dialog-Ecken
   bricht. Horizontal mehr padding damit die Icons nicht am Rand kleben. */
#chatTypingArea {
    border-top: var(--atlantis-std-border);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    box-sizing: border-box;
}

.chatTypingIcon {
    width: 1.5rem;
    height: 1.5rem;
    flex: 0 0 auto;
}

/* ST11a (#22, 2026-06-30): Textarea wächst mit dem Inhalt (autoGrow via JS).
   min-height = 2.5rem, max-height begrenzt auf ~6 Zeilen damit der Composer
   nicht den Chat-Bereich überrollt. line-height auf normales Verhältnis
   damit mehrzeilig vernünftig aussieht. */
#chatTextarea, #chatTextareaDummy {
    flex: 1;
    min-width: 0;
    min-height: 2.5rem;
    max-height: 9rem;
    resize: none;
    border: var(--atlantis-std-border);
    border-radius: 1rem;
    padding: 0.5rem 0.75rem;
    box-sizing: border-box;
    line-height: 1.4;
    font-family: inherit;
    font-size: 1rem;
    background-color: white;
}
#chatTextareaDummy {
    outline: none;
    text-align: center;
}

/* ST11a (#3, 2026-06-29): Send-Button als sauberer runder Atlantis-blauer
   Kreis mit klar erkennbarem Pfeil — Pfeil-Icon kleiner, damit es nicht den
   Button-Rand berührt; volle --atlantis-blue-text-Farbe statt blass. */
#sendChatMsgButton {
    flex: 0 0 auto;
    width: 3.5rem;
    height: 3.5rem;
    padding: 0;
    border-radius: 50%;
    background: var(--atlantis-blue-text);
    border: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
#sendChatMsgButton:hover:not(:disabled) {
    background: var(--atlantis-blue-selected);
    border: 0;
}
#sendChatMsgButton img {
    width: 2.5rem;
    height: 2.5rem;
    filter: brightness(0) invert(1);
}

/* Mobile: typing area pinned to viewport bottom. position:sticky alone
   does not work when the chat scroll-container is taller than the viewport
   (the bar then sits at the container bottom, below the visible area).
   position:fixed guarantees visibility regardless of scroll state. */
body.isMobile #chatTypingArea {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: white;
    border-top: var(--atlantis-std-border);
    box-sizing: border-box;
    z-index: 11;
}
/* B2 fix: Im Mobile-Listen-View (kein Chat offen, .mobileChatOpen fehlt) darf
   der position:fixed-Composer nicht sichtbar sein — sonst entkommt er dem
   overflow:hidden-Clip der weggeschobenen Chat-Spalte und klebt in der Liste. */
body.isMobile #msgDialog:not(.mobileChatOpen) #chatTypingArea {
    display: none;
}
body.isMobile #chatContent {
    padding-bottom: 4rem;
    box-sizing: border-box;
}
body.isMobile #sendChatMsgButton {
    width: 3rem;
    height: 3rem;
}

/* ST11a (#27, 2026-06-30): Touch-Targets ≥44px (3rem ≈ 42px bei 14px base,
   reicht knapp; padding um das Icon vergrössert die hitbox). */
body.isMobile .chatTypingIcon {
    width: 1.75rem;
    height: 1.75rem;
    padding: 0.5rem;
    box-sizing: content-box;
}

/* Der Dummy tritt an die Stelle der echten Bedienelemente, sobald einer der drei
   Sperrgruende greift. Sein :not() muss deshalb ALLE drei ausnehmen — sonst waere
   bei fehlender Chat-Auswahl weder das echte Textfeld (unten ausgeblendet) noch
   der Dummy sichtbar und die Zeile bliebe leer. */
#chatMsgContainer[commentingAllowed='false'] #emoji-button,
#chatMsgContainer[commentingAllowed='false'] #addAttachmentButton,
#chatMsgContainer[commentingAllowed='false'] #chatTextarea,
#chatMsgContainer[commentingAllowed='false'] #sendChatMsgButton,
#chatMsgContainer[commentingAllowed='true']:not([blockedByOther='true']):not([noChatSelected='true']) #chatTextareaDummy,
#chatMsgContainer[blockedByOther='true'] #emoji-button,
#chatMsgContainer[blockedByOther='true'] #addAttachmentButton,
#chatMsgContainer[blockedByOther='true'] #chatTextarea,
#chatMsgContainer[blockedByOther='true'] #sendChatMsgButton,
#chatMsgContainer[noChatSelected='true'] #emoji-button,
#chatMsgContainer[noChatSelected='true'] #addAttachmentButton,
#chatMsgContainer[noChatSelected='true'] #chatTextarea,
#chatMsgContainer[noChatSelected='true'] #sendChatMsgButton {
    display: none;
}

/* Task-1: Auswahl-Liste an den programmweiten Standard angeglichen — identisch
   zu #genericFilteredSelection (Klassenbuch/Schülerliste): graues Zebra, volle
   Blau-Auswahl mit weißer Schrift; die runden Zeilenecken liefert .tableDesign. */
#newChatSelection tr {
    vertical-align: top;
    cursor: pointer;
}

#newChatSelection tr.oddRow {
    background-color: var(--atlantis-lightgrey);
}

#newChatSelection tr.selected {
    background-color: var(--atlantis-blue);
    color: white;
}

#newChatSelection td {
    padding: 0.25rem 0.5rem;
}

/* Erste SICHTBARE Zelle links runden: .tableDesign td:first-child trifft die
   ausgeblendete .hidden-Zelle (display:none), daher hier explizit auf
   .displayValue — sonst bleiben die linken Ecken eckig. */
#newChatSelection td.displayValue {
    border-top-left-radius: 1rem;
    border-bottom-left-radius: 1rem;
}

#newChatSelection .classDisplay,
#newChatSelection .courseDisplay {
    white-space: pre-wrap;
}

.newChatFilterDisplay {
    /* Die ganze Box öffnet die Auswahl (Handler in initMailbox), nicht nur die
       Lupe daneben — sie sieht aus wie ein Eingabefeld. */
    cursor: pointer;
    width: 16rem;
    border: var(--atlantis-std-border);
    border-radius: 1rem;
    white-space: pre-wrap;
    max-height: 6rem;
    /* Leere Box genauso hoch wie eine mit einem Teilnehmer — sonst sind die
       Felder untereinander unterschiedlich hoch, obwohl sie wie gleichartige
       Eingabefelder aussehen. Der Wert MUSS der line-height der Box
       entsprechen: hier die geerbte 2.5rem aus der globalen td-Regel, auf
       Mobile die dort gesetzten 2.2em (siehe body.isMobile-Block weiter unten).
       line-height hier explizit, obwohl sie dieselbe ist wie die geerbte
       td-Regel: sonst haengt die Box-Hoehe unsichtbar an design_2026.css. */
    line-height: 2.5rem;
    min-height: 2.5rem;
    float: left;
    overflow-y: auto;
    padding: 0.25rem 0.75rem;
    margin: 0.5rem 0.75rem;
}

.newChatGroupNameRow > td {
    border-top: var(--atlantis-std-border);
    padding-top: 1rem;
}

.newChatGroupNameRow > td:nth-child(2) {
    padding-right: 0.75rem;
}

.newChatGroupNameInput {
    width: 100%;
    box-sizing: border-box;
    margin: 0.5rem 0;
}

/* Eine Teilnehmerzeile in den Auswahl-Boxen (#newParticipantTemplate-Klon):
   Name links, Kommentier-Toggle rechtsbündig auf gleicher Höhe.
   Bewusst KEIN float für die Icons: die Icons sind 32px hoch, eine Zeile aber
   nur ~31px — der 1px Überstand ragte in die nächste Zeile und schob deren
   Float um eine volle Icon-Breite nach links (je Zeile ein anderer rechter
   Rand). Flex hat das Problem nicht und zentriert das Icon zum Namen. */
.newChatFilterDisplay > div[selectionID] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

/* Namen einzeilig mit Ellipsis — gleiche Behandlung wie in der Gruppen-
   Teilnehmerliste (.chatParticipantMain .noBreakEllipsis). Umbrechende Namen
   wären hier schädlich: das Icon zentriert dann gegen die GESAMTE mehrzeilige
   Zeile und schwebt mitten im Namen statt neben der ersten Zeile.
   min-width: 0 hebt die Flex-Mindestbreite auf, sonst greift text-overflow
   nicht und der Name drückt das Icon aus der Box. */
.newChatFilterDisplay > div[selectionID] > .displayName {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.allowCommentButton,
.disallowCommentButton {
    flex: none;
    width: 1.5rem;
    height: 1.5rem;
    /* Padding statt größerem Icon: vergrößert die Trefferfläche auf 2rem,
       ohne die Zeile optisch aufzublähen. */
    padding: 0.25rem;
    cursor: pointer;
}

/* Gesperrt-Zustand zusätzlich zum durchgestrichenen Stift leicht abgedunkelt —
   der Unterschied bleibt so auch ohne Farbwahrnehmung erkennbar. */
.disallowCommentButton {
    opacity: 0.7;
}

/* Erklärt den Toggle im Dialog selbst — aber NUR auf Mobile und nur, solange
   Teilnehmer ausgewählt sind (Klasse von updateNewChatCommentHint). Auf Desktop
   liefert der Tooltip am Stift dieselbe Erklärung; initTooltip (global.js)
   haengt Tooltips ausschliesslich ausserhalb von isMobile ein, deshalb braucht
   es die Zeile genau dort, wo der Tooltip fehlt. */
.newChatCommentHint {
    display: none;
    align-items: center;
    gap: 0.5rem;
    /* linksbündig mit der Label-Spalte der Filter-Tabelle */
    margin: 0.5rem 0.75rem 0 0;
    font-size: 0.8rem;
    /* eigene line-height: die geerbten 1.8rem der Tabelle ergeben bei 0.8rem
       Schrift Faktor 2,25 — die zwei Zeilen wirken dann zusammenhanglos. */
    line-height: 1.4;
    /* NICHT --atlantis-darkgrey: auf Weiß nur 1,86:1 Kontrast. Dieser Text soll
       gelesen werden, deshalb dieselbe Farbe wie die Feld-Labels daneben. */
    color: grey;
    /* Der Dialog ist Shrink-to-fit: ohne Deckel setzt diese Zeile auf Desktop
       die Dialogbreite (gemessen 694px statt 453px) und reisst ein totes Feld
       rechts neben dem Formular auf. Der Wert MUSS unter der Breite der
       Filter-Tabelle (26,5rem) bleiben — auch bei längeren Übersetzungen. */
    max-width: 26rem;
}

body.isMobile .newChatCommentHint.hasParticipants {
    display: flex;
}

.newChatCommentHint > img {
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
}

.loadingMoreMsgsIndicator {
    text-align: center;
}

#customPupilChatImageClone {
    max-height: 10rem;
    max-width: 100%;
    object-fit: contain;
    margin-bottom: 0.5rem;
}

#chatContentContainer {
    width: -webkit-fill-available;
    width: -moz-available;
}


/* --------------------------- Mobile Start --------------------------------------------- */


body.isMobile #fullMenu {
    overflow-y: scroll;
    max-height: 97vh;
}

/* ST11a (#26): Auf Mobile sitzt der Chat-Dialog UNTER der (sticky) globalen
   App-Kopfzeile statt sie zu überlappen — Offset via --mobile-header-height
   (in global.js aus #head.offsetHeight gesetzt). Gilt gleichermaßen für die
   connectivityCenter-Seite und den Header-Icon-Dialog (identische View). */
body.isMobile #msgDialog {
    top: var(--mobile-header-height, 80px);
    margin-top: 0;
    width: 100%;
    height: calc(100% - var(--mobile-header-height, 80px));
    box-sizing: border-box;
}

/* F17 (UIUX-N2): Chat auf Mobile ECHT vollflächig, solange er offen ist
   (Body-Marker mbxDialogOpen — gesetzt in afterOpenMailboxDialog, entfernt in
   hideMailboxDialog, auch auf dem Zurück-Button-Pfad, siehe mailbox.js History-
   Swap). Der Dialog rückt auf top:0 und deckt die volle Viewport ab.
   Die darunterliegenden Sticky-Header haben ein höheres z als der Dialog
   (#msgDialog z:10) und würden sonst als Streifen über der dunklen Chat-
   Titelleiste durchstechen:
     #head               (z:200, global auf allen Seiten)
     #pupilListToggleRow (z:101, "Auswahl ◀"-Umschalter auf Listen-Seiten wie stundenplan)
     #pupilTabs          (z:50,  Schüler-Tabs)
   → für die Dauer des offenen Chats ausblenden; beim Schließen kommt alles zurück.
   Der Chat hat auf Mobile eine eigene Titelleiste, #head ist also entbehrlich.
   Der Dialog-Stack wird bewusst NICHT angehoben (wie F5): die Confirms
   (jQuery-UI .ui-front z:100) liegen so weiterhin über dem Dialog (z:10).
   Rest-Grenze: eine Seite mit einer EIGENEN, anders benannten Sticky-Top-Toolbar
   (z>10) außerhalb dieser drei IDs würde weiterhin einen Streifen zeigen — auf
   den heute existierenden Seiten decken diese drei alle persistenten Top-Stickies ab.

   connectivityCenter ausgenommen: dort IST der Chat die Seite (kein Schließen-X),
   #head bleibt als einzige Navigation stehen und der Chat sitzt bewusst darunter
   (Review N2: von connectivityCenter aus bereits sauber). */
body.isMobile.mbxDialogOpen:not(#page_connectivityCenter) #msgDialog {
    top: 0;
    height: 100%;
}
body.isMobile.mbxDialogOpen:not(#page_connectivityCenter) #head,
body.isMobile.mbxDialogOpen:not(#page_connectivityCenter) #pupilListToggleRow,
body.isMobile.mbxDialogOpen:not(#page_connectivityCenter) #pupilTabs {
    display: none;
}

/* Auf connectivityCenter ist der Chat die Seite selbst, kein Dialog: das
   Schliessen-X blendet initConnectivityCenterPage aus, uebrig bliebe eine
   53px hohe Leiste mit dem blossen Wort "Chat" — waehrend #head darueber die
   Seite ohnehin schon benennt. Auf einem 412x915-Geraet gingen so 123px (13 %
   der Viewport-Hoehe) verloren, bevor der erste Listeneintrag beginnt.
   Nur mobil: auf Desktop ist der Platz da und die Leiste rahmt den Dialog. */
body#page_connectivityCenter.isMobile #msgDialog > .dialogWindow > .dialogWindowTitle {
    display: none;
}

body.isMobile #msgDialog.customDialog .dialogWindow {
    max-height: unset;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    box-sizing: border-box;
    /* Mobil fuellt das Chat-Fenster die volle Flaeche — die 1rem-Rundung der
       globalen .dialogWindow-Regel hat dann nichts mehr zu runden und legt in
       den vier Ecken den Overlay-Schleier von #msgDialog (rgba(0,0,0,0.086))
       frei. Vorher verdeckte die dunkle Titelleiste das oben; seit sie auf
       connectivityCenter entfaellt, sassen dort vier graue Flecken. */
    border-radius: 0;
}

body.isMobile #msgDialog .dialogWindow .dialogHeader:not(.dialogScrollable) {
    display: none;
}

body.isMobile #msgDialog .dialogWindow .dialogScrollable,
body.isMobile #mailboxDialogContent,
body.isMobile #chatSplitView,
body.isMobile #chatList,
body.isMobile #chatContent {
    height: 100%;
}

body.isMobile #chatList {
    width: 100%;
}

body.isMobile #chatListContainer,
body.isMobile #chatListToolbar,
body.isMobile #chatMsgContainer,
body.isMobile #msgNewChatDialog .dialogWindow,
body.isMobile #newChatFilterDialog .dialogWindow {
    width: 100%;
    box-sizing: border-box;
}

/* Listen- und Chat-Spalte liegen beide mit width: 100% im nowrap-Flex
   #chatSplitView (overflow: hidden traegt die Slide-Animation). Der Bedarf
   betraegt damit 200 % der Containerbreite, und ohne flex-shrink: 0 schrumpft
   Flexbox beide bis auf ihre min-content-Breite. Wie breit die Liste dann
   tatsaechlich rendert, haengt allein an der Textlaenge der Eintraege: bei
   langen Chatnamen liegt min-content ueber der Viewportbreite und die Spalte
   sieht zufaellig korrekt aus, bei kurzen Namen bleibt sie sichtbar zu schmal
   (min-content von #chatListToolbar) und der Zurueck-Pfeil ragt heraus. */
body.isMobile #chatListContainer,
body.isMobile #chatMsgContainer {
    flex-shrink: 0;
}

/* Mi2 fix: "Neuen Chat erstellen" auf Mobile unter die App-Kopfzeile setzen
   (statt vertikal zentriert dahinter), damit die Kopfzeile den Dialog nicht
   überlappt. Fenster behält Titelleiste, X und natürliche Höhe. */
body.isMobile #msgNewChatDialog {
    align-items: flex-start;
    /* F16 (UIUX-N1): etwas mehr Abstand nach oben, damit die Titelzeile nicht
       am oberen Rand angeschnitten wirkt. */
    padding-top: calc(var(--mobile-header-height, 80px) + 1rem);
    box-sizing: border-box;
}

/* F18 (UIUX-N3): "Neuer Chat"-Button auf Mobile einzeilig halten (bricht sonst
   zu "Neuer" / "Chat"). */
body.isMobile #newChatButtonWrapper .ui_like_button {
    white-space: nowrap;
}

/* F19: Empty-State-Box hat eine feste Breite (24rem = 384px inkl. Padding) und
   läuft auf schmalen Viewports (≤375px) horizontal über — auf Mobile die
   Spaltenbreite übernehmen. */
body.isMobile .chatListEmptyState {
    width: 100%;
    box-sizing: border-box;
}

/* ST11a (#25, 2026-06-30): Mobile — der äussere #chatSplitView-Wrapper soll
   auf einem schmalen Viewport NICHT scrollen, sondern die List- und Chat-
   Spalte exklusiv anzeigen. overflow:hidden cuts der Slide-Animation den
   Restschwanz ab, sodass die Liste nicht "links angeschnitten" sichtbar
   bleibt. */
body.isMobile #chatSplitView {
    overflow: hidden;
}

/* F20: Filter-Tabelle auf Mobile als Flex-Zeilen statt als Tabelle.

   Ausgangsproblem: .newChatFilterDisplay IST die mittlere Tabellenzelle; erst
   float: left macht daraus eine Block-Box, damit margin/border-radius greifen.
   Zusammen mit der festen Box-Breite (16rem, 249px inkl. Rahmen), der
   nowrap-Label-Spalte (120px) und der Lupe (32px) brauchte die Tabelle 424px
   Mindestbreite — in einem 384px breiten Dialoginhalt (412px Viewport) lag die
   Lupe damit ausserhalb des sichtbaren Bereichs und war auf Touch praktisch
   nicht erreichbar. Ohne Lupe ist der Dialog nicht bedienbar.

   Loesung: Tabelle und tbody werden zu Bloecken, jede Zeile zu einem
   Flex-Container. Flex-Items werden blockifiziert — die Box bleibt also eine
   Block-Box mit wirksamen Margins. (Wuerde man stattdessen nur float: none
   setzen, faellt die Zelle auf display: table-cell zurueck, Margins wirken
   nicht mehr und die Boxen kleben randlos als Gitter aneinander.)
   Label und Lupe behalten ihre Breite, die Box bekommt den Rest (flex: 1) und
   darf beliebig schmal werden (min-width: 0, zusaetzlich eigener
   Scroll-Container durch overflow-y) — die Zeile passt damit bei JEDER
   Viewport-Breite in den Dialog.

   Das nowrap der frueheren Label-Regel (F16) entfaellt: es war noetig, weil ein
   zweizeiliges Label die Lupe in der Tabellenzeile nach unten schob. Mit
   align-items: center sitzt die Lupe unabhaengig von der Label-Hoehe mittig. */
body.isMobile #newChatFilterTable,
body.isMobile #newChatFilterTable > tbody {
    display: block;
    width: 100%;
}

body.isMobile #newChatFilterTable .newChatFilterContainer,
body.isMobile #newChatFilterTable .newChatGroupNameRow {
    display: flex;
    align-items: center;
}

/* Label-Spalte: feste Breite statt Tabellenspalte — nur so bleiben die Boxen
   aller Zeilen buendig (Flex-Zeilen kennen einander nicht). 9rem traegt das
   laengste Label "Eltern einer Klasse" (120px) einzeilig. Kein min-width: 0 —
   die automatische Mindestbreite (laengstes Wort) ist hier erwuenscht: das
   Label bricht um, statt seinen Text aus der Zelle laufen zu lassen. */
body.isMobile #newChatFilterTable .newChatFilterContainer > td:first-child,
body.isMobile #newChatFilterTable .newChatGroupNameRow > td:first-child {
    flex: 0 1 9rem;
}

/* Auswahl-Box und Gruppenname-Feld bekommen den gesamten Rest der Zeile
   (flex-basis 0) und duerfen dabei beliebig schmal werden (min-width: 0).
   Genau das ersetzt die feste 16rem-Breite: statt die Zeile zu sprengen,
   schrumpft die Box mit dem Viewport. Ihr Inhalt kann sie nicht aufblaehen —
   sie ist durch overflow-y ein eigener Scroll-Container. */
body.isMobile #msgNewChatDialog .newChatFilterDisplay,
body.isMobile #newChatFilterTable .newChatGroupNameRow > td:nth-child(2) {
    flex: 1;
    min-width: 0;
}

/* float: left und width: 16rem aus der Desktop-Basisregel bleiben stehen, sind
   hier aber wirkungslos: an einem Flex-Item wird float ignoriert, und flex: 1
   (flex-basis 0) schlaegt die width. Bewusst nicht zurueckgesetzt — beides
   traegt auf Desktop weiterhin das Layout. */
body.isMobile #msgNewChatDialog .newChatFilterDisplay {
    margin: 0.75rem;
    line-height: 2.2em;
    /* muss der line-height dieser Regel folgen, siehe Basisregel */
    min-height: 2.2em;
}

/* Lupen-Spalte behaelt ihre natuerliche Breite (32px Touch-Ziel). */
body.isMobile #newChatFilterTable .newChatFilterContainer > td:last-child {
    flex: none;
}

/* Trennlinie ueber der Gruppenname-Zeile: als border-top je Zelle saesse sie
   wegen align-items: center auf unterschiedlichen Hoehen und waere
   unterbrochen — deshalb auf die Zeile selbst. */
body.isMobile #newChatFilterTable .newChatGroupNameRow {
    border-top: var(--atlantis-std-border);
    padding-top: 1rem;
}

body.isMobile #newChatFilterTable .newChatGroupNameRow > td {
    border-top: 0;
    padding-top: 0;
}

body.isMobile #newChatSelection td {
    padding: 0.75rem 0.5rem;
}

body.isMobile #chatMsgContainer {
    border-left: 0;
}

/* Die Trennlinie unter dem Chat-Header soll wie die ueber der Eingabezeile bis
   an beide Raender laufen. #chatTypingArea schafft das, weil es mobil fixed und
   volle Viewport-Breite ist; #chatHeader steht dagegen im Fluss und erbt seinen
   Einzug von .dialogScrollable (1rem je Seite) und #chatMsgContainer (0.5rem).

   Ein negativer Margin am Header allein reicht NICHT: #chatSplitView hat mobil
   overflow: hidden (fuer die Slide-Animation) und schneidet alles ab, was ueber
   seine Kante hinausragt — die Layout-Box laege bei 0..412, gezeichnet wuerde
   trotzdem nur 14..398. Deshalb faellt das seitliche Padding von
   .dialogScrollable mobil weg; den Abstand tragen die Elemente, die ihn wirklich
   brauchen (Suchzeile, Listeneintraege, Bubbles) selbst. */
body.isMobile #msgDialog > .dialogWindow > .dialogScrollable {
    padding-left: 0;
    padding-right: 0;
}

/* Auch die Spalten selbst laufen mobil bis an den Rand — den Innenabstand
   bringt jede Zeile mit (Listeneintrag 0.5rem, #chatHeader 0.5rem aus seiner
   Grundregel, Suchzeile siehe unten). So stehen Zurueck-Pfeil, Avatare der
   Listeneintraege und Suchfeld auf derselben Kante, und keine Trennlinie hoert
   vor dem Rand auf. */
body.isMobile #chatMsgContainer {
    padding-left: 0;
    padding-right: 0;
}

/* #chatListToolbar traegt nur rechts Padding (fuer den Scrollbalken der Liste
   daneben). Randbuendig gestellt fehlt links jeder Abstand, waehrend rechts
   zu viel bleibt — deshalb mobil symmetrisch auf die Kante der Listeneintraege. */
body.isMobile #chatListToolbar {
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}

body.isMobile #chatList .chatListItem {
    margin-right: unset;
}

body.isMobile #chatMsgContainer {
    padding-bottom: 0.5rem;
}

body.isMobile #chatPaneRow {
    height: calc(100% - 2.5rem);
}

body.isMobile #chatMessagePane {
    height: calc(100% - 4.25rem);
}

/* Kein eigener Rechts-Abstand mehr: den bringt jetzt das symmetrische Padding
   von #chatListToolbar mit. Sonst endete der "Neuer Chat"-Button 10px vor der
   rechten Kante der Datumsspalte darunter. */
body.isMobile #newChatButtonWrapper {
    margin-right: 0;
}

/* ST11a (#28, 2026-06-30): Back-Button im Mobile-Chat-Header — sichtbar
   mit hervorgehobenem runden Hintergrund (touch-Target ≥44px). */
body.isMobile #backToChatistButton {
    display: block;
    height: 2rem;
    width: 2rem;
    padding: 0.375rem;
    box-sizing: content-box;
    border-right: 0;
    margin-right: 0.5rem;
    flex: 0 0 auto;
    cursor: pointer;
}

body.isMobile #chatContentContainer {
    width: 100%;
    box-sizing: border-box;
}

body.isMobile #chatGroupInfo {
    width: 0vw;
    margin-top: 1rem;
    border-right: 0;
}

body.isMobile .chatGroupParticipantsContainer,
body.isMobile .chatGroupParticipants>div {
    margin-top: 1rem;
}

body.isMobile #addParticipantButton,
body.isMobile .chatGroupAdminIcon,
body.isMobile .chatGroupNoAdminIcon,
body.isMobile .chatGroupCommentingAllowedIcon,
body.isMobile .chatGroupCommentingDisallowedIcon,
body.isMobile .removeParticipantIcon,
body.isMobile .placeholderIcon {
    margin-right: 1.25rem;
}


/* --------------------------- Mobile End ----------------------------------------------- */
