/* ============================================================================
   shell.css — die Shell.  Gruppe 1

   Regelwerk: docs/redesign/STIL.md · Layout: docs/redesign/STEP_01_SHELL.md
   Register: comfort

   WAS HIER STEHT
   --------------
   Der Rahmen, in dem die Kanäle liegen: linke Leiste, Kopfzeile, rechte
   Leiste, Nutzerzeile. Kein Kanalinhalt — Chat, Journal und Scanner sind
   Gruppe 2, 3 und 4. Auch die Überlagerungen, die zwar in `index.html`
   stehen, aber laut STEP_01_SHELL.md §5 nicht zu dieser Gruppe gehören
   (Einstellungsdialog, Posteingang, Anmeldefenster, Bestätigungsfenster),
   bleiben vorerst in `theme.css`.

   KASKADE
   -------
   `@layer channels` — nach `components` und vor `overrides`. Die
   Reihenfolge steht in `tokens.css`:

       @layer tokens, base, components, channels, overrides;

   `theme.css` ist unbeschichtet und gewinnt gegen jede Schicht. Deshalb
   sind die hier übernommenen Regeln in `theme.css` **gelöscht** worden,
   nicht bloß überschrieben. Was dort noch steht, gehört einer anderen
   Gruppe.

   FARBEN
   ------
   Vollständig über Tokens. Kein Hexwert, kein rgba() in dieser Datei —
   `tests/check_redesign_coverage.py --gruppe 1` prüft das.

   KONTRAST — was wo stehen darf
   -----------------------------
   Gemessen gegen die tatsächliche Fläche, Soll 4,5 : 1:

       --ink-muted auf --surface-canvas    5,05 : 1   ✓
       --ink-muted auf --surface-raised    4,56 : 1   ✓
       --ink-muted auf --surface-selected  4,41 : 1   ✗
       --ink-muted auf --surface-hover     4,17 : 1   ✗

   Also: `--ink-muted` nur auf Flächen, die nicht überfahren oder gewählt
   werden können. Überall sonst `--ink-secondary` (12,6 : 1 auf canvas).
   Das ist der Grund, warum unten an mehreren Stellen `--ink-secondary`
   steht, wo `--ink-muted` naheläge.
   ========================================================================= */

@layer channels {

    /* ====================================================================
       1 · Der Rahmen
       ==================================================================== */

    .app-container {
        /* 256 → 240 und 224 → 208 (STEP_01_SHELL.md §3.1 und §3.3). Die
           beiden Werte sind veränderlich: der Nutzer zieht die Leisten,
           das JavaScript schreibt sie als Inline-Stil auf dieses Element. */
        --left-panel-width: 240px;
        --right-panel-width: 208px;
        --panel-resizer-width: 6px;
        display: flex;
        block-size: 100vh;
        block-size: 100dvh;
        inline-size: 100vw;
    }

    /* Der Ziehgriff zwischen den Flächen. Er ist 6 px breit, sieht aber
       aus wie eine Haarlinie — die Trefferfläche ist größer als das, was
       man sieht. */
    .panel-resizer {
        position: relative;
        z-index: var(--z-sticky);
        flex-shrink: 0;
        inline-size: var(--panel-resizer-width);
        margin-inline: calc(var(--panel-resizer-width) / -2);
        background: transparent;
        cursor: col-resize;
        touch-action: none;
        user-select: none;
    }

    .panel-resizer::before {
        content: "";
        position: absolute;
        inset-block: 0;
        inset-inline-start: 50%;
        inline-size: 1px;
        background: var(--line-strong);
        opacity: 0;
        transform: translateX(-50%);
        transition: opacity var(--dur-instant) var(--ease-standard);
    }

    /* Der alte Zustand war ein blauer Schein aus zwei Werten, die in
       keinem Token standen (AUDIT_IST.md §2b). Jetzt: dieselbe Haarlinie
       wie überall, nur sichtbar. */
    body.is-resizing .panel-resizer::before,
    .panel-resizer:focus-visible::before {
        opacity: 1;
    }

    @media (hover: hover) and (pointer: fine) {
        .panel-resizer:hover::before { opacity: 1; }
    }

    /* Der Fokusring kommt aus base.css und wird NICHT weggenommen (S2).
       `outline: none` stand hier vorher. */

    body.is-resizing,
    body.is-resizing * {
        cursor: col-resize;
    }

    /* ====================================================================
       2 · Linke Leiste
       `--surface-canvas` — sie ist die untere Ebene, der Inhalt liegt
       darüber (R1).
       ==================================================================== */

    .channel-list {
        display: flex;
        flex-direction: column;
        flex-shrink: 0;
        inline-size: var(--left-panel-width);
        border-inline-end: 1px solid var(--line-subtle);
        background: var(--surface-canvas);
    }

    /* Die Wortmarke. Vorher `L4-AI PRO DASHBOARD` in Rajdhani-Versalien
       mit einem `OPEN`-Abzeichen, das immer denselben Wert zeigte (S10).
       Jetzt: der Name, in der Schrift des Hauses. */
    .channel-header {
        display: flex;
        flex-shrink: 0;
        align-items: center;
        gap: var(--space-2);
        /* Der bisherige Abstand zum Modusschalter gehoert zur Kopfzeile,
           damit die Marke innerhalb dieser Flaeche mittig steht. */
        block-size: 56px;
        padding-inline: var(--space-4);
        color: var(--ink-primary);
        font-family: var(--font-ui);
        font-size: 15px;
        font-weight: var(--font-weight-medium);
        letter-spacing: normal;
        text-transform: none;
        white-space: nowrap;
        overflow: hidden;
    }

    /* Vorher eine eigene Fläche mit Radius um den Schriftzug. Eine Marke
       braucht keinen Kasten. */
    .channel-header-text {
        display: inline-flex;
        align-items: center;
        gap: var(--space-2);
        min-inline-size: 0;
        padding: 0;
        background: none;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* ====================================================================
       2a · Der Chat/Data-Umschalter — Gruppe 2b, §4 (P4)

       Er stand oben in der Inhaltsflaeche des Kanals und gehoerte dort nicht
       hin: er schaltet nicht den Inhalt, er schaltet die Betriebsart des
       Chats. Jetzt sitzt er unter der Wortmarke, wie `Startseite`/`Code`
       beim Vorbild — und nur, solange der AI-Trading-Chat offen ist.

       Die Klassen heissen weiter `chat-mode-switch-row`, `v2-switch` und
       `v2-switch-btn`; `setDataMode()` und der `localStorage`-Zustand sind
       unberuehrt.
       ==================================================================== */

    .chat-mode-switch-row {
        flex-shrink: 0;
        padding-block: 0;
        padding-inline: var(--space-2);
    }

    /* Auf allen anderen Kanaelen als dem AI-Trading-Chat schaltet der
       Umschalter nichts — er bleibt aber stehen, statt die Flaeche
       verschwinden zu lassen und "Kanaele" eine Zeile nach oben zu
       ziehen. Gedimmt und stumm statt weg. */
    .chat-mode-switch-row.is-inactive .v2-switch {
        opacity: 0.5;
        pointer-events: none;
    }

    /* Zwei Felder nebeneinander, ueber die volle Leistenbreite minus Rand —
       daher `grid` mit zwei gleichen Spalten statt `inline-flex`. */
    .v2-switch {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 2px;
        padding: 2px;
        border-radius: var(--radius-control);
        background: var(--surface-raised);
    }

    /* 30 px hoch, normal gesetzt — keine Versalien. Das ruhende Feld ist
       durchsichtig; die Flaeche zeigt, welches gilt (R3). */
    .v2-switch-btn {
        appearance: none;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        block-size: 30px;
        padding: 0;
        border: none;
        border-radius: var(--radius-chip);
        background: transparent;
        color: var(--ink-secondary);
        font-family: var(--font-ui);
        font-size: var(--text-sm);
        font-weight: var(--font-weight-regular);
        letter-spacing: normal;
        text-transform: none;
        cursor: pointer;
        transition:
            background-color var(--dur-fast) var(--ease-out),
            color var(--dur-fast) var(--ease-out);
    }

    @media (hover: hover) and (pointer: fine) {
        .v2-switch-btn:hover { color: var(--ink-primary); }
    }

    .v2-switch-btn.is-active {
        background: var(--surface-selected);
        color: var(--ink-primary);
        font-weight: var(--font-weight-medium);
    }

    .channels-container {
        position: relative;
        display: flex;
        flex: 1;
        flex-direction: column;
        min-block-size: 0;
        padding: 0;
        overflow-y: hidden;
    }

    /* Die Marke am aktiven Kanal. Neutral (R2), 2 px, und sie bewegt sich
       nur über `transform` — die Höhe setzt das JavaScript, sie wird aber
       nicht mitanimiert (§6 verbietet animierte `height`). */
    .sidebar-active-indicator {
        position: absolute;
        inset-block-start: 0;
        inset-inline-start: 0;
        z-index: var(--z-local);
        inline-size: 2px;
        block-size: 24px;
        border-radius: 999px;
        background: var(--accent);
        opacity: 1;
        pointer-events: none;
        transform: translate3d(0, 0, 0);
        will-change: transform;
        backface-visibility: hidden;
        transition:
            transform var(--dur-base) var(--ease-out),
            opacity var(--dur-instant) var(--ease-out);
    }

    .sidebar-active-indicator.is-hidden { opacity: 0; }
}

@layer channels {

    /* ====================================================================
       3 · Kanäle

       Die Abschnittsmarke hieß `[01] CHANNELS`: Mono, Versalien, in
       Klammern nummeriert (S4). Sie heißt jetzt „Kanäle" und sieht aus
       wie eine Beschriftung, nicht wie eine Terminalausgabe.
       ==================================================================== */

    .nav-channels-section {
        flex-shrink: 0;
        padding: var(--space-3) var(--space-2) var(--space-1);
    }

    .nav-section-label,
    .chat-section-label {
        padding: 0 var(--space-2) var(--space-2);
        color: var(--ink-secondary);
        font-family: var(--font-ui);
        font-size: var(--text-xs);
        font-weight: var(--font-weight-regular);
        letter-spacing: normal;
        text-transform: none;
        user-select: none;
    }

    .nav-divider {
        flex-shrink: 0;
        block-size: 1px;
        margin-inline: var(--space-2);
        background: var(--line-subtle);
    }

    /* Zeile 32 px, Icon 16 px, Abstand 10 px (§3.1). Kein Rahmen — die
       Fläche ordnet (R3). */
    .channel-item {
        position: relative;
        display: flex;
        align-items: center;
        gap: 10px;
        min-block-size: 32px;
        padding-inline: var(--space-2);
        margin-block: 1px;
        border: 0;
        border-radius: var(--radius-chip);
        background: transparent;
        color: var(--ink-secondary);
        font-family: var(--font-ui);
        font-size: var(--text-sm);
        font-weight: var(--font-weight-regular);
        cursor: pointer;
        overflow: hidden;
        transition:
            background-color var(--dur-instant) var(--ease-standard),
            color var(--dur-instant) var(--ease-standard);
    }

    @media (hover: hover) and (pointer: fine) {
        .channel-item:hover {
            background: var(--surface-hover);
            color: var(--ink-primary);
        }
    }

    /* Vorher grüne Schrift auf grüner Füllung. Jetzt Fläche und Schrift —
       kein Grün an einem Bedienelement ohne Finanzbedeutung (R2). */
    .channel-item.active {
        background: var(--surface-selected);
        color: var(--ink-primary);
        font-weight: var(--font-weight-medium);
    }

    .channel-item > .icon {
        flex-shrink: 0;
        font-size: var(--icon-md);
        line-height: 1;
    }

    /* Das Icon trägt die Schriftfarbe der Zeile mit. Vorher wurde es beim
       Überfahren und im aktiven Zustand grün. */
    .channel-item:hover > .icon,
    .channel-item.active > .icon {
        color: inherit;
    }

    /* Zählmarke am Kanal. Rot ist hier Zustandssignal — das ist erlaubt. */
    .channel-item .badge {
        margin-inline-start: auto;
        padding: 1px var(--space-2);
        border-radius: 999px;
        background: var(--signal-down-surface);
        color: var(--signal-down);
        font-family: var(--font-data);
        font-size: var(--text-2xs);
        font-variant-numeric: tabular-nums;
        font-weight: var(--font-weight-medium);
    }

    /* ====================================================================
       4 · Chat-Verlauf

       Die Liste selbst und ihre Gruppierung bleiben unangetastet — sie
       haben eigene Verträge und eigene Tests (§2). Hier ändert sich nur
       das Aussehen.
       ==================================================================== */

    .chat-history-section {
        flex: 1;
        min-block-size: 0;
        padding: 0 var(--space-2) var(--space-2);
        overflow-y: auto;
        scrollbar-width: thin;
        scrollbar-color: var(--line-strong) transparent;
    }

    .chat-history-header {
        position: sticky;
        inset-block-start: 0;
        z-index: var(--z-local);
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding-block: var(--space-3) var(--space-1);
        background: var(--surface-canvas);
    }

    .chat-history-header .chat-section-label { padding: 0 var(--space-2); }

    /* Vorher Mono, Versalien, gesperrt. Ein Knopf ist keine Terminalzeile. */
    .new-chat-btn {
        display: inline-flex;
        align-items: center;
        gap: var(--space-1);
        min-block-size: 24px;
        padding-inline: var(--space-2);
        border: 1px solid var(--line);
        border-radius: var(--radius-chip);
        background: transparent;
        color: var(--ink-secondary);
        font-family: var(--font-ui);
        font-size: var(--text-xs);
        font-weight: var(--font-weight-regular);
        letter-spacing: normal;
        text-transform: none;
        white-space: nowrap;
        cursor: pointer;
        transition:
            background-color var(--dur-instant) var(--ease-standard),
            border-color var(--dur-instant) var(--ease-standard),
            color var(--dur-instant) var(--ease-standard);
    }

    @media (hover: hover) and (pointer: fine) {
        .new-chat-btn:hover {
            border-color: var(--line-strong);
            background: var(--surface-hover);
            color: var(--ink-primary);
        }
    }

    .new-chat-btn .icon {
        font-size: var(--icon-sm);
        transform-origin: center;
        transition: transform var(--dur-base) var(--ease-out);
    }

    @media (hover: hover) and (pointer: fine) {
        .new-chat-btn:hover .icon { transform: rotate(90deg); }
    }

    .chat-history-list {
        display: flex;
        flex-direction: column;
        gap: 1px;
    }

    /* Linksbuendig wie jede andere Zeile der Liste. Zentriert stand sie
       mitten im nichts und sah aus wie ein Fehler statt wie ein Hinweis. */
    .chat-history-empty {
        padding: var(--space-2);
        color: var(--ink-secondary);
        font-size: var(--text-xs);
        text-align: start;
    }

    .chat-history-item,
    .chat-item {
        position: relative;
        display: flex;
        align-items: center;
        gap: var(--space-2);
        min-block-size: 30px;
        padding-inline: var(--space-2);
        border: 0;
        border-radius: var(--radius-chip);
        background: transparent;
        color: var(--ink-secondary);
        font-size: var(--text-xs);
        cursor: pointer;
        transition:
            background-color var(--dur-instant) var(--ease-standard),
            color var(--dur-instant) var(--ease-standard);
    }

    @media (hover: hover) and (pointer: fine) {
        .chat-history-item:hover,
        .chat-item:hover {
            background: var(--surface-hover);
            color: var(--ink-primary);
        }
    }

    .chat-history-item.active,
    .chat-item.active {
        background: var(--surface-selected);
        color: var(--ink-primary);
    }

    .chat-history-icon {
        display: inline-flex;
        flex-shrink: 0;
        align-items: center;
        justify-content: center;
        inline-size: var(--icon-sm);
        block-size: var(--icon-sm);
        color: var(--ink-muted);
    }

    .chat-history-icon .icon { font-size: var(--icon-sm); }

    .chat-history-item.active .chat-history-icon,
    .chat-item.active .chat-history-icon { color: inherit; }

    .chat-history-title {
        flex: 1;
        min-inline-size: 0;
        line-height: 1.35;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Zeitstempel steht in der Datenschrift (§4). Er sitzt auf einer
       Fläche, die überfahren und gewählt werden kann — deshalb
       `--ink-secondary` und nicht `--ink-muted`. */
    .chat-history-time {
        flex-shrink: 0;
        color: var(--ink-secondary);
        font-family: var(--font-data);
        font-size: var(--text-2xs);
        font-variant-numeric: tabular-nums;
    }

    .chat-history-actions {
        position: relative;
        flex-shrink: 0;
    }

    .chat-action-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: 24px;
        block-size: 24px;
        border: 0;
        border-radius: var(--radius-chip);
        background: transparent;
        color: var(--ink-secondary);
        cursor: pointer;
        opacity: 0;
        transition: opacity var(--dur-instant) var(--ease-standard);
    }

    .chat-history-item:hover .chat-action-btn,
    .chat-action-btn:focus-visible { opacity: 1; }

    @media (hover: hover) and (pointer: fine) {
        .chat-action-btn:hover {
            background: var(--surface-raised);
            color: var(--ink-primary);
        }
    }

    /* Das Menü an einer Verlaufszeile. Es wächst aus seinem Auslöser (§6). */
    .chat-item-menu {
        position: absolute;
        inset-inline-end: 0;
        inset-block-start: calc(100% + var(--space-1));
        z-index: var(--z-dropdown);
        display: none;
        min-inline-size: 128px;
        padding: var(--space-1);
        border: 1px solid var(--line);
        border-radius: var(--radius-control);
        background: var(--surface-overlay);
        overflow: hidden;
    }

    .chat-item-menu.show { display: block; }

    .chat-item-menu button {
        inline-size: 100%;
        padding: var(--space-2);
        border: 0;
        border-radius: var(--radius-chip);
        background: transparent;
        color: var(--ink-primary);
        font-family: var(--font-ui);
        font-size: var(--text-xs);
        letter-spacing: normal;
        text-align: start;
        text-transform: none;
        cursor: pointer;
    }

    @media (hover: hover) and (pointer: fine) {
        .chat-item-menu button:hover { background: var(--surface-hover); }
    }

    /* Die rote Farbe kommt erst beim Zugreifen — siehe unten. In Ruhe ist
       Loeschen eine Zeile wie die andere. */
    .chat-item-menu button.delete-chat { color: inherit; }

    .chat-history-section::-webkit-scrollbar { inline-size: 3px; }
    .chat-history-section::-webkit-scrollbar-track { background: transparent; }
    .chat-history-section::-webkit-scrollbar-thumb { background: var(--line-strong); }
}

@layer channels {

    /* ====================================================================
       5 · Nutzerzeile

       54 → 48 px, Grund `--surface-canvas`, obere Haarlinie (§3.4). Der
       Status „Online" ist weg: er stand auf 2,51 : 1 (S3) und sagte in
       einem Ein-Personen-Werkzeug nichts. Der Name genügt.
       ==================================================================== */

    .user-panel {
        display: flex;
        flex-shrink: 0;
        align-items: center;
        gap: var(--space-2);
        block-size: 48px;
        padding-inline: var(--space-3);
        border-block-start: 1px solid var(--line-subtle);
        background: var(--surface-canvas);
    }

    /* Vorher grün gefüllt und grün umrandet — Markenfarbe an einem Ort
       ohne Finanzbedeutung (R2). Jetzt neutral. */
    .user-avatar {
        display: flex;
        flex-shrink: 0;
        align-items: center;
        justify-content: center;
        inline-size: 28px;
        block-size: 28px;
        border: 1px solid var(--line);
        border-radius: var(--radius-chip);
        background: var(--surface-raised);
        color: var(--ink-secondary);
        font-family: var(--font-data);
        font-size: var(--text-2xs);
        font-weight: var(--font-weight-medium);
    }

    .user-info {
        flex: 1;
        min-inline-size: 0;
    }

    .user-name {
        color: var(--ink-primary);
        font-size: var(--text-sm);
        font-weight: var(--font-weight-medium);
        line-height: 1.3;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Nur noch fuer „Offline". Rot, weil das ein Zustandssignal ist. */
    .user-status {
        color: var(--signal-down);
        font-size: var(--text-2xs);
        line-height: 1.3;
    }

    .user-actions {
        position: relative;
        display: flex;
        flex-shrink: 0;
        align-items: center;
        gap: var(--space-1);
    }

    /* Die beiden Icon-Knöpfe der Nutzerzeile. Gleiche Maße, gleiches
       Verhalten — dieselbe Bedienlogik wie überall (§5.2 der Bauweise in
       components.css). */
    .user-settings-btn,
    .inbox-btn {
        position: relative;
        display: flex;
        flex-shrink: 0;
        align-items: center;
        justify-content: center;
        inline-size: 28px;
        block-size: 28px;
        border: 0;
        border-radius: var(--radius-chip);
        background: transparent;
        color: var(--ink-secondary);
        cursor: pointer;
        transition:
            background-color var(--dur-instant) var(--ease-standard),
            color var(--dur-instant) var(--ease-standard);
    }

    .user-settings-btn .icon,
    .inbox-btn .icon { font-size: var(--icon-lg); }

    @media (hover: hover) and (pointer: fine) {
        .user-settings-btn:hover,
        .inbox-btn:hover {
            background: var(--surface-raised);
            color: var(--ink-primary);
        }
    }

    /* Das Zahnrad drehte sich beim Überfahren eine Runde. Das ist
       Vorführung, keine Rückmeldung (§6) — die Farbe genügt. */

    /* Ungelesene Nachrichten. Rot ist Zustandssignal — erlaubt. */
    .inbox-badge {
        position: absolute;
        inset-block-start: -2px;
        inset-inline-end: -2px;
        min-inline-size: 15px;
        block-size: 15px;
        padding-inline: 3px;
        border: 1px solid var(--surface-canvas);
        border-radius: 999px;
        background: var(--signal-down);
        color: var(--accent-ink);
        font-family: var(--font-data);
        font-size: 9px;
        font-variant-numeric: tabular-nums;
        font-weight: var(--font-weight-medium);
        line-height: 13px;
        text-align: center;
        pointer-events: none;
    }

    /* Solange die Benachrichtigungs-Erlaubnis fehlt, trägt die Glocke
       einen Punkt (§3.5). Er ersetzt den schwebenden Knopf, der auf dem
       Scanner den SENDEN-Knopf überdeckt hat (S7). */
    .inbox-btn[data-push-permission="default"]::after {
        content: "";
        position: absolute;
        inset-block-start: 3px;
        inset-inline-end: 3px;
        inline-size: 6px;
        block-size: 6px;
        border: 1px solid var(--surface-canvas);
        border-radius: 999px;
        background: var(--signal-warn);
        pointer-events: none;
    }

    .user-menu {
        position: absolute;
        inset-inline-end: 0;
        inset-block-end: calc(100% + var(--space-2));
        z-index: var(--z-dropdown);
        display: none;
        min-inline-size: 168px;
        padding: var(--space-1);
        border: 1px solid var(--line);
        border-radius: var(--radius-control);
        /* Dieselbe Flaeche wie das Verlaufszeilen-Menue und das Act-Menue —
           vorher `--surface-overlay`, das neutrale Grau der Ueberlagerungen,
           nicht die warme Menuefarbe. */
        background: var(--surface-menu);
    }

    .user-menu.show { display: block; }

    .user-menu button {
        inline-size: 100%;
        padding: var(--space-2) var(--space-3);
        border: 0;
        border-radius: var(--radius-chip);
        background: transparent;
        /* Ruhig in Ruhe, hell erst beim Zugreifen — wie in den anderen
           Menues (`.chat-item-menu`), vorher durchgehend `--ink-primary`. */
        color: var(--ink-secondary);
        font-family: var(--font-ui);
        font-size: var(--text-sm);
        font-weight: var(--font-weight-regular);
        letter-spacing: normal;
        text-align: start;
        text-transform: none;
        cursor: pointer;
    }

    @media (hover: hover) and (pointer: fine) {
        .user-menu button:hover { background: var(--surface-hover); color: var(--ink-primary); }
    }

    .user-menu button.logout { color: var(--signal-down); }
}

@layer channels {

    /* ====================================================================
       6 · Kopfzeile und Inhaltsfläche

       52 → 48 px. Der Schatten ist weg: eine Haarlinie genügt, um zwei
       Ebenen zu trennen (R3, §3.2).
       ==================================================================== */

    .main-content {
        display: flex;
        flex: 1;
        flex-direction: column;
        min-inline-size: 0;
        min-block-size: 0;
        background: var(--surface-panel);
    }

    /* Gruppe 2b, §5 (P5): 48 → 44 px. Titel und Untertitel stehen auf einer
       Zeile, getrennt durch den Abstand. Rechts steht nichts mehr — das
       Modellabzeichen ist in den Composer gezogen (§2). */
    /* STEP_02C B.6: `align-items: baseline` hielt die Zeile an der
       Schriftlinie zusammen — bei 44 px Hoehe und einer Schrift von 15 px
       landete der Titel damit an der OBEREN Kante, nicht in der Mitte. Er
       steht jetzt mittig; Icon und Untertitel richten sich an derselben
       Mitte aus. */
    .content-header {
        display: flex;
        flex-shrink: 0;
        align-items: center;
        gap: var(--space-2);
        block-size: 44px;
        padding-inline: var(--space-5);
        background: var(--surface-panel);
    }

    /* 18 px (`--icon-nav`, Lauf A). Der Abstand zum Namen sind die 8 px des
       `gap` — Icon und Name sind eine Einheit. Der Untertitel dahinter steht
       weiter, er ist eine zweite Sache (siehe unten). */
    .content-header .channel-header-icon {
        flex-shrink: 0;
        color: var(--ink-secondary);
        font-size: var(--icon-nav);
        line-height: 1;
    }

    /* Ein Kanal ohne Motiv laesst das Element leer stehen —
       `updateChannelHeader()` setzt dann `hidden`. Die Regel hing vorher an
       einer `ph-`Klasse; seit der Satz ein <use>-Verweis ist, gibt es die
       Klasse nicht mehr, und die Regel blendete das Icon IMMER aus. */
    .content-header .channel-header-icon[hidden] {
        display: none;
    }

    /* 15 px statt 16, einzeilig, mit Auslassungspunkten. „AI Trading-Chat"
       brach vorher ab und wirkte dadurch abgehackt — P5. */
    .content-header .channel-name {
        flex-shrink: 0;
        max-inline-size: 40ch;
        color: var(--ink-primary);
        font-family: var(--font-ui);
        font-size: 15px;
        font-weight: var(--font-weight-medium);
        line-height: 1.2;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    /* Der Untertitel wird je Kanal richtig gesetzt (F4, S6). Vorher stand
       auf Journal und Scanner der Chat-Untertitel. Die senkrechte Linie
       davor ist weg — der Abstand trennt (R3). */
    .content-header .channel-desc {
        min-inline-size: 0;
        /* 8 px `gap` plus 4 px = die 12 px, die vorher der `gap` der ganzen
           Zeile trug. Der `gap` steht jetzt enger, weil er Icon und Name
           zusammenhaelt (B.6). */
        margin-inline-start: var(--space-1);
        color: var(--ink-secondary);
        font-size: var(--text-xs);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .content-header .channel-desc:empty { display: none; }

    /* Das Modellabzeichen stand hier bis Gruppe 2b, rechts in der Kopfzeile.
       Es steht jetzt im Composer des Chats — die Regeln dafuer sind in
       `channels/chat.css` (Abschnitt 6), weil das Element dort lebt.
       Die Klasse `token-badge` und die drei Toenungen bleiben als Kennung
       bestehen; ihr Aussehen setzt der Kanal. */

    .content-body {
        position: relative;
        flex: 1;
        min-block-size: 0;
        min-inline-size: 0;
        padding: var(--space-5) var(--space-5) 0;
        overflow-y: auto;
    }

    /* ====================================================================
       7 · Rechte Leiste

       Die Anwesenheitsliste („ONLINE — 2") ist ersatzlos gestrichen (F2):
       sie zeigte dich und den Bot, beide immer da. Geblieben ist die
       Dienstliste — sie trägt echte Information.

       S1, der schwerste Befund dieser Fläche: der Dienstname stand in
       einem zusammengefallenen Raster auf `white-space: nowrap` und lief
       über den RPM-Wert. Zehn gemessene Überlappungen. Die Zeile ist
       jetzt ein Raster aus zwei Spuren, `minmax(0, 1fr) auto`, und der
       Name darf umbrechen.
       ==================================================================== */

    /* Unter 1280 px nehmen die beiden Leisten zusammen 448 der verfuegbaren
       Breite. Gemessen in Gruppe 2: die Lesespalte faellt dadurch auf 52
       Zeichen statt der geforderten 65 bis 75 - nicht wegen --measure-prose,
       sondern weil das Fenster nichts mehr hergibt. Die Dienstliste ist
       Diagnose, der Text ist der Zweck: also weicht die Leiste.
       STEP_01_SHELL.md, Nachtrag aus Gruppe 2. */
    @media (max-width: 1279px) {
        .member-list {
            display: none;
        }
    }

    .member-list {
        flex-shrink: 0;
        inline-size: var(--right-panel-width);
        padding: var(--space-3) var(--space-3);
        padding-block-start: 0;
        border-inline-start: 1px solid var(--line-subtle);
        background: var(--surface-canvas);
        overflow-y: auto;
    }

    .member-category {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: var(--space-2);
        padding: var(--space-3) var(--space-1) var(--space-2);
        border-block-end: 1px solid var(--line);
        color: var(--ink-secondary);
        font-family: var(--font-ui);
        font-size: var(--text-xs);
        font-weight: var(--font-weight-regular);
        letter-spacing: normal;
        text-transform: none;
    }

    .member-category:first-child {
        block-size: 44px;
        padding-block: 0;
    }

    /* Der Spaltenkopf ueber der Zahlenspalte. Datenschrift, damit er
       ueber den Werten steht und nicht daneben wirkt. */
    .member-category small {
        color: var(--ink-muted);
        font-family: var(--font-data);
        font-size: var(--text-2xs);
    }

    /* Die Zeile ist Anzeige, kein Bedienelement. Sie hatte einen
       Überfahr-Zustand, der nichts auslöste — und der `--ink-muted` auf
       `--surface-hover` gedrückt hätte, wo es 4,17 : 1 misst. */
    .member-item {
        display: flex;
        align-items: center;
        padding: 0;
        cursor: default;
    }

    .member-stats-card {
        inline-size: 100%;
        padding: 0;
    }

    .member-stat-row {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: baseline;
        gap: var(--space-2);
        padding: var(--space-2) var(--space-1);
        border-block-end: 1px solid var(--line-subtle);
    }

    .member-stat-row:last-child { border-block-end: 0; }

    .member-stat-label {
        display: block;
        min-inline-size: 0;
    }

    /* Die Kürzel-Kachel (`TD`, `FH`, `AI`) ist weg — sie wiederholte nur
       den Namen, in Grün (§3.3). */
    .member-stat-badge { display: none; }

    .member-stat-copy {
        display: grid;
        gap: 2px;
        min-inline-size: 0;
    }

    .member-stat-copy strong {
        color: var(--ink-primary);
        font-size: var(--text-sm);
        font-weight: var(--font-weight-regular);
        line-height: 1.3;
        white-space: normal;
    }

    .member-stat-copy small {
        color: var(--ink-muted);
        font-size: var(--text-2xs);
        line-height: 1.3;
        white-space: normal;
    }

    /* Rechtsbündig, Datenschrift, `tabular-nums` (§4 und §3.3). Ein Wert
       größer als 0 wird NICHT eingefärbt — Farbe ist Finanzsignal (R2). */
    .member-stat-value {
        justify-self: end;
        color: var(--ink-secondary);
        font-family: var(--font-data);
        font-size: var(--text-xs);
        font-variant-numeric: tabular-nums;
        white-space: nowrap;
    }
}

/* ══════════════════════════════════════════════════════════════════════
   GRUPPE 2c, LAUF C — die beiden Leisten
   ══════════════════════════════════════════════════════════════════════ */
@layer channels {

    /* ── C.1/C.2  Wortmarke und Einklapp-Knopf ────────────────────────
       Die Wortmarke steht mittig in der Zeile, der Knopf rechts an der
       Kante. `margin-inline-start: auto` schiebt ihn dorthin, ohne dass
       die Wortmarke ihre Mitte verliert. */
    .channel-header-text {
        display: flex;
        align-items: center;
        block-size: 100%;
        gap: 6px;
        font-size: 16px;
        line-height: 1.25;
    }

    .brand-mark {
        flex: none;
        inline-size: 36px;
        block-size: 36px;
        object-fit: contain;
    }

    .rail-toggle {
        display: inline-flex;
        flex: none;
        align-items: center;
        justify-content: center;
        margin-inline-start: auto;
        padding: 0;
        border: 0;
        border-radius: var(--radius-control);
        background: transparent;
        color: var(--ink-muted);
        cursor: pointer;
        inline-size: 28px;
        block-size: 28px;
        transition:
            color var(--dur-fast) var(--ease-out),
            background-color var(--dur-fast) var(--ease-out);
    }

    .rail-toggle:hover { background: var(--surface-hover); color: var(--ink-primary); }

    /* ── C.7  Der Knopf der rechten Leiste ─────────────────────────────
       Er sitzt unten an der Vorderkante — der Kante zur Inhaltsflaeche.
       `margin-block-start: auto` drueckt ihn ans untere Ende, sobald die
       Leiste eine Spalte ist. */
    .rail-toggle--right {
        margin-block-start: auto;
        margin-inline-start: 0;
        margin-inline-end: auto;
    }

    .member-list { display: flex; flex-direction: column; }

    /* ── Eingeklappt ───────────────────────────────────────────────────
       Nicht die Breite wird bewegt: eine Breitenanimation laesst den
       ganzen Inhalt daneben bei jedem Bild neu rechnen. Die Leiste ist
       entweder da oder weg; nur der Knopf bleibt. */
    .app-container[data-leiste-links="zu"] .channel-list {
        inline-size: 44px;
        min-inline-size: 44px;
        overflow: hidden;
    }

    .app-container[data-leiste-links="zu"] .channel-header {
        justify-content: center;
        padding-inline: 0;
    }

    .app-container[data-leiste-links="zu"] .channel-header-text,
    .app-container[data-leiste-links="zu"] .channels-container,
    .app-container[data-leiste-links="zu"] .chat-mode-switch-row,
    .app-container[data-leiste-links="zu"] .sidebar-user-area,
    .app-container[data-leiste-links="zu"] #left-panel-resizer {
        display: none;
    }

    .app-container[data-leiste-links="zu"] .rail-toggle { margin-inline-start: 0; }

    .app-container[data-leiste-rechts="zu"] .member-list {
        inline-size: 36px;
        min-inline-size: 36px;
        padding-inline: 0;
        overflow: hidden;
    }

    .app-container[data-leiste-rechts="zu"] .member-list > *:not(.rail-toggle) { display: none; }
    .app-container[data-leiste-rechts="zu"] #right-panel-resizer { display: none; }

    /* Eingeklappt ist der Streifen schmaler als der Knopf plus die
       Vorderkanten-Position (C.7) vertraegt — der Knopf sass dann fast
       ohne Rand an der linken Kante. Im schmalen Streifen zaehlt die
       Vorderkante nicht mehr; hier gilt dieselbe Mitte wie beim
       eingeklappten linken Knopf. */
    .app-container[data-leiste-rechts="zu"] .rail-toggle--right {
        margin-block-start: var(--space-2);
        margin-block-end: auto;
        margin-inline-start: auto;
        margin-inline-end: var(--space-1);
    }

    /* ── C.3  Der Umschalter mit gleitendem Zeiger ─────────────────────
       Der Zeiger liegt als eigene Flaeche unter den Beschriftungen und
       faehrt hinueber. Zwei Felder, die abwechselnd aufleuchten, wirken
       wie zwei Knoepfe; eine Flaeche, die wandert, wirkt wie ein Schalter. */
    .v2-switch { position: relative; }

    .v2-switch-indicator {
        position: absolute;
        /* Der Zeiger liegt unter den Beschriftungen — das ist die Grundflaeche
           des Schalters, nicht eine Stufe darueber. */
        z-index: auto;
        inset-block: 2px;
        inset-inline-start: 2px;
        inline-size: calc(50% - 3px);
        border-radius: calc(var(--radius-control) - 1px);
        background: var(--control-selected);
        transition: transform var(--dur-base) var(--ease-out);
    }

    .v2-switch[data-gewaehlt="data"] .v2-switch-indicator {
        transform: translateX(calc(100% + 2px));
    }

    .v2-switch-btn {
        position: relative;
        z-index: var(--z-local);
        display: inline-flex;
        gap: var(--space-2);
        align-items: center;
        justify-content: center;
        background: transparent;
    }

    /* Die Flaeche kommt vom Zeiger, nicht vom Feld — sonst haette der
       gewaehlte Zustand zwei Quellen und beim Gleiten blitzt beides. */
    .v2-switch-btn.is-active { background: transparent; }

    @media (prefers-reduced-motion: reduce) {
        .v2-switch-indicator { transition-duration: 1ms; }
    }

    /* ── C.4  Kanalzeile: die Flaeche traegt die Auswahl, kein Balken ──
       R3: Die Flaeche ordnet. Der linke Strich war eine zweite Aussage
       ueber dieselbe Sache. */
    .channel-item.active::before,
    .sidebar-active-indicator { display: none; }

    .channel-item {
        display: flex;
        gap: var(--space-3);
        align-items: center;
        border-radius: var(--radius-control);
        color: var(--ink-secondary);
        transition:
            background-color var(--dur-fast) var(--ease-out),
            color var(--dur-fast) var(--ease-out);
    }

    .channel-item:hover { background: var(--surface-hover); color: var(--ink-primary); }
    .channel-item.active { background: var(--surface-selected); color: var(--ink-primary); }

    /* Das Icon ist ruhiger als der Name — es fuehrt den Blick, es ruft
       nicht. In der gewaehlten Zeile zieht es mit. */
    .channel-item > .icon { color: var(--ink-muted); }
    .channel-item.active > .icon,
    .channel-item:hover > .icon { color: var(--ink-primary); }

    .member-category { display: flex; gap: var(--space-2); align-items: center; }
    .member-category > .icon { color: var(--ink-muted); }
    .member-category > small { margin-inline-start: auto; }
}

/* ══════════════════════════════════════════════════════════════════════
   DIE LINKE LEISTE NACH DEM VORBILD
   ══════════════════════════════════════════════════════════════════════ */
@layer channels {

    /* Waagerechte Linien innerhalb der Leiste fallen weg. Die Abstaende
       trennen die Abschnitte; eine Linie sagt dasselbe ein zweites Mal
       (R3). Die senkrechte Kante zur Inhaltsflaeche bleibt — sie trennt
       zwei Bereiche, nicht zwei Listen. */
    .nav-divider { display: none; }
    .user-panel { border-block-start: 0; }

    /* ── Der Neu-Knopf: ein Kreis mit einem Zeichen darin ────────────── */
    .new-chat-btn {
        display: inline-flex;
        flex: none;
        align-items: center;
        justify-content: center;
        gap: 0;
        inline-size: 26px;
        min-inline-size: 26px;
        block-size: 26px;
        min-block-size: 26px;
        padding: 0;
        border: 1px solid var(--line);
        border-radius: 50%;
        background: transparent;
        color: var(--ink-secondary);
        transition:
            background-color var(--dur-fast) var(--ease-out),
            color var(--dur-fast) var(--ease-out);
    }

    .new-chat-btn:hover { background: var(--surface-hover); color: var(--ink-primary); }
    .new-chat-btn .icon { inline-size: 14px; block-size: 14px; }

    /* Die Drehung beim Ueberfahren stammt aus dem Kastenknopf und ergibt
       an einem Kreis keinen Sinn mehr. */
    .new-chat-btn:hover .icon { transform: none; }

    /* ── Die Chatzeile ───────────────────────────────────────────────── */
    .chat-history-item {
        display: flex;
        gap: var(--space-3);
        align-items: center;
        border-radius: var(--radius-control);
        color: var(--ink-secondary);
    }

    /* Die Marke ist ein Punkt, keine Sprechblase: in einer Liste, in der
       jede Zeile ein Chat ist, sagt ein Sprechblasensymbol nichts. Klein
       und ruhig, damit der Titel fuehrt. */
    .chat-history-icon-glyph {
        inline-size: 9px;
        block-size: 9px;
        color: var(--ink-muted);
    }

    .chat-history-item.active .chat-history-icon-glyph { color: var(--ink-secondary); }

    /* ── Das Menue auf einer Chatzeile ───────────────────────────────── */
    .chat-item-menu {
        min-inline-size: 168px;
        padding: var(--space-2);
        border: 1px solid var(--line);
        border-radius: var(--radius-panel);
        background: var(--surface-menu);
    }

    /* Vorher 11 px und gesperrt — ein Menue ist zum Lesen da, nicht zum
       Entziffern. */
    .chat-item-menu button {
        display: flex;
        gap: var(--space-3);
        align-items: center;
        inline-size: 100%;
        padding: var(--space-2) var(--space-3);
        border: 0;
        border-radius: var(--radius-control);
        background: transparent;
        color: var(--ink-secondary);
        cursor: pointer;
        font-family: var(--font-ui);
        font-size: var(--text-sm);
        font-weight: var(--font-weight-regular);
        letter-spacing: normal;
        text-align: start;
        text-transform: none;
        transition: background-color var(--dur-instant) var(--ease-out);
    }

    .chat-item-menu button:hover { background: var(--surface-hover); color: var(--ink-primary); }

    /* Loeschen ist rot erst beim Zugreifen — in Ruhe ist es eine Zeile wie
       die andere, sonst schreit die Liste dauerhaft. */
    .chat-item-menu .delete-chat:hover { color: var(--signal-down); }
}

/* Responsive shell: overlay panels never reserve space in the work area. */
@layer channels {
    .mobile-shell-action, .mobile-data-mode { display: none; }
    .shell-scrim { position: fixed; inset: 0; z-index: var(--z-modal-backdrop); border: 0; border-radius: 0; padding: 0; background: var(--scrim); cursor: pointer; }
    .shell-scrim[hidden] { display: none; }
    @media (max-width: 1279px) {
        #mobile-services-toggle { display: inline-flex; margin-inline-start: auto; }
        #right-panel-resizer { display: none; }
        .app-container .member-list { display: flex; position: fixed; inset: env(safe-area-inset-top) 0 env(safe-area-inset-bottom) auto; z-index: var(--z-modal); inline-size: min(320px, calc(100vw - 48px)); padding: 0 16px 16px; visibility: hidden; pointer-events: none; }
        .app-container[data-mobile-panel="rechts"] .member-list { visibility: visible; pointer-events: auto; }
        .member-list .member-category { min-block-size: 56px; }
        .member-list .rail-toggle--right { order: -1; margin: 8px 0 0 auto; inline-size: 44px; block-size: 44px; }
        .mobile-shell-action { align-items: center; justify-content: center; flex: 0 0 44px; inline-size: 44px; block-size: 44px; padding: 10px; border: 0; border-radius: var(--radius-control); color: var(--ink-secondary); background: transparent; cursor: pointer; }
    }
    @media (max-width: 767px) {
        .app-container { inline-size: 100%; padding-inline: env(safe-area-inset-left) env(safe-area-inset-right); }
        .app-container .channel-list { position: fixed; inset: env(safe-area-inset-top) auto env(safe-area-inset-bottom) 0; z-index: var(--z-modal); inline-size: min(320px, calc(100vw - 48px)); visibility: hidden; pointer-events: none; }
        .app-container[data-mobile-panel="links"] .channel-list { visibility: visible; pointer-events: auto; }
        #left-panel-resizer { display: none; }
        .main-content { inline-size: 100%; margin: 0; }
        .content-header { block-size: auto; min-block-size: 56px; padding: env(safe-area-inset-top) 8px 0; gap: 4px; }
        #mobile-nav-toggle { display: inline-flex; }
        .content-header .channel-header-icon { display: none; }
        .content-header .channel-name { flex: 0 1 auto; min-inline-size: 0; max-inline-size: none; font-size: 15px; }
        .content-header .channel-desc { display: none; }
        .mobile-data-mode:not([hidden]) { display: inline; color: var(--ink-secondary); font-size: 12px; padding-inline: 4px; }
        .content-body { padding: 0 12px; }
        .channel-header { min-block-size: 56px; padding-inline: 16px 8px; }
        .channel-header .rail-toggle { inline-size: 44px; block-size: 44px; }
        .channel-item { min-block-size: 44px; }
        .channel-list .v2-switch-btn { block-size: 44px; }
        .chat-history-item { min-block-size: 44px; }
        .channel-list .new-chat-btn, .channel-list .inbox-btn, .channel-list .user-settings-btn { min-inline-size: 44px; min-block-size: 44px; }
        .channel-list .user-panel { padding-bottom: max(12px, env(safe-area-inset-bottom)); }
        .chat-item-menu-btn { opacity: 1; }
        .user-menu { max-inline-size: calc(100vw - 64px); }
    }
    @media (pointer: coarse) {
        .content-header-action { min-inline-size: 44px; min-block-size: 44px; }
        .channel-list .chat-history-item-menu { opacity: 1; }
    }
}

/* ── Modellblock der rechten Leiste ──────────────────────────────────
   Dieselbe Zeilenform wie die Dienste: Motiv, Name, Statuspunkt,
   Ping in ms. */
@layer channels {
    .member-model-copy {
        display: flex;
        align-items: center;
        gap: var(--space-2);
        min-inline-size: 0;
    }

    .member-model-icon {
        inline-size: 14px;
        block-size: 14px;
        color: var(--ink-secondary);
        flex: none;
    }

    .member-model-copy strong {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}
