Files
dogfather-universe/workspace/assets/css/chat.css
T
DogFatherGitandClaude Opus 5 18a5231b70 Die Tuer ohne Klingel, der Anruf ohne Ende, die Glocke ohne Liste
Siebter Durchgang durch die Team-Dogi-Seiten aus Benutzersicht. Alles am
Code belegt, die Groessenangaben nachgerechnet.

=== DIE ANMELDUNG ===

WOHER BEKOMMT MAN EINEN CODE? Stand nirgends. Vier Kacheln, ein Feld,
ein Knopf -- wer keinen Code hatte, fand keinen einzigen Satz dazu. Fuer
die Community besonders teuer: Sie ist die einzige Rolle, die von
aussen kommt und niemanden im Haus kennt.

"BITTE KURZ WARTEN" SIND BIS ZU ZEHN MINUTEN (VERSUCHE_FENSTER_MIN).
Wer nach zwanzig Sekunden nachsieht und dieselbe Meldung liest, haelt
die Seite fuer kaputt. Jetzt steht die Zahl da.

EIN RICHTIGER CODE AN DER FALSCHEN KACHEL fiel in dieselbe Absage wie
ein erfundener -- der Server sucht nur unter der gewaehlten Rolle. Wer
aus der Community kommt und auf "Modi" tippt (das klingt ja danach),
tippt seinen richtigen Code dreimal Buchstabe fuer Buchstabe. Ab dem
zweiten Fehlversuch kommt jetzt ein Hinweis auf die Auswahl -- ohne zu
sagen, welche die richtige waere.

=== DER ANRUF: VIER FEHLER, EINE ERFAHRUNG ===

DAS FREIZEICHEN LIEF UNENDLICH. Es gab keinen Zeitgeber, der aufhoert.
Wer niemanden erreichte, sass vor einem piependen Kasten mit "02:47"
darauf, als telefoniere er laengst. Der Server schickt den Verfallszeit-
punkt sogar mit (`laeuft_bis`) -- benutzt hat ihn nie jemand.

DER KLINGELKASTEN VERSCHWAND NACH 46 SEKUNDEN, waehrend der Server 120
gibt. Wer beim Klingeln das Handy aus der Tasche holt und in Sekunde 50
hinsieht, fand nichts mehr -- kein Kasten, keine Knoepfe -- waehrend der
Anrufer noch siebzig Sekunden Freizeichen hoerte. Die 120 Sekunden sind
im Server ausdruecklich damit begruendet, dass man Zeit zum Entsperren
braucht; eine Zeile im Browser hat diese Entscheidung aufgehoben.

DAS FREIZEICHEN PIEPTE WEITER, waehrend daneben "Keine Verbindung."
stand. Ton sagte "es klingelt noch", Text sagte "vorbei".

DIE UHR ZAEHLTE AB DEM WAEHLEN. Wer 30 Sekunden klingeln liess und 12
Sekunden sprach, las im Kasten "00:42" und danach im Chat "Anruf . 12
Sekunden". Der Server rechnet es richtig; der Kasten hat es wieder
kaputtgemacht.

Dazu: Die Mikrofon-Absage verwies auf "das Schloss-Symbol neben der
Adresse" -- in der installierten App gibt es weder Adresszeile noch
Schloss. Das Haus kennt diesen Fehler und hat ihn beim Weg zur
Anruf-Probe schon behoben; hier stand er noch.

Und die Anruf-Probe: Ihr einziger Punkt ohne Handlungsanweisung war
"Antwort 503." -- auf einer Seite, die ausdruecklich fuer jemanden
gebaut ist, der nicht technisch ist. Ihr Rueckweg fuehrte ausserdem
immer in den Chat, auch wenn man von der Startseite kam.

=== DER TREFF ===

EIN EINZEILER MACHTE SECHS ERKLAERTEXTE UNSICHTBAR. bewerben.js las
`g.unter`, der Server schickt `g.text` -- also immer undefined. Damit
fehlten ALLE SECHS Gruppeneinleitungen des Fragebogens ("Kein Test mit
richtigen Antworten"), und die CSS-Regel dafuer lief ins Leere. Uebrig
blieben sechs nackte Ueberschriften ueber fuenfzehn Fragen.

DIE EINZIGE "SO LAEUFT DAS HIER"-SEITE WAR FAST UNERREICHBAR. Die
Kachel "Regeln & Hilfe" zeigte auf ein Brett, das am ersten Tag leer
ist. Die Regeln, die es wirklich gibt (Begruessung, fuenf Regeln, drei
Stufen, Mindestalter), stehen auf treff-regeln.html -- erreichbar ueber
genau einen kleinen Textlink auf einer Brettseite. Die Kachel zeigt
jetzt dorthin.

FIEL /api/treff/lage AUS, versprach die Seite einem Zuschauer
Schreibrechte, die der Server ablehnt: Die Pruefung fiel bei `lage ===
null` auf `true` durch -- von "darf auf keinem Brett" auf "darf
ueberall". Formular auf, getippt, 403.

Dazu: hilfe.js hatte eine eigene kleine Fehlertabelle fuer zwei
Kennungen und endete sonst bei "Ging nicht." -- ausgerechnet die Seite,
auf der jemand mit einem Problem sitzt, hatte die inhaltsleerste Absage
im Haus. Und der gesperrte "Neue Meldung"-Knopf erklaerte sich nur im
Maus-Tooltip; die Community kommt von TikTok, also vom Handy.

=== DIE STARTSEITE ===

DIE COMMUNITY BEKAM EIN WORT. Unter dem Titel steht bei jeder Rolle ein
Satz -- beim Community-Mitglied stand "Community". Woertlich derselbe
Mangel, den der Kommentar bei MODI_ROLLENTEXT beschreibt und fuer den
Modi behebt.

DER RING MELDETE 100 %, bevor man irgendetwas getan hat. Am ersten Tag,
ohne eine einzige Aufgabe, stand das groesste Element der Seite auf
"100 % -- HEUTE NICHTS OFFEN". Gelesen wird zuerst die Zahl, und 100 %
heisst fuer jeden "fertig", nicht "leer".

UND BEI EINER STOERUNG BLIEB "wird geladen" FUER IMMER STEHEN -- der
fruehe `return` liess den Platzhalter unberuehrt.

=== DIE ZUGANGSVERWALTUNG ===

Der Code-Kasten sagte "jetzt weitergeben" und gab die Haelfte nicht
mit, die man weitergeben muss: WO sich die Person anmeldet. DogFather
ruft den Code durchs Zimmer, der andere fragt "und wo?". Die Adresse
kommt jetzt vom Server (anmeldeAdresseFuer, abgeleitet aus derselben
Weiche), dazu ein Knopf "Code und Adresse kopieren".

Er verschwieg ausserdem den Rettungsweg: "danach nicht mehr abrufbar"
stimmt fuer DIESEN Code -- man kann jederzeit einen neuen vergeben. Wer
das nicht weiss, glaubt, er habe einen Menschen angelegt, der nie
hereinkommt. Und das Fenster liess sich wortlos schliessen, waehrend
der Code offen stand.

=== OPTIK: NACHGERECHNET, NICHT VERMUTET ===

DIE GLOCKE STAND NICHT IN DER LISTE. Sie ist ein echtes <button> und
wurde von der 44-px-Regel erfasst, waehrend ihre vier Nachbarn durch
einen staerkeren Selektor auf 36 px gehen. Zwischen 401 und 560 px --
also bei 412 px (haeufigste Android-Breite) und 430 px (iPhone Pro Max)
-- stand eine 44 px hohe runde Pille zwischen fuenf 36-px-Quadraten.
Der 400er-Block listet sie korrekt; genau dieses Band fiel durch beide
Rechnungen. Dasselbe Muster wie am 06.09.

DIE 9,6-px-REPARATUR IM KALENDER WAR SEIT WOCHEN WIRKUNGSLOS.
kalender.css wird NACH start.css geladen, beide Selektoren sind gleich
stark -- also gewann `.6rem` auf jeder Breite unter 760 px. Genau der
Wert, den start.css als behobenen Fehler protokolliert.

Und die Hebung selbst unterschritt ihre eigene Grenze: Die Regel, die
zu kleine Schrift hochziehen soll, zog `.k-pille` auf 11,2 px -- 0,3 px
unter die 11,5, die 33 Zeilen darueber aufgestellt werden.

Weitere nachgerechnete Groessen: Spaltenkopf und KW-Spalte im Kalender
(10,56 px), Kalenderwoche am Balken (9,92 px), Wecker-Knopf (30 px --
der kleinste im Haus, 14 unter der Vorgabe), Chat-Zurueck auf dem
Tablet (34x34, 40 % weniger Flaeche als noetig, und der einzige Weg
zurueck in die Liste), Emoji-Knoepfe (34 px bei 2 px Abstand -- wer
danebentippt, verschickt ein anderes Zeichen, und das ist sofort
abgeschickt).

IM WINDOWS-KONTRASTMODUS HATTE DIE STARTSEITE KEINE UEBERSCHRIFT.
`.ztitel` und der Team-Dogi-Schriftzug sind mit `background-clip: text`
gesetzt; faellt der Verlauf weg, bleibt durchsichtiger Text. Beide
haben jetzt den Rueckfall, den gate.css schon lange hat.

UND MEIN EIGENES STREIFENRASTER rechnete die Spaltenzahl aus der Breite
statt aus den Daten (`auto-fit`): Bei 390 px passten sechs, alles
darueber fiel in eine zweite, unbeschriftete Zeile. Das `overflow-x`
daneben konnte nie greifen -- ein auto-fit-Raster wird nie breiter als
sein Kasten. Der Kommentar beschrieb ein Verhalten, das es nicht gab.

GEMESSEN: pruef-meldungen 8/0, pruef-css-klassen ALLES IN ORDNUNG,
pruef-rechtetafel 19/0, alle Module laden, keine doppelten
Kachelnamen/-ziele/-farben in allen vier Rollen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 15:07:31 +02:00

1780 lines
69 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =====================================================================
chat.css — Gespräche im Workspace.
Wunsch Filipe, 06.09.2026: *"richtig krass, richtig hochwertig,
professionell und ultra geil."*
WAS DAS HIER HEISST — und was nicht:
Nicht mehr Effekte. Ein Chat wird täglich benutzt und oft lange
angesehen; was beim ersten Blick beeindruckt, stört beim hundertsten.
Die Wirkung kommt aus vier Dingen:
1. EINE FLÄCHE, kein scrollendes Dokument. Die Seite hat die Höhe
des Fensters, gescrollt wird nur INNERHALB der Spalten. Das
Eingabefeld steht immer an derselben Stelle -- man muss es nie
suchen.
2. RUHE IM VERLAUF. Fast schwarzer Grund, die eigenen Nachrichten
in einem gedeckten Blau, fremde in einem neutralen Grau. Kein
Farbverlauf in der Blase; er macht Text unruhig zu lesen.
3. GRUPPIERUNG. Mehrere Nachrichten derselben Person rücken
zusammen und wiederholen den Namen nicht. Ein Datumstrenner
gliedert den Verlauf.
4. GENUG LUFT. Zeilenhöhe 1.5, Blasen mit ordentlichem Innenabstand.
Enge sieht auf einem Bildschirmfoto ordentlich aus und liest
sich schlecht.
Augenschonend ist Hausregel: keine harten Weißflächen, keine
Neonränder, Bewegung nur als kurze Blende.
===================================================================== */
/* ---------- Die Fläche --------------------------------------------------- */
.chat-seite {
/* Der Rest des Hauses scrollt; hier soll die Seite stehen.
100dvh statt 100vh: Auf dem Handy ändert sich die sichtbare Höhe,
wenn die Adresszeile ein- und ausfährt -- mit vh springt das
Eingabefeld dabei aus dem Bild.
--kopf-hoehe WIRD GEMESSEN, nicht geraten (chat.js). Der erste
Entwurf hatte hier 62 px stehen; am Handy ist die Kopfleiste aber
zweizeilig und gut doppelt so hoch. Folge: Die Seite war zu lang,
und das Eingabefeld stand halb unterhalb des Bildschirmrands --
ausgerechnet das Feld, um das es geht. Der Rückfallwert bleibt
stehen für den Moment vor der ersten Messung. */
/* Der sichere Bereich unten wird ABGEZOGEN (09.09.2026): `100dvh` ist
die ganze Bildhoehe einschliesslich der Gestenleiste. Ohne den Abzug
liegt das Eingabefeld darunter -- ausgerechnet das Feld, um das es
geht. Auf Geraeten ohne Gestenleiste ist der Wert 0. */
height: calc(100dvh - var(--kopf-hoehe, 62px) - var(--ws-sicher-unten, 0px));
display: flex; flex-direction: column;
padding-bottom: 0;
overflow: hidden;
}
.chat {
flex: 1;
min-height: 0; /* sonst wächst das Raster über die Fläche */
display: grid;
grid-template-columns: minmax(240px, 320px) 1fr;
gap: 0;
border: 1px solid var(--rand);
border-radius: var(--radius);
background:
radial-gradient(120% 90% at 0% 0%, rgba(255, 255, 255, .03), transparent 55%),
var(--flaeche);
overflow: hidden;
}
.chat__spalte {
display: flex; flex-direction: column;
min-height: 0; min-width: 0;
}
/* Der Trenner zwischen Liste und Verlauf. Läuft oben und unten aus --
eine durchgehende Linie zerschneidet die Kachel in zwei. */
.chat__spalte--verlauf { position: relative; }
.chat__spalte--verlauf::before {
content: ""; position: absolute; left: 0; top: 12px; bottom: 12px; width: 1px;
background: linear-gradient(180deg,
transparent, var(--rand-hell) 15%, var(--rand-hell) 85%, transparent);
}
.chat__kopf {
display: flex; align-items: center; gap: 12px;
padding: 15px 17px;
border-bottom: 1px solid var(--rand);
flex: none;
}
.chat__kopf-text { min-width: 0; }
.chat__titel {
margin: 0;
font-size: 1.02rem; font-weight: 650; color: var(--text);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat__unter {
margin: 2px 0 0;
font-size: .78rem; color: var(--text-still);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat__kopf .knopf { margin-left: auto; flex: none; }
/* Der Zurück-Pfeil gehört dem Handy. Am Rechner stehen beide Spalten
nebeneinander, da gibt es nichts, wohin man zurückkönnte. */
.chat__zurueck {
display: none;
flex: none;
/* 44px statt 34px (19.09.2026): Zwischen 761 und 860 px -- also auf
jedem Tablet hochkant -- greift die 44-px-Hausregel nicht, und
dieser Knopf war dort 34x34, also 40 Prozent weniger Flaeche als
noetig. Er ist der EINZIGE Weg von einem Gespraech zurueck in die
Liste; wer ihn verfehlt, sitzt fest. */
width: 44px; height: 44px;
align-items: center; justify-content: center;
border: 1px solid var(--rand); border-radius: var(--radius-klein);
background: rgba(255, 255, 255, .04);
color: var(--text-leise); cursor: pointer;
}
.chat__zurueck svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.chat__zurueck:hover { color: var(--text); border-color: var(--rand-hell); }
.chat__suche { padding: 10px 14px 4px; flex: none; }
.chat__suche input { width: 100%; }
.chat__leer {
margin: 0; padding: 20px 18px;
font-size: .86rem; color: var(--text-still); line-height: 1.55;
}
/* ---------- Links: die Gespräche ----------------------------------------- */
.chat__liste {
flex: 1; min-height: 0;
overflow-y: auto;
margin: 0; padding: 8px; list-style: none;
display: grid; gap: 3px; align-content: start;
}
.chat-raum__knopf {
--r: var(--akzent);
width: 100%;
display: grid; grid-template-columns: auto 1fr auto;
align-items: center; gap: 11px;
padding: 10px 11px;
border: 1px solid transparent; border-radius: 12px;
background: transparent;
color: inherit; font: inherit; text-align: left; cursor: pointer;
transition: background .16s ease, border-color .16s ease;
}
.chat-raum__knopf:hover { background: rgba(255, 255, 255, .04); }
.chat-raum__knopf:focus-visible { outline: 2px solid var(--akzent); outline-offset: -2px; }
/* Das offene Gespräch bleibt sichtbar markiert -- sonst weiß man nach
dem Scrollen nicht mehr, wo man ist. */
.chat-raum[data-offen="ja"] .chat-raum__knopf {
background: color-mix(in srgb, var(--akzent) 11%, transparent);
border-color: color-mix(in srgb, var(--akzent) 32%, transparent);
}
.chat-raum__zeichen {
flex: none;
width: 38px; height: 38px; border-radius: 50%;
display: grid; place-items: center;
font-size: .82rem; font-weight: 700;
color: var(--r);
background: color-mix(in srgb, var(--r) 13%, transparent);
border: 1px solid color-mix(in srgb, var(--r) 30%, transparent);
}
/* Dieselben Rollenfarben wie überall im Haus. */
.chat-raum__zeichen[data-rolle="admin"] { --r: var(--dogi-haupt); }
.chat-raum__zeichen[data-rolle="manager"] { --r: var(--manager-haupt); }
.chat-raum__zeichen[data-rolle="scout"] { --r: var(--scout-haupt); }
.chat-raum__zeichen[data-rolle="creator"] { --r: var(--creator-haupt); }
/* Eine Gruppe zeigt ihre Größe statt einer Initiale -- der Name der
Gruppe steht ohnehin daneben. */
.chat-raum__zeichen[data-gruppe="ja"] {
--r: #a0aec4;
border-radius: 12px;
font-variant-numeric: tabular-nums;
}
.chat-raum__mitte { min-width: 0; }
.chat-raum__oben { display: flex; align-items: baseline; gap: 8px; }
.chat-raum__name {
flex: 1; min-width: 0;
font-size: .89rem; font-weight: 600; color: var(--text-leise);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-raum__zeit {
flex: none;
font-size: .75rem; color: var(--text-still);
font-variant-numeric: tabular-nums;
}
.chat-raum__vorschau {
display: block; margin-top: 2px;
font-size: .78rem; color: var(--text-still);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-raum__vorschau[data-weg="ja"] { font-style: italic; opacity: .8; }
/* Ungelesen: die Zahl UND ein kräftigerer Name. Nur eine Zahl übersieht
man beim Überfliegen. */
.chat-raum[data-neu="ja"] .chat-raum__name { color: var(--text); font-weight: 700; }
.chat-raum[data-neu="ja"] .chat-raum__vorschau { color: var(--text-leise); }
.chat-raum__zahl {
flex: none;
min-width: 21px; height: 21px; padding: 0 6px;
display: grid; place-items: center;
border-radius: 999px;
font-size: .72rem; font-weight: 700;
font-variant-numeric: tabular-nums;
color: #0b0f16;
background: var(--akzent);
}
/* ---------- Rechts: der Verlauf ------------------------------------------ */
.chat__verlauf {
flex: 1; min-height: 0;
overflow-y: auto;
padding: 18px 18px 8px;
display: flex; flex-direction: column; gap: 3px;
/* Ein weicher Schleier am oberen Rand: Der Verlauf scrollt unter den
Kopf, statt an einer harten Kante abgeschnitten zu wirken. */
mask-image: linear-gradient(180deg, transparent, #000 14px);
}
/* KURZE GESPRÄCHE LIEGEN UNTEN AN.
Bei drei Nachrichten standen sie oben, und darunter klaffte der halbe
Bildschirm -- man sucht die neueste dann am falschen Ende. Jeder
Messenger legt sie ans untere Ende, direkt über das Eingabefeld, und
das ist kein Geschmack: Dort schaut man hin, wenn man antworten will.
`margin-top: auto` auf dem ERSTEN Kind statt `justify-content:
flex-end` am Behälter. Der naheliegende Weg hat einen bekannten
Haken: In einem scrollbaren Flex-Behälter wird der obere Teil damit
unerreichbar, sobald der Inhalt überläuft -- man käme an die ältesten
Nachrichten nicht mehr heran. */
.chat__verlauf > :first-child { margin-top: auto; }
/* Der Datumstrenner. */
.chat-tag {
display: flex; align-items: center; gap: 10px;
margin: 14px 0 10px;
color: var(--text-still);
}
.chat-tag::before, .chat-tag::after {
content: ""; flex: 1; height: 1px;
background: linear-gradient(90deg, transparent, var(--rand-hell), transparent);
}
.chat-tag__text {
flex: none;
font-size: .72rem; font-weight: 700;
letter-spacing: .07em; text-transform: uppercase;
}
.chat-nachricht {
display: grid;
grid-template-columns: 30px 1fr;
gap: 9px;
align-items: flex-end;
max-width: 76%;
margin-top: 9px;
}
/* Folgt eine Nachricht derselben Person, rückt sie näher und lässt den
Kreis weg -- der Platz bleibt frei, damit die Blasen fluchten. */
.chat-nachricht[data-folge="ja"] { margin-top: 2px; }
.chat-nachricht[data-selbst="ja"] {
grid-template-columns: 1fr;
margin-left: auto;
}
.chat-nachricht__zeichen {
--r: #a0aec4;
grid-column: 1;
width: 30px; height: 30px; border-radius: 50%;
display: grid; place-items: center;
font-size: .75rem; font-weight: 700;
color: var(--r);
background: color-mix(in srgb, var(--r) 13%, transparent);
border: 1px solid color-mix(in srgb, var(--r) 28%, transparent);
}
.chat-nachricht__zeichen[data-rolle="admin"] { --r: var(--dogi-haupt); }
.chat-nachricht__zeichen[data-rolle="manager"] { --r: var(--manager-haupt); }
.chat-nachricht__zeichen[data-rolle="scout"] { --r: var(--scout-haupt); }
.chat-nachricht__zeichen[data-rolle="creator"] { --r: var(--creator-haupt); }
/* Ohne Kreis (Folgenachricht) bleibt die Spalte trotzdem stehen. */
.chat-nachricht[data-folge="ja"]:not([data-selbst="ja"]) .chat-nachricht__blase { grid-column: 2; }
.chat-nachricht__blase {
grid-column: 2;
padding: 10px 13px 7px;
border: 1px solid var(--rand);
border-radius: 14px 14px 14px 4px;
background: rgba(255, 255, 255, .045);
min-width: 0;
}
.chat-nachricht[data-folge="ja"] .chat-nachricht__blase { border-radius: 14px 14px 14px 8px; }
/* Die eigenen: gedecktes Blau, Ecke rechts. Kein Verlauf in der Fläche
-- Text auf einem Farbverlauf liest sich unruhig. */
.chat-nachricht[data-selbst="ja"] .chat-nachricht__blase {
grid-column: 1;
border-radius: 14px 14px 4px 14px;
background: color-mix(in srgb, var(--akzent) 16%, transparent);
border-color: color-mix(in srgb, var(--akzent) 30%, transparent);
}
.chat-nachricht[data-selbst="ja"][data-folge="ja"] .chat-nachricht__blase {
border-radius: 14px 14px 8px 14px;
}
.chat-nachricht__von {
margin: 0 0 3px;
font-size: .74rem; font-weight: 700;
color: color-mix(in srgb, var(--text-leise) 85%, transparent);
}
.chat-nachricht__text {
margin: 0;
font-size: .92rem; color: var(--text);
/* pre-wrap: Zeilenumbrüche aus der Eingabe bleiben erhalten, ohne
dass dafür HTML erzeugt werden müsste (das wäre der Weg, über den
jemand Auszeichnung einschleust). */
white-space: pre-wrap;
overflow-wrap: anywhere; /* eine lange Adresse sprengt nichts */
line-height: 1.5;
}
.chat-nachricht__weg { color: var(--text-still); font-style: italic; }
.chat-nachricht[data-weg="ja"] .chat-nachricht__blase {
background: transparent;
border-style: dashed;
}
/* EINE FARBE FÜR DIE GANZE FUSSZEILE — und zwar hier, an einer Stelle.
---------------------------------------------------------------------
Uhrzeit, "antworten", "zurücknehmen" und "kopieren" standen alle auf
var(--text-still) (#7f8fa6). Gemessen (pruef-chat-ausbau, Abschnitt 9)
ergibt das auf der eigenen Blase 3,68:1 -- unter den 4,5:1, die für
Text dieser Größe gelten. Es ist nie aufgefallen, weil niemand
nachgemessen hat; die Blase ist heller als der übrige Grund, und
genau dort wird eine leise Farbe zu leise.
var(--text-leise) (#94a5bb) bringt dieselbe Stelle auf 4,80:1 und
bleibt trotzdem deutlich ruhiger als der Nachrichtentext.
Die Kinder erben sie (color: inherit). Vier eigene Farbangaben wären
vier Stellen, die beim nächsten Mal auseinanderlaufen -- der Fehler,
der in diesem Haus am häufigsten vorkommt. */
/* VIER HANDGRIFFE PASSEN NICHT IN EINE ZEILE (10.09.2026).
Hier stand `display: flex` ohne Umbruch. Mit drei Eintraegen (Zeit,
antworten, kopieren) ging die Rechnung auf. Seit "anheften"
danebensteht, geht sie nicht mehr: Gemessen an echten Bildpunkten
stand "kopieren" bei 390 px -- der haeufigsten Handybreite -- 18 px
ueber der Blase, bei 320 px waren es 75. Die Zeile lief einfach
weiter, ueber ihren eigenen Rand hinaus.
DIE LEHRE IST NICHT "eine Schwelle einbauen". Das waere derselbe
Fehler wie in der Kopfleiste am 06.09., nur mit einer anderen Zahl
-- und beim fuenften Eintrag stuende sie wieder falsch da.
`flex-wrap: wrap` ist eine REGEL statt einer Rechnung: Sie bricht
genau dann um, wenn der Platz nicht reicht, und zwar unabhaengig
davon, wie viele Handgriffe es einmal sein werden.
`row-gap` kleiner als `column-gap`: Zwei Zeilen Fusstext sollen wie
ein Block wirken, nicht wie zwei Absaetze. */
.chat-nachricht__fuss {
display: flex; align-items: center; flex-wrap: wrap;
column-gap: 9px; row-gap: 2px;
margin-top: 4px;
color: var(--text-leise);
}
.chat-nachricht__zeit {
font-size: .75rem; color: inherit;
font-variant-numeric: tabular-nums;
}
/* Der Zurücknehmen-Knopf erscheint erst beim Darüberfahren -- er ist
die seltene Handlung und soll nicht in jeder Zeile mitlaufen. Auf
Geräten ohne Zeiger steht er immer da (siehe unten). */
.chat-nachricht__weg-knopf {
padding: 0; border: 0; background: none;
font: inherit; font-size: .75rem;
color: inherit; cursor: pointer;
opacity: 0; transition: opacity .16s ease, color .16s ease;
}
.chat-nachricht:hover .chat-nachricht__weg-knopf,
.chat-nachricht__weg-knopf:focus-visible { opacity: 1; }
.chat-nachricht__weg-knopf:hover { color: var(--warn); }
/* Unterwegs und gescheitert -- der Unterschied muss sichtbar sein. */
.chat-nachricht__blase:has(+ *) { /* Platzhalter, damit :has unterstützt bleibt */ }
/* ---------- Das Eingabefeld ---------------------------------------------- */
.chat__eingabe {
flex: none;
display: flex; align-items: flex-end; gap: 10px;
padding: 12px 14px 14px;
border-top: 1px solid var(--rand);
background: rgba(0, 0, 0, .2);
}
.chat__eingabe-schild {
position: absolute; width: 1px; height: 1px; margin: -1px;
overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.chat__eingabe textarea {
flex: 1; min-width: 0;
resize: none;
min-height: 42px; max-height: 160px;
line-height: 1.5;
}
.chat__senden {
flex: none;
width: 42px; height: 42px;
display: grid; place-items: center;
border: 1px solid color-mix(in srgb, var(--akzent) 40%, transparent);
border-radius: 12px;
background: color-mix(in srgb, var(--akzent) 18%, transparent);
color: color-mix(in srgb, var(--akzent) 55%, #ffffff);
cursor: pointer;
transition: background .16s ease, color .16s ease;
}
.chat__senden svg { width: 20px; height: 20px; fill: currentColor; }
.chat__senden:hover {
background: color-mix(in srgb, var(--akzent) 28%, transparent);
color: #fff;
}
.chat__senden:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* ---------- Die Wahl im Neu-Dialog --------------------------------------- */
.chat-wahl { margin: 4px 0 6px; max-height: 46vh; overflow-y: auto; }
.chat-wahl__gruppe + .chat-wahl__gruppe { margin-top: 13px; }
.chat-wahl__titel {
margin: 0 0 7px;
display: flex; align-items: center; gap: 7px;
font-size: .75rem; font-weight: 700;
letter-spacing: .08em; text-transform: uppercase;
color: var(--text-still);
}
.chat-wahl__punkt {
width: 7px; height: 7px; border-radius: 50%;
background: var(--r, var(--text-still)); flex: none;
}
.chat-wahl__gruppe[data-rolle="admin"] { --r: var(--dogi-haupt); }
.chat-wahl__gruppe[data-rolle="manager"] { --r: var(--manager-haupt); }
.chat-wahl__gruppe[data-rolle="scout"] { --r: var(--scout-haupt); }
.chat-wahl__gruppe[data-rolle="creator"] { --r: var(--creator-haupt); }
.chat-wahl__liste { display: flex; flex-wrap: wrap; gap: 7px; }
.chat-wahl__knopf {
--r: rgba(255, 255, 255, .5);
display: inline-flex; align-items: center; gap: 9px;
min-height: 40px;
padding: 5px 14px 5px 6px;
border: 1px solid var(--rand); border-radius: 999px;
background: rgba(255, 255, 255, .035);
color: var(--text-leise); font: inherit; cursor: pointer;
transition: color .16s ease, border-color .16s ease, background .16s ease;
}
.chat-wahl__knopf[data-rolle="admin"] { --r: var(--dogi-haupt); }
.chat-wahl__knopf[data-rolle="manager"] { --r: var(--manager-haupt); }
.chat-wahl__knopf[data-rolle="scout"] { --r: var(--scout-haupt); }
.chat-wahl__knopf[data-rolle="creator"] { --r: var(--creator-haupt); }
.chat-wahl__knopf:hover { color: var(--text); border-color: rgba(255, 255, 255, .24); }
.chat-wahl__knopf:focus-visible { outline: 2px solid var(--r); outline-offset: 2px; }
.chat-wahl__zeichen {
flex: none;
width: 28px; height: 28px; border-radius: 50%;
display: grid; place-items: center;
font-size: .74rem; font-weight: 700;
color: var(--r);
background: color-mix(in srgb, var(--r) 14%, transparent);
border: 1px solid color-mix(in srgb, var(--r) 34%, transparent);
}
.chat-wahl__name { font-size: .86rem; font-weight: 550; }
.chat-wahl__knopf[data-an="ja"] {
color: var(--text); font-weight: 600;
border-color: color-mix(in srgb, var(--r) 55%, transparent);
background: color-mix(in srgb, var(--r) 13%, transparent);
}
.chat-wahl__knopf[data-an="ja"] .chat-wahl__zeichen {
color: #12151b; background: var(--r); border-color: var(--r);
}
/* ---------- Handy --------------------------------------------------------
EINE Spalte, umgeschaltet über data-ansicht. Zwei Spalten auf 390
Pixeln hiessen zwei unbenutzbare Hälften. */
@media (max-width: 860px) {
.chat { grid-template-columns: 1fr; }
.chat__spalte--verlauf::before { display: none; }
.chat__zurueck { display: flex; }
.chat[data-ansicht="liste"] .chat__spalte--verlauf { display: none; }
.chat[data-ansicht="verlauf"] .chat__spalte--liste { display: none; }
/* Mehr Breite für die Blasen -- auf einem schmalen Schirm sind 76 %
drei Wörter je Zeile. */
.chat-nachricht { max-width: 88%; }
/* Ohne Zeiger gibt es kein "Darüberfahren": Der Knopf steht immer da,
sonst wäre er auf dem Handy gar nicht erreichbar. */
.chat-nachricht__weg-knopf { opacity: .75; }
}
@media (hover: none) {
.chat-nachricht__weg-knopf { opacity: .75; }
}
@media (prefers-reduced-motion: reduce) {
.chat-raum__knopf, .chat__senden, .chat-wahl__knopf,
.chat-nachricht__weg-knopf { transition: none; }
}
/* Ohne Farbverläufe tragen Kanten und Formen allein. Die eigenen
Nachrichten sind dann nur noch an der Ecke und der Ausrichtung zu
erkennen -- deshalb bekommen sie hier einen kräftigeren Rand. */
@media (forced-colors: active) {
.chat { border: 1px solid CanvasText; }
.chat__spalte--verlauf::before { background: CanvasText; }
.chat-nachricht__blase { border: 1px solid CanvasText; }
.chat-nachricht[data-selbst="ja"] .chat-nachricht__blase { border-width: 2px; }
.chat-raum__zeichen, .chat-nachricht__zeichen { border: 1px solid CanvasText; }
.chat-raum__zahl { border: 1px solid CanvasText; }
.chat-tag::before, .chat-tag::after { background: CanvasText; }
.chat__verlauf { mask-image: none; }
}
/* =====================================================================
DER CHAT (07.09.2026)
Wunsch Filipe: "mach die chat fenster auch viel geiler, viel
detaillierter und viel perfekter. ich will dass die leute auch bock
bekommen diesen chat zu benutzen."
---------------------------------------------------------------------
WORAN MAN EINEN GUTEN CHAT ERKENNT
Nicht an Effekten. An vier Dingen, die alle mit ORIENTIERUNG zu tun
haben -- und alle vier fehlten:
1. MAN SIEHT, MIT WEM MAN SCHREIBT. Initialen sind ein Platzhalter,
kein Gesicht. Die Bilder liefert der Server seit heute mit; hier
werden sie gezeichnet -- rund, mit einem feinen Rand in der Farbe
der Rolle.
2. EINE NACHRICHT HAT EINE RICHTUNG. Eigene Nachrichten kommen von
rechts und tragen den Hausakzent, fremde von links und bleiben
neutral. Die Ecke am Anfang einer Folge ist eckig, die übrigen
rund -- so sieht man, wo ein Gedanke anfängt, ohne den Namen zu
lesen.
3. EIN GESPRÄCH HAT EIN GEWICHT. Ungelesenes ist nicht "auch da",
sondern das, weshalb man die Seite geöffnet hat: kräftigerer
Grund, farbige Schiene, die Zahl als Marke.
4. DAS EINGABEFELD IST DAS WICHTIGSTE ELEMENT DER SEITE. Es war
eines von vielen. Jetzt sitzt es in einer eigenen Leiste, die
sich beim Hineinschreiben hebt.
Und was NICHT passiert ist: kein Blinken, kein Springen, keine
Verläufe im Text. Ein Chat wird stundenlang angesehen -- alles, was
einmal auffällt, nervt beim zwanzigsten Mal.
===================================================================== */
/* ---------- Das Gesicht ---------------------------------------------- */
.chat-raum__zeichen,
.chat-nachricht__zeichen {
position: relative;
overflow: hidden;
background: linear-gradient(150deg,
color-mix(in srgb, var(--rton, var(--akzent)) 30%, rgba(20, 27, 40, .9)),
rgba(12, 17, 26, .95));
box-shadow:
inset 0 0 0 1px color-mix(in srgb, var(--rton, var(--akzent)) 38%, transparent),
0 2px 6px -3px rgba(0, 0, 0, .8);
}
/* Die Farbe der Rolle -- dieselbe Zuordnung wie überall im Haus. */
.chat-raum__zeichen[data-rolle="spicy"],
.chat-nachricht__zeichen[data-rolle="spicy"] { --rton: var(--spicy-haupt); }
.chat-raum__zeichen[data-rolle="admin"],
.chat-nachricht__zeichen[data-rolle="admin"] { --rton: var(--dogi-haupt); }
.chat-raum__zeichen[data-rolle="manager"],
.chat-nachricht__zeichen[data-rolle="manager"] { --rton: var(--manager-haupt); }
.chat-raum__zeichen[data-rolle="scout"],
.chat-nachricht__zeichen[data-rolle="scout"] { --rton: var(--scout-haupt); }
.chat-raum__zeichen[data-rolle="creator"],
.chat-nachricht__zeichen[data-rolle="creator"] { --rton: var(--creator-haupt); }
/* Das Bild liegt ÜBER dem Buchstaben, nicht an seiner Stelle. Fällt es
aus, steht der Buchstabe weiterhin da. */
.chat-raum__zeichen img,
.chat-nachricht__zeichen img {
position: absolute; inset: 0;
width: 100%; height: 100%;
object-fit: cover;
border-radius: inherit;
}
/* ---------- Die Gesprächsliste --------------------------------------- */
.chat-raum__knopf {
position: relative;
border-radius: 12px;
margin: 0 8px 4px;
transition: background var(--tempo), box-shadow var(--tempo);
}
/* Das offene Gespräch trägt eine Schiene -- man sieht auch beim Scrollen
der Liste, wo man gerade ist. */
.chat-raum__knopf[data-an="ja"] {
background: linear-gradient(90deg,
color-mix(in srgb, var(--akzent) 16%, transparent),
rgba(255, 255, 255, .03) 55%);
box-shadow: inset 3px 0 0 var(--akzent);
}
/* Ungelesenes ist der Grund, warum man hier ist. */
.chat-raum__knopf:has(.chat-raum__zahl) {
background: rgba(255, 255, 255, .045);
}
/* ---------- Die Nachrichten ------------------------------------------ */
.chat-nachricht__blase {
border-radius: 16px 16px 16px 5px;
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .06),
0 2px 6px -3px rgba(0, 0, 0, .55);
}
/* Die erste Blase einer Folge bekommt oben eine eckige Ecke -- dort
fängt der Gedanke an. Die folgenden sind rundum weich. */
.chat-nachricht[data-folge="ja"] .chat-nachricht__blase {
border-top-left-radius: 8px;
}
.chat-nachricht[data-selbst="ja"] .chat-nachricht__blase {
border-radius: 16px 16px 5px 16px;
background: linear-gradient(160deg,
color-mix(in srgb, var(--akzent) 26%, rgba(17, 24, 37, .95)),
color-mix(in srgb, var(--akzent) 12%, rgba(12, 17, 27, .95)));
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .10),
0 2px 8px -3px color-mix(in srgb, var(--akzent) 45%, transparent);
}
.chat-nachricht[data-selbst="ja"][data-folge="ja"] .chat-nachricht__blase {
border-top-right-radius: 8px;
border-top-left-radius: 16px;
}
/* Der Tagestrenner: eine Linie mit dem Datum darin statt eines Wortes
im Nichts. */
.chat-tag {
display: flex; align-items: center; gap: 12px;
margin: 18px 0 12px;
}
.chat-tag::before, .chat-tag::after {
content: ""; flex: 1 1 auto; height: 1px;
background: linear-gradient(90deg, transparent, rgba(150, 186, 220, .18), transparent);
}
/* ---------- Das Eingabefeld ------------------------------------------ */
/* Es ist das wichtigste Element der Seite und sah aus wie eines von
vielen. Eine eigene Leiste, die sich beim Hineinschreiben hebt. */
/* Sie heisst .chat__eingabe (chat.html), nicht .chat-neu -- ich hatte
den Namen aus dem Kopf geschrieben. pruef-struktur meldete es als
totes CSS: eine Regel, die auf nichts zeigt, sieht aus wie erledigte
Arbeit und ist keine. */
.chat__eingabe {
position: relative;
padding: 12px 14px;
border-top: 1px solid rgba(150, 186, 220, .12);
background: linear-gradient(180deg, rgba(13, 18, 28, .6), rgba(9, 12, 20, .92));
transition: box-shadow var(--tempo);
}
.chat__eingabe:focus-within {
box-shadow: inset 0 1px 0 color-mix(in srgb, var(--akzent) 34%, transparent);
}
@media (prefers-reduced-motion: reduce) {
.chat-raum__knopf, .chat__eingabe { transition: none; }
}
@media (forced-colors: active) {
.chat-nachricht__blase,
.chat-raum__knopf[data-an="ja"] { box-shadow: none; border: 1px solid CanvasText; }
.chat-raum__zeichen, .chat-nachricht__zeichen { background: Canvas; box-shadow: none; }
}
/* =====================================================================
DREI DINGE, DIE DEM CHAT GEFEHLT HABEN (Punkt 15, 09.09.2026)
Filipe: "ich will dass du diese seite viel krasser und detaillierter
machst, ich will dass du dich informierst und alles reinsetzt was
wir noch gebrauchen könnten."
Nicht alles, sondern das, was hier täglich fehlt. Der Chat konnte
schon Räume, Verlauf, Gelesen-Stand, Live-Zustellung, Gruppen und
Zurücknehmen. Was fehlte:
1. SUCHE IN DEN NACHRICHTEN. Ein Chat ohne sie ist ab dem zweiten
Monat ein Archiv, in dem man nichts findet. Das Suchfeld gab es
— es durchsuchte aber nur die NAMEN der Gespräche.
2. ANTWORTEN MIT ZITAT. Zu zweit weiß man meist, worauf sich etwas
bezieht. In einer Gruppe laufen drei Fäden parallel, und "ja,
mach das" kann alles heißen.
3. DIE LINIE "AB HIER NEU". Wer nach zwei Tagen zurückkommt, sucht
sonst die Stelle, an der er aufgehört hat, indem er Uhrzeiten
liest.
Bewusst NICHT gebaut: Anhänge (dafür gibt es den Dateien-Bereich mit
Rechten und Ablauf), Reaktionen (eine vierte Sache, bevor die drei
sich bewährt haben) und Tipp-Anzeigen (sie kosten dauernd Verkehr
und sagen nichts, was man nicht in zwei Sekunden sieht).
===================================================================== */
/* ---- Das Zitat in der Blase ---------------------------------------- */
.chat-zitat {
display: block; width: 100%; text-align: left;
margin: 0 0 7px; padding: 6px 10px 6px 11px;
border: 0; border-radius: 0;
/* Der senkrechte Strich links ist das Zeichen für ein Zitat -- in
jedem Mailprogramm seit dreißig Jahren dasselbe. */
box-shadow: inset 3px 0 0 color-mix(in srgb, var(--akzent) 60%, transparent);
background: rgba(255, 255, 255, .05);
color: var(--text-leise);
font: inherit; cursor: pointer;
transition: background var(--tempo);
}
.chat-zitat:hover { background: rgba(255, 255, 255, .09); }
.chat-zitat__von {
display: block;
font-size: .74rem; font-weight: 700;
color: color-mix(in srgb, var(--akzent) 70%, #ffffff);
}
.chat-zitat__text {
display: block;
font-size: .8rem; line-height: 1.35;
/* Zwei Zeilen reichen: Es ist ein Hinweis auf die Stelle, nicht ihre
Wiederholung. */
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
overflow: hidden;
}
/* Die zitierte Nachricht, wenn man hinspringt -- kurz hervorgehoben.
Ein Sprung ohne Markierung lässt einen raten, welche Zeile gemeint
war. */
.chat-nachricht[data-hervor="ja"] .chat-nachricht__blase {
box-shadow: 0 0 0 2px color-mix(in srgb, var(--akzent) 65%, transparent);
transition: box-shadow .4s ease;
}
@media (prefers-reduced-motion: reduce) {
.chat-nachricht[data-hervor="ja"] .chat-nachricht__blase { transition: none; }
}
/* ---- Die Linie "ab hier neu" --------------------------------------- */
.chat-neu {
display: flex; align-items: center; gap: 10px;
margin: 14px 2px 10px;
color: #ff8f98;
font-size: .72rem; font-weight: 700;
letter-spacing: .1em; text-transform: uppercase;
}
.chat-neu::before, .chat-neu::after {
content: ""; flex: 1; height: 1px;
background: linear-gradient(90deg, transparent, rgba(255, 143, 152, .5));
}
.chat-neu::after { background: linear-gradient(90deg, rgba(255, 143, 152, .5), transparent); }
.chat-neu__text { flex: none; }
/* ---- Die Antwortleiste über dem Eingabefeld ------------------------ */
.antwort-leiste {
display: flex; align-items: flex-start; gap: 10px;
margin-bottom: 8px; padding: 8px 10px 8px 11px;
box-shadow: inset 3px 0 0 var(--akzent);
background: rgba(255, 255, 255, .05);
}
.antwort-leiste[hidden] { display: none; }
.antwort-leiste__inhalt { min-width: 0; flex: 1; }
.antwort-leiste__schild {
/* 0,72 rem = 11,52 px. Mit 0,7 waeren es 11,2 und damit unter der
Grundlinie, die pruef-css-klassen haelt. */
font-size: .72rem; letter-spacing: .08em; text-transform: uppercase;
color: var(--text-still);
}
.antwort-leiste__von {
margin-left: 6px;
font-size: .78rem; font-weight: 700;
color: color-mix(in srgb, var(--akzent) 70%, #ffffff);
}
.antwort-leiste__text {
display: block;
font-size: .82rem; color: var(--text-leise);
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.antwort-leiste__weg {
flex: none; width: 28px; height: 28px;
border: 0; border-radius: 50%;
background: rgba(255, 255, 255, .07);
color: var(--text-leise); font-size: .9rem; cursor: pointer;
}
.antwort-leiste__weg:hover { background: rgba(255, 255, 255, .13); color: var(--text); }
/* ---- Fundstellen in Nachrichten ------------------------------------ */
.chat-funde { padding: 4px 10px 12px; }
.chat-funde[hidden] { display: none; }
.chat-funde__schild {
margin: 8px 0 6px;
font-size: .72rem; font-weight: 700;
letter-spacing: .09em; text-transform: uppercase;
color: var(--text-still);
}
.chat-funde__liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.chat-funde__leer { font-size: .84rem; color: var(--text-still); }
.chat-fund {
display: grid; gap: 2px;
width: 100%; padding: 8px 11px;
text-align: left; border: 0;
clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%, 0 7px);
background: rgba(255, 255, 255, .045);
color: var(--text); font: inherit; cursor: pointer;
transition: background var(--tempo);
}
.chat-fund:hover { background: rgba(255, 255, 255, .09); }
.chat-fund__kopf { display: flex; justify-content: space-between; gap: 8px; }
.chat-fund__raum {
font-size: .78rem; font-weight: 700;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-fund__wann { flex: none; font-size: .72rem; color: var(--text-still); }
.chat-fund__von { font-size: .72rem; color: var(--text-still); }
.chat-fund__text {
font-size: .82rem; color: var(--text-leise); line-height: 1.35;
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
overflow: hidden;
}
/* Der Antworten-Knopf am Fuß einer Nachricht -- genauso leise wie
"zurücknehmen" daneben. Er ist ein Angebot, keine Aufforderung. */
/* "reagieren" steht seit dem 14.09.2026 daneben und sieht genauso aus
-- dieselbe Sorte Handgriff, dieselbe Zeile. Deshalb DIESELBE Regel
und keine vierte Abschrift: Neben antworten, anheften und kopieren
waere sie die vierte fast gleiche, und die vierte ist die, die
irgendwann eine Zeile anders hat. */
.chat-nachricht__antwort-knopf,
.chat-nachricht__reag-knopf {
border: 0; background: none; padding: 0;
font: inherit; font-size: .72rem;
color: inherit; cursor: pointer;
text-decoration: underline; text-underline-offset: 2px;
}
.chat-nachricht__antwort-knopf:hover,
.chat-nachricht__reag-knopf:hover { color: var(--text); }
.chat-nachricht__reag-knopf:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* =====================================================================
CHAT: SECHS ERGÄNZUNGEN (09.09.2026)
Filipe: "die kategorie chat, boah ich will dass du die wirklich
überall perfektionierst. wirklich alles was gratis ist und
hinzugefügt werden kann ohne problem will ich drin haben."
Alle sechs kommen ohne fremde Bibliothek aus und laden nichts nach:
Links, Kopieren, Emoji-Auswahl, Zeichenzähler, ein Bildlauf der nicht
mehr wegreisst, und Entwürfe je Gespräch (dafür braucht es kein CSS).
===================================================================== */
/* Ein Link in einer Nachricht ist unterstrichen, nicht farbig -- eine
Blase hat schon eine Farbe, und zwei Farben in einer Blase lesen sich
wie zwei Sachen. */
.chat-nachricht__link {
color: inherit;
text-decoration: underline;
text-underline-offset: 3px;
text-decoration-color: color-mix(in srgb, currentColor 55%, transparent);
word-break: break-word;
}
.chat-nachricht__link:hover { text-decoration-color: currentColor; }
.chat-nachricht__link:focus-visible {
outline: 2px solid var(--akzent); outline-offset: 2px; border-radius: 3px;
}
/* Der Kopier-Knopf sieht aus wie "antworten" -- es ist dieselbe Sorte
Handgriff an derselben Stelle. Ein anders gestalteter Knopf daneben
waere eine zweite Sprache in derselben Zeile. */
.chat-nachricht__kopie-knopf {
appearance: none; border: 0; background: none; padding: 0;
font: inherit; font-size: .72rem; font-weight: 600;
color: inherit; cursor: pointer;
text-decoration: underline; text-underline-offset: 2px;
}
.chat-nachricht__kopie-knopf:hover { color: var(--text); }
.chat-nachricht__kopie-knopf:focus-visible {
outline: 2px solid var(--akzent); outline-offset: 2px; border-radius: 4px;
}
/* ---- Emoji ---------------------------------------------------------- */
.chat__emoji {
flex: none;
width: 40px; height: 40px;
display: flex; align-items: center; justify-content: center;
appearance: none; border: 1px solid rgba(150, 186, 220, .18);
border-radius: 11px;
background: rgba(255, 255, 255, .04);
color: var(--text-leise);
font-size: 1.15rem; line-height: 1; cursor: pointer;
transition: color var(--tempo), border-color var(--tempo);
}
.chat__emoji:hover { color: var(--text); border-color: rgba(150, 186, 220, .34); }
.chat__emoji:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* Die Tafel steht ÜBER der Eingabe, nicht darunter: Darunter läge sie
auf dem Handy hinter der Bildschirmtastatur. */
.emoji-tafel {
position: absolute;
right: 14px; bottom: calc(100% - 6px);
z-index: 5;
display: grid; grid-template-columns: repeat(10, 1fr); gap: 4px;
padding: 10px;
border-radius: 14px;
background: rgba(8, 12, 20, .97);
border: 1px solid rgba(150, 186, 220, .2);
box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .9);
}
.emoji-tafel__knopf {
appearance: none; border: 0; background: none;
/* FUELLT SEINE SPALTE, STATT 34 px BREIT ZU SEIN (19.09.2026).
Emojis stehen dicht an dicht: Bei 34 px Knopf und 2 px Abstand
liegt der Nachbar 36 px vom Mittelpunkt entfernt. Wer danebentippt,
verschickt ein anderes Zeichen -- und anders als ein Fehlgriff in
einem Menue ist das sofort abgeschickt. */
width: 100%; min-height: 44px; border-radius: var(--radius-klein);
font-size: 1.15rem; line-height: 1; cursor: pointer;
transition: background var(--tempo);
}
.emoji-tafel__knopf:hover { background: rgba(255, 255, 255, .1); }
.emoji-tafel__knopf:focus-visible { outline: 2px solid var(--akzent); outline-offset: -2px; }
@media (max-width: 620px) {
.emoji-tafel { left: 14px; right: 14px; grid-template-columns: repeat(8, 1fr); }
}
/* ---- Zeichenzähler --------------------------------------------------- */
.chat__zeichen {
flex: none; align-self: center;
font-size: .72rem; font-weight: 700; letter-spacing: .04em;
color: var(--text-still);
font-variant-numeric: tabular-nums;
}
/* Eng heisst rot -- aber erst dann. Ein dauerhaft roter Zähler ist eine
Warnung, die niemand mehr liest. */
.chat__zeichen[data-eng="ja"] { color: var(--warn, #ff9aa2); }
/* ---- Zum neuesten ---------------------------------------------------- */
.chat__zum-neuesten {
position: absolute; left: 50%; bottom: 96px;
transform: translateX(-50%);
z-index: 4;
padding: 9px 18px;
border-radius: 999px;
border: 1px solid color-mix(in srgb, var(--akzent) 40%, transparent);
background: rgba(8, 12, 20, .95);
color: var(--text);
font: inherit; font-size: .8rem; font-weight: 700;
cursor: pointer;
box-shadow: 0 10px 26px -12px rgba(0, 0, 0, .9);
}
.chat__zum-neuesten:hover { border-color: var(--akzent); }
.chat__zum-neuesten:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
.chat__emoji, .emoji-tafel__knopf { transition: none; }
}
@media (forced-colors: active) {
.emoji-tafel, .chat__zum-neuesten { border: 1px solid CanvasText; background: Canvas; }
}
/* =====================================================================
ANHÄNGE, ABLAGE UND WEGRÄUMEN (09.09.2026)
Filipe: "man muss die chats auch gelöscht bekommen!!! am besten wäre
es auch wenn man da auch im chat pdfs schicken könnte. pdfs und
fotos."
===================================================================== */
/* Der Wegräum-Knopf sitzt im Kopf, rechts. Er ist absichtlich LEISE:
Löschen ist die seltene Handlung, und ein roter Knopf, der jeden Tag
danebensteht, wird irgendwann aus Versehen getroffen. Rot wird er
erst beim Darüberfahren -- dann, wenn jemand ihn wirklich meint. */
/* Der Behaelter schiebt, die Knoepfe stehen. Vorher schob sich jeder
Knopf mit `margin-left: auto` selbst -- bei zwei sichtbaren teilen
sich zwei auto-Raender den freien Platz und reissen sie auseinander.
Welche sichtbar sind, entscheidet der Server; eine Regel, die das
aushaelt, ist besser als eine Zahl, die fuer einen Fall stimmt. */
/* =====================================================================
REAKTIONEN (14.09.2026)
Filipe: "ich will dass man auf die nachrichten auch reagieren kann
mit einem emoji, die nachricht selbst ohne zu antworten."
GEDECKT, NICHT BUNT. Die Zeichen bringen ihre eigene Farbe mit --
ein farbiger Rahmen darum waere zu viel fuer eine Zeile, die unter
jeder zweiten Nachricht stehen kann. Die eigene Reaktion ist am
Rahmen zu erkennen, nicht an einem Leuchten.
===================================================================== */
.reaktionen {
display: flex; flex-wrap: wrap; gap: 5px;
margin: 7px 0 0;
}
.reaktionen__stueck {
display: inline-flex; align-items: center; gap: 5px;
padding: 2px 8px 3px;
border: 1px solid var(--rand); border-radius: 999px;
background: rgba(255, 255, 255, .04);
font: inherit; font-size: .8rem; line-height: 1.4;
color: var(--text-leise); cursor: pointer;
transition: border-color var(--tempo), background var(--tempo);
}
.reaktionen__stueck:hover { border-color: var(--rand-hell); }
/* Die EIGENE Reaktion: ein Rahmen in der Hausfarbe. Damit sieht man
auf einen Blick, wo man selbst schon geklickt hat -- und ein zweiter
Klick nimmt sie zurueck. */
.reaktionen__stueck[data-selbst="ja"] {
border-color: color-mix(in srgb, var(--akzent) 55%, transparent);
background: color-mix(in srgb, var(--akzent) 12%, transparent);
color: var(--text);
}
.reaktionen__stueck:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
.reaktionen__zeichen { font-size: .95rem; line-height: 1; }
.reaktionen__zahl { font-variant-numeric: tabular-nums; }
/* Die Tafel: eine Karte, kein Pillenstreifen (14.09.2026).
Filipe: "soll viel besser und geiler sein und man soll auch
auswaehlen koennen, also paar als vorschlaege mit der moeglichkeit
andere auszuwaehlen und als favoriten zu speichern."
Die erste Fassung war eine Reihe von sechs Zeichen in einer Pille.
Das sah nach Notloesung aus -- und es WAR eine: Mehr ging nicht
hinein. Jetzt ist es eine Karte mit drei Teilen: Vorschlaege oben,
Suche, Katalog. Der Katalog rollt, die Vorschlaege bleiben stehen.
GEDECKT, NICHT GRELL: Die Zeichen bringen ihre eigene Farbe mit. Die
Karte darum ist dunkel und ruhig, damit die Zeichen die einzigen
bunten Punkte sind. */
.reagieren-tafel {
position: relative; z-index: 5;
/* SIE MUSS SAGEN, IN WELCHE SPALTE SIE GEHOERT (15.09.2026).
Filipe, mit einem Bildschirmfoto: "was ist das den fuer eine
scheisse verbesser das sofort." Darauf ein dreissig Pixel schmaler
Streifen mit sechs Zeichen untereinander.
.chat-nachricht ist ein RASTER aus zwei Spalten: dreissig Pixel
fuer den Kreis mit den Initialen, der Rest fuer die Blase. Ein
Kind ohne Spaltenangabe wird automatisch in die naechste freie
Zelle gesetzt -- und das ist die Spalte des Kreises. Die Tafel
bekam damit dreissig Pixel, `width: min(330px, 100%)` machte
brav 30 daraus, und die Zeichen stapelten sich.
BEI EIGENEN NACHRICHTEN FIEL ES NIE AUF: Dort hat das Raster nur
EINE Spalte (der Kreis entfaellt), die Tafel bekam die volle
Breite. Und genau diesen Fall hat die Pruefung gemessen -- sie war
gruen, waehrend es bei jeder fremden Nachricht kaputt war. */
grid-column: 2; justify-self: start;
margin: 8px 0 2px;
width: min(330px, 100%);
border: 1px solid var(--rand-hell, var(--rand));
border-radius: 16px;
background:
linear-gradient(180deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, .015)),
var(--flaeche-tief, #131a24);
box-shadow: 0 18px 40px -22px rgba(0, 0, 0, .95),
inset 0 1px 0 rgba(255, 255, 255, .06);
padding: 9px 9px 7px;
animation: tafel-auf .13s ease-out;
}
@keyframes tafel-auf {
from { opacity: 0; transform: translateY(-4px); }
to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
.reagieren-tafel { animation: none; }
}
/* Die eigene Nachricht hat nur eine Spalte -- dort waere `2` eine
Spalte, die es nicht gibt, und das Raster legte still eine an. */
.chat-nachricht[data-selbst="ja"] .reagieren-tafel {
grid-column: 1; justify-self: end;
}
/* Kopf: die Vorschlaege nehmen den Platz, der Stern bleibt rechts. */
.reagieren-tafel__kopf {
display: flex; align-items: center; gap: 6px;
}
.reagieren-tafel__schnell {
flex: 1; min-width: 0;
display: flex; flex-wrap: wrap; gap: 2px;
}
.reagieren-tafel__stern {
flex: none;
appearance: none; border: 1px solid transparent; border-radius: 10px;
width: 30px; height: 30px;
background: none; cursor: pointer;
font-size: .95rem; line-height: 1;
color: var(--text-still);
transition: color var(--tempo), background var(--tempo), border-color var(--tempo);
}
.reagieren-tafel__stern:hover { color: var(--text-leise); background: rgba(255, 255, 255, .06); }
.reagieren-tafel__stern:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* Im Merk-Modus ist der Stern AN -- und die ganze Tafel sagt es mit,
damit niemand aus Versehen reagiert, wenn er merken wollte. */
.reagieren-tafel[data-merken="ja"] .reagieren-tafel__stern {
color: var(--akzent);
border-color: color-mix(in srgb, var(--akzent) 45%, transparent);
background: color-mix(in srgb, var(--akzent) 14%, transparent);
}
.reagieren-tafel[data-merken="ja"] {
border-color: color-mix(in srgb, var(--akzent) 40%, var(--rand));
}
.reagieren-tafel__hinweis {
margin: 0; padding: 0 2px;
font-size: .72rem; line-height: 1.45;
color: var(--text-still);
}
.reagieren-tafel__hinweis:empty { display: none; }
.reagieren-tafel__suche {
width: 100%; box-sizing: border-box;
margin: 7px 0 6px;
padding: 6px 10px;
border: 1px solid var(--rand); border-radius: 10px;
background: rgba(0, 0, 0, .25);
font: inherit; font-size: .78rem;
color: var(--text);
}
.reagieren-tafel__suche::placeholder { color: var(--text-still); }
.reagieren-tafel__suche:focus-visible { outline: 2px solid var(--akzent); outline-offset: 1px; }
/* Der Katalog rollt INNEN. Eine Tafel, die laenger wird als der
Bildschirm, schiebt den Chat weg und ihre eigene Suche nach oben
hinaus. */
.reagieren-tafel__katalog {
max-height: 210px; overflow-y: auto;
padding-right: 2px;
overscroll-behavior: contain;
}
.reagieren-tafel__gruppe {
margin: 6px 0 3px; padding: 0 2px;
/* .72rem = 11.52 px und damit knapp ueber der Lesbarkeitsgrenze von
11.5 px, die pruef-css-klassen zieht. Mein erster Wert (.66rem =
10.56 px) ist dort aufgeschlagen -- richtig so: Eine gesperrte
Versalzeile ist ohnehin schon schwerer zu lesen als normale
Schrift, da darf sie nicht auch noch die kleinste sein. */
font-size: .72rem; letter-spacing: .09em; text-transform: uppercase;
color: var(--text-still);
}
.reagieren-tafel__gruppe:first-child { margin-top: 0; }
.reagieren-tafel__reihe { display: flex; flex-wrap: wrap; gap: 2px; }
.reagieren-tafel__leer {
margin: 10px 2px; font-size: .76rem; color: var(--text-still);
}
.reagieren-tafel__zeichen {
position: relative;
appearance: none; border: 1px solid transparent; border-radius: 10px;
width: 34px; height: 32px;
padding: 0;
background: none; cursor: pointer;
font-size: 1.15rem; line-height: 1;
transition: background var(--tempo), transform var(--tempo), border-color var(--tempo);
}
.reagieren-tafel__zeichen:hover {
background: rgba(255, 255, 255, .09);
transform: scale(1.14);
}
.reagieren-tafel__zeichen:focus-visible { outline: 2px solid var(--akzent); outline-offset: 1px; }
/* EIN FAVORIT TRAEGT EINEN PUNKT, keinen Rahmen: Der Rahmen gehoert im
Merk-Modus dem, was man gerade anfasst. Ein kleiner Punkt unten sagt
"gemerkt", ohne mit dem Zeichen zu konkurrieren. */
.reagieren-tafel__zeichen[data-favorit="ja"]::after {
content: ""; position: absolute;
left: 50%; bottom: 2px; transform: translateX(-50%);
width: 4px; height: 4px; border-radius: 50%;
background: var(--akzent);
}
/* Im Merk-Modus wird der Punkt zum Rahmen -- dort geht es genau darum. */
.reagieren-tafel[data-merken="ja"] .reagieren-tafel__zeichen[data-favorit="ja"] {
border-color: color-mix(in srgb, var(--akzent) 55%, transparent);
background: color-mix(in srgb, var(--akzent) 12%, transparent);
}
@media (prefers-reduced-motion: reduce) {
.reagieren-tafel__zeichen:hover { transform: none; }
.reagieren-tafel__zeichen, .reagieren-tafel__stern { transition: none; }
}
/* Am Handy darf die Tafel die ganze Breite nehmen -- 330 px neben
einer Sprechblase waeren dort ein Streifen. */
@media (max-width: 560px) {
.reagieren-tafel { width: 100%; }
.reagieren-tafel__katalog { max-height: 44vh; }
}
.chat__kopf-knoepfe {
flex: none; margin-left: auto;
display: flex; align-items: center; gap: 6px;
}
.chat__weg {
flex: none;
width: 34px; height: 34px;
display: grid; place-items: center;
border: 1px solid var(--rand); border-radius: 10px;
background: rgba(255, 255, 255, .03);
color: var(--text-leise); cursor: pointer;
transition: color var(--tempo), border-color var(--tempo);
}
.chat__weg svg {
width: 17px; height: 17px;
fill: none; stroke: currentColor; stroke-width: 1.7;
stroke-linecap: round; stroke-linejoin: round;
}
.chat__weg:hover { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.chat__weg:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* AUFLOESEN SIEHT ANDERS AUS ALS WEGRAEUMEN (11.09.2026). Zwei gleich
aussehende Knoepfe nebeneinander, von denen einer nur bei mir und
einer bei ALLEN loescht, waeren eine Falle. Anderes Zeichen, eigener
Rand -- aber gedeckt, nicht signalrot: Der Knopf steht im Kopf und
soll nicht den ganzen Tag schreien. */
.chat__weg--ganz {
border-color: color-mix(in srgb, var(--warn) 30%, var(--rand));
color: color-mix(in srgb, var(--warn) 55%, var(--text-leise));
}
.chat__weg--ganz:hover {
color: var(--warn);
border-color: color-mix(in srgb, var(--warn) 65%, transparent);
background: color-mix(in srgb, var(--warn) 9%, transparent);
}
/* Steht der Knopf da, braucht der Text daneben seinen eigenen Rand --
sonst hat .chat__kopf-text keine Grenze und schiebt ihn hinaus. */
.chat__kopf--verlauf .chat__kopf-text { min-width: 0; flex: 1; }
/* ---- Die Büroklammer ------------------------------------------------ */
.chat__anhang-feld {
/* Nicht display:none -- ein verstecktes Feld lässt sich in manchen
Browsern nicht mehr über click() öffnen. Es steht da, nur ohne
Fläche. */
position: absolute; width: 1px; height: 1px;
padding: 0; margin: -1px; overflow: hidden;
clip-path: inset(50%); border: 0;
}
.chat__anhang {
flex: none;
width: 40px; height: 40px;
display: flex; align-items: center; justify-content: center;
appearance: none; border: 1px solid rgba(150, 186, 220, .18);
border-radius: 11px;
background: rgba(255, 255, 255, .04);
color: var(--text-leise); cursor: pointer;
transition: color var(--tempo), border-color var(--tempo);
}
.chat__anhang svg {
width: 19px; height: 19px;
fill: none; stroke: currentColor; stroke-width: 1.7;
stroke-linecap: round; stroke-linejoin: round;
}
.chat__anhang:hover { color: var(--text); border-color: rgba(150, 186, 220, .34); }
.chat__anhang:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
.chat__anhang:disabled { opacity: .45; cursor: progress; }
/* ---- Ein Foto in der Blase ------------------------------------------ */
/* Die Höhe ist begrenzt, die Breite folgt dem Bild. Ein Hochformat
nähme sonst den halben Verlauf ein und schöbe alles darunter aus dem
Bild -- man scrollt dann durch ein Foto statt durch ein Gespräch. */
.chat-bild {
display: block;
width: 100%; /* die Hoechstbreite setzt das Skript */
margin: 0 0 6px;
border-radius: 12px;
overflow: hidden;
line-height: 0;
background: rgba(255, 255, 255, .04);
}
/* Die Groesse macht der Kasten (aspect-ratio + max-width, siehe
chat.js). Das Bild fuellt ihn nur aus. Stuende die Groesse hier am
Bild, waere sie erst bekannt, wenn das Bild da ist -- und genau das
war der Fehler, der den Verlauf um 323 px verschoben hat. */
.chat-bild img {
display: block;
width: 100%; height: 100%;
object-fit: contain;
}
/* Ohne bekannte Masse gibt es kein Verhaeltnis, an dem der Kasten
haengen koennte. Dann greift der alte Weg -- und der Zuhoerer auf
`load` in chat.js haelt den Bildlauf unten. */
.chat-bild:not([style*="aspect-ratio"]) img { height: auto; max-height: 340px; }
.chat-bild:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
.chat-bild[data-kaputt="ja"] {
line-height: 1.5; padding: 12px 14px;
font-size: .84rem; color: var(--text-leise);
}
/* ---- Ein PDF als Karte ---------------------------------------------- */
.chat-datei {
display: flex; align-items: center; gap: 11px;
margin: 0 0 6px; padding: 10px 12px;
border: 1px solid rgba(150, 186, 220, .2);
border-radius: 12px;
background: rgba(255, 255, 255, .04);
color: inherit; text-decoration: none;
transition: border-color var(--tempo), background var(--tempo);
}
.chat-datei:hover {
border-color: rgba(150, 186, 220, .38);
background: rgba(255, 255, 255, .07);
}
.chat-datei:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
.chat-datei__zeichen {
flex: none;
width: 38px; height: 38px; border-radius: 10px;
display: grid; place-items: center;
font-size: .72rem; font-weight: 800; letter-spacing: .04em;
color: #ff9aa2;
background: rgba(255, 154, 162, .12);
border: 1px solid rgba(255, 154, 162, .3);
}
.chat-datei__mitte { min-width: 0; display: grid; }
.chat-datei__name {
font-size: .86rem; font-weight: 600; color: var(--text);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-datei__mass { font-size: .74rem; color: var(--text-leise); }
/* ---- Die Ablagefläche beim Hineinziehen ------------------------------ */
.chat__ablage {
position: absolute; inset: 8px;
z-index: 6;
display: grid; place-items: center;
border: 2px dashed color-mix(in srgb, var(--akzent) 55%, transparent);
border-radius: 16px;
background: rgba(8, 12, 20, .82);
color: var(--text);
font-size: .95rem; font-weight: 650;
pointer-events: none; /* sonst frisst sie das drop-Ereignis */
}
/* ---- Zwischenstand statt Störung ------------------------------------ */
/* "wird geschickt …" ist keine Fehlermeldung. Rot ist hier das
Einzige, was Aufmerksamkeit verlangen darf -- wer es für
Zwischenstände mitbenutzt, macht es wertlos. */
.fehler[data-art="lauf"] { color: var(--text-leise); }
@media (prefers-reduced-motion: reduce) {
.chat__weg, .chat__anhang, .chat-datei { transition: none; }
}
@media (forced-colors: active) {
.chat-datei, .chat__ablage { border: 1px solid CanvasText; }
}
/* =====================================================================
KATEGORIE-KANÄLE UND ANGEHEFTETE ANKÜNDIGUNGEN (10.09.2026)
Kapitel 7.2 des Anforderungsdokuments: "Kategorie-Kanäle" und
"Ankündigungs-Funktion: Pin-Nachrichten von Owner/rechte Hand an
alle."
DER TON IST GEDÄMPFTES BERNSTEIN, nicht Signalgelb. Eine Ankündigung
steht dauerhaft oben im Bild – sie ist das Element, das am längsten
im Blick liegt, und genau deshalb darf es nicht das lauteste sein.
Auffallen soll sie durch ihre POSITION, nicht durch ihre Farbe.
===================================================================== */
.chat {
/* Bernstein, entsättigt. Auf dem dunklen Grund der Seite kommt es
als warmes Signal an, ohne zu blenden. */
--pin: #d9ae62;
}
/* ---- Ein Kanal in der Gesprächsliste -------------------------------- */
/* Die Raute statt einer Zahl oder Initiale: Ein Kanal hat keine feste
Größe (es kommen Leute dazu) und keinen Menschen dahinter. Eckiger
als ein Kreis, runder als eine Gruppe -- so sind die drei Arten auch
ohne Farbe auseinanderzuhalten. */
.chat-raum__zeichen[data-kanal="ja"] {
--r: var(--pin);
border-radius: 10px;
font-size: 1.05rem;
font-weight: 700;
}
/* ---- Die Pinnwand über dem Verlauf ---------------------------------- */
.chat-pins {
flex: none;
display: flex; flex-direction: column; gap: 6px;
padding: 8px 12px;
border-bottom: 1px solid var(--rand);
background: color-mix(in srgb, var(--pin) 6%, transparent);
}
/* Drei Aushänge sind das Höchste (PIN_MAX im Server). Selbst dann
bleibt die Wand niedrig genug, dass der Verlauf die Seite behält --
mehr als ein Drittel der Höhe darf sie nie nehmen. */
.chat-pin {
display: flex; align-items: stretch; gap: 8px;
border: 1px solid color-mix(in srgb, var(--pin) 26%, transparent);
border-radius: 10px;
background: rgba(255, 255, 255, .025);
}
.chat-pin__auf {
flex: 1; min-width: 0;
display: block; text-align: left;
appearance: none; border: 0; background: none;
padding: 7px 10px;
font: inherit; color: inherit; cursor: pointer;
border-radius: 10px 0 0 10px;
}
.chat-pin__auf:hover { background: rgba(255, 255, 255, .03); }
.chat-pin__auf:focus-visible { outline: 2px solid var(--akzent); outline-offset: -2px; }
.chat-pin__kopf {
display: flex; align-items: center; gap: 6px;
font-size: .72rem; line-height: 1.2;
}
.chat-pin__nadel { flex: none; width: 13px; height: 13px; color: var(--pin); }
.chat-pin__von { font-weight: 700; color: var(--pin); }
/* Wer angeheftet hat, steht daneben und nicht darunter: Es ist eine
Randnotiz, keine zweite Zeile. Am Handy fällt sie weg -- dort zählt
der Text der Ankündigung, nicht ihre Herkunft. */
/* .72rem und nicht .68 (10.09.2026, gefunden von pruef-css-klassen).
Unter 11,5 px wird Text auf einem Handy zur Zumutung -- und diese
Zeile steht dauerhaft im Bild. Sie soll leiser sein als der Text
daneben; das macht die FARBE, nicht die Groesse. */
.chat-pin__wer { color: var(--text-still); font-size: .72rem; }
.chat-pin__text {
display: block; margin-top: 2px;
font-size: .8rem; color: var(--text-leise);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.chat-pin__los {
flex: none;
appearance: none; border: 0; border-left: 1px solid color-mix(in srgb, var(--pin) 20%, transparent);
background: none; padding: 0 10px;
font: inherit; font-size: .72rem;
color: var(--text-still); cursor: pointer;
border-radius: 0 10px 10px 0;
}
.chat-pin__los:hover { color: var(--text); background: rgba(255, 255, 255, .04); }
.chat-pin__los:focus-visible { outline: 2px solid var(--akzent); outline-offset: -2px; }
@media (max-width: 560px) {
.chat-pin__wer { display: none; }
}
/* ---- Die angeheftete Nachricht im Verlauf --------------------------- */
/* Ein schmaler Streifen an der Blase, mehr nicht. Wer im Verlauf
zurückrollt, soll erkennen, dass genau DIESE Zeile oben hängt --
ohne dass sie sich wie eine andere Sorte Nachricht liest. */
.chat-nachricht[data-angeheftet="ja"] .chat-nachricht__blase {
box-shadow: inset 3px 0 0 color-mix(in srgb, var(--pin) 70%, transparent);
}
/* Der Anheften-Knopf sieht aus wie "antworten" daneben -- dieselbe
Sorte Handgriff, dieselbe Zeile, dieselbe Lautstärke. */
.chat-nachricht__pin-knopf {
appearance: none; border: 0; background: none; padding: 0;
font: inherit; font-size: .72rem; font-weight: 600;
color: inherit; cursor: pointer;
text-decoration: underline; text-underline-offset: 2px;
}
.chat-nachricht__pin-knopf:hover { color: var(--pin); }
.chat-nachricht__pin-knopf:focus-visible {
outline: 2px solid var(--akzent); outline-offset: 2px; border-radius: 4px;
}
/* ---- Wer ist im Kanal ----------------------------------------------- */
/* Derselbe Knopf wie das Wegräumen, nur wird er beim Darüberfahren
nicht rot: Leute hinzuzunehmen ist keine gefährliche Handlung. */
.chat__leute { margin-left: auto; }
.chat__leute:hover {
color: var(--pin);
border-color: color-mix(in srgb, var(--pin) 45%, transparent);
}
/* ---- Die zwei Arten im Neu-Dialog ----------------------------------- */
.neu__art {
display: flex; gap: 6px;
margin: 0 0 9px;
padding: 4px;
border: 1px solid var(--rand); border-radius: 12px;
background: rgba(255, 255, 255, .02);
}
/* Die Erklaerung zum Umschalter (11.09.2026). Gedaempft und klein --
sie soll beim ERSTEN Mal gelesen werden und danach nicht im Weg sein.
Der Rand links fuehrt das Auge an beiden Zeilen entlang, ohne dass es
ein Kasten sein muss. */
.neu__erklaerung {
margin: 0 0 14px;
padding: 2px 0 2px 11px;
border-left: 2px solid color-mix(in srgb, var(--akzent) 34%, transparent);
font-size: .79rem; line-height: 1.55;
color: var(--text-still);
}
.neu__erklaerung p { margin: 0; }
.neu__erklaerung p + p { margin-top: 5px; }
.neu__erklaerung strong { color: var(--text-leise); font-weight: 650; }
.neu__erklaerung em { font-style: normal; color: var(--text-leise); }
.neu__art button {
flex: 1;
appearance: none; border: 0; border-radius: 9px;
padding: 8px 10px;
background: none;
font: inherit; font-size: .82rem; font-weight: 600;
color: var(--text-still); cursor: pointer;
transition: color var(--tempo), background var(--tempo);
}
.neu__art button[data-an="ja"] {
background: color-mix(in srgb, var(--akzent) 14%, transparent);
color: var(--text);
}
.neu__art button:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
.neu__hinweis {
margin: 6px 0 0;
font-size: .78rem; color: var(--text-still);
}
@media (prefers-reduced-motion: reduce) {
.chat-pin__auf, .chat-pin__los, .neu__art button { transition: none; }
}
/* =====================================================================
TELEFONIEREN (18.09.2026)
Filipe: „kann man machen dass die modis, rechte hand und ich auch
telefonieren können im chat?"
DER KASTEN SCHWEBT UNTEN RECHTS und nimmt dem Gespräch nichts weg.
Ein Anruf ersetzt den Chat nicht -- man schreibt oft WÄHREND man
spricht („schick mir mal den Link"). Ein Vollbild-Anruf hätte genau
das unmöglich gemacht.
Am Handy geht er über die volle Breite: Dort ist daneben ohnehin
kein Platz, und ein halber Kasten wäre nur im Weg.
===================================================================== */
.anruf {
position: fixed;
right: 18px; bottom: 18px;
z-index: 60;
width: min(340px, calc(100vw - 36px));
padding: 14px 16px;
border: 1px solid color-mix(in srgb, var(--gut, #79d1a2) 40%, var(--rand));
border-radius: 14px;
/* Undurchsichtig gemischt: Ein Anrufkasten, durch den das
Bühnenbild scheint, ist genau dann schlecht lesbar, wenn es
schnell gehen muss. */
background: color-mix(in srgb, var(--tinte) 92%, #ffffff 8%);
box-shadow: 0 18px 44px -20px rgba(0, 0, 0, .9);
}
.anruf__kopf {
display: flex; align-items: baseline; gap: 10px;
margin-bottom: 10px;
}
.anruf__lage {
font-size: .86rem; font-weight: 600;
color: color-mix(in srgb, var(--gut, #79d1a2) 30%, #ffffff);
}
.anruf__zeit {
margin-inline-start: auto;
font-size: .82rem; color: var(--text-still);
/* Gleiche Ziffernbreite -- sonst zappelt die Uhr bei jedem Wechsel. */
font-variant-numeric: tabular-nums;
}
.anruf__leute {
display: flex; flex-wrap: wrap; gap: 8px;
margin-bottom: 12px;
}
.anruf__bild {
width: 100%; max-width: 150px; aspect-ratio: 4 / 3;
border-radius: 10px;
background: #05070e;
object-fit: cover;
}
/* Das eigene Bild kleiner -- man schaut die anderen an, nicht sich. */
.anruf__bild--ich { max-width: 88px; }
.anruf__name { font-size: .8rem; color: var(--text-leise); }
.anruf__knoepfe { display: flex; flex-wrap: wrap; gap: 8px; }
.anruf__knopf {
min-height: 40px;
padding: 8px 14px;
border: 1px solid var(--rand-hell);
border-radius: 999px;
background: color-mix(in srgb, var(--tinte) 88%, #ffffff 12%);
color: var(--text);
font: inherit; font-size: .84rem; font-weight: 600;
cursor: pointer;
}
.anruf__knopf:hover { border-color: var(--akzent); }
.anruf__knopf:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* Aus heißt aus -- und zwar sichtbar. Ein stummes Mikrofon, das
aussieht wie ein offenes, ist der Grund, warum Leute in Konferenzen
ins Leere reden. */
.anruf__knopf[aria-pressed="false"] {
border-style: dashed;
color: var(--text-still);
}
.anruf__knopf--auf {
margin-inline-start: auto;
border-color: color-mix(in srgb, var(--warn, #ff9aa2) 55%, var(--rand));
color: color-mix(in srgb, var(--warn, #ff9aa2) 40%, #ffffff);
}
.anruf__knopf--auf:hover { border-color: var(--warn, #ff9aa2); }
/* Das Fragezeichen neben den Anrufknöpfen. Gleiche Größe wie sie,
damit die Reihe ruhig bleibt -- aber blass, weil es kein Angebot
ist, sondern ein Ausweg. */
.chat__probe {
display: inline-flex; align-items: center; justify-content: center;
color: var(--text-still);
font-weight: 700; font-size: .9rem;
text-decoration: none;
}
.chat__probe:hover { color: var(--text-leise); }
/* Der Weg zur Anruf-Probe. Bewusst unscheinbar: Wer gerade
telefoniert, soll ihn übersehen -- wer ratlos vor einem stillen
Kasten sitzt, findet ihn. In der installierten App ist er der
EINZIGE Weg dorthin, weil es dort keine Adresszeile gibt. */
.anruf__probe {
display: inline-block;
margin-top: 10px;
font-size: .78rem;
color: var(--text-still);
text-decoration: underline;
text-decoration-color: var(--rand-hell);
text-underline-offset: 3px;
}
.anruf__probe:hover { color: var(--text-leise); }
/* Wohin der Ton geht -- nur auf Rechnern, wo der Browser das wirklich
umstellen kann. Schmal gehalten: Geraetenamen wie „Kopfhoerer
(RODECaster Duo Main)" wuerden die Knopfreihe sonst sprengen. */
.anruf__ausgabe {
max-width: 11rem;
min-height: 40px;
padding: 6px 10px;
border: 1px solid var(--rand-hell);
border-radius: 999px;
background: color-mix(in srgb, var(--tinte) 88%, #ffffff 12%);
color: var(--text);
font: inherit; font-size: .8rem;
text-overflow: ellipsis;
}
.anruf__ausgabe:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* ---------------------------------------------------------------------
ES KLINGELT
MITTIG UND ÜBER ALLEM. Ein Anruf, den man übersieht, ist ein
verpasster -- das ist der eine Fall, in dem etwas den Bildschirm
unterbrechen darf.
--------------------------------------------------------------------- */
.anruf-klingelt {
position: fixed;
left: 50%; top: 24px;
transform: translateX(-50%);
z-index: 70;
width: min(380px, calc(100vw - 32px));
padding: 16px 18px;
border: 1px solid color-mix(in srgb, var(--akzent) 50%, var(--rand));
border-radius: 14px;
background: color-mix(in srgb, var(--tinte) 94%, #ffffff 6%);
box-shadow: 0 22px 50px -18px rgba(0, 0, 0, .95);
text-align: center;
}
.anruf-klingelt__wer {
margin: 0 0 12px;
font-size: .96rem; font-weight: 700;
}
.anruf-klingelt__knoepfe { display: flex; gap: 10px; justify-content: center; }
.anruf-klingelt__ja, .anruf-klingelt__nein {
min-height: 44px;
padding: 10px 20px;
border-radius: 999px;
font: inherit; font-size: .88rem; font-weight: 700;
cursor: pointer;
}
.anruf-klingelt__ja {
border: 1px solid color-mix(in srgb, var(--gut, #79d1a2) 60%, transparent);
background: color-mix(in srgb, var(--gut, #79d1a2) 18%, var(--tinte));
color: #ffffff;
}
.anruf-klingelt__nein {
border: 1px solid var(--rand-hell);
background: none;
color: var(--text-leise);
}
.anruf-klingelt__ja:focus-visible,
.anruf-klingelt__nein:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* Die zwei Knöpfe im Kopf des Gesprächs. Gebaut wie die Nachbarn
daneben, damit die Zeile eine Sprache spricht. */
.chat__anruf svg {
width: 18px; height: 18px;
fill: none; stroke: currentColor; stroke-width: 1.7;
stroke-linecap: round; stroke-linejoin: round;
}
.chat__anruf:hover { color: color-mix(in srgb, var(--gut, #79d1a2) 40%, #ffffff); }
@media (max-width: 560px) {
.anruf {
right: 8px; left: 8px; bottom: 8px;
width: auto;
}
}
@media (prefers-reduced-motion: reduce) {
.anruf, .anruf-klingelt { transition: none; }
}
/* =====================================================================
DIE NACHTRUHE DES TREFFS (19.09.2026)
Filipe: „nach mitternacht bis morgens 6 uhr keiner schreiben kann
damit auch die privatsphäre berücksichtig wird über nacht."
---------------------------------------------------------------------
KEIN ROT, UND ZWAR AUS EINEM GRUND
Der schlafende Chat ist keine Störung und kein Fehler – er ist so
gewollt. Eine Warnfarbe würde sagen „hier stimmt etwas nicht", und
das ist das Gegenteil der Botschaft. Sie wäre außerdem die dritte
Signalfarbe auf dieser Seite, und ab der dritten bedeutet keine mehr
etwas.
Stattdessen ein tiefes, ruhiges Blau – die Farbe, die jedes
Betriebssystem für „Nicht stören" benutzt. Wer es sieht, weiß es
ohne zu lesen.
ZWEI ZUSTÄNDE, zwei Helligkeiten:
zu das Band steht ruhig da, der Mond gefüllt
gleich ein Hauch wärmer – es ist noch offen, aber nicht lange
AUGENSCHONEND heißt hier auch: keine Animation. Ein pulsierendes
Band über dem Eingabefeld, stundenlang, wäre genau die Art von
Unruhe, die diese Seite nicht haben soll.
===================================================================== */
.chat__nachtruhe {
display: flex; align-items: center; gap: 10px;
margin: 0; padding: 9px 14px;
border-top: 1px solid var(--rand);
background: color-mix(in srgb, var(--tinte) 88%, #2b4a7a 12%);
font-size: .82rem; line-height: 1.5;
color: var(--text-leise);
}
.chat__nachtruhe[data-lage="gleich"] {
background: color-mix(in srgb, var(--tinte) 90%, #7a5a2b 10%);
}
.chat__nachtruhe-zeichen {
flex: none; display: grid; place-items: center;
width: 22px; height: 22px;
}
.chat__nachtruhe-zeichen svg {
width: 17px; height: 17px;
fill: #9db4d8; stroke: none;
}
.chat__nachtruhe[data-lage="gleich"] .chat__nachtruhe-zeichen svg { fill: #d8a76a; }
.chat__nachtruhe-text { min-width: 0; }
/* Das Eingabefeld, wenn der Treff schläft. Sichtbar aus, nicht weg:
Ein verschwundenes Feld sieht aus wie ein Fehler, ein ausgegrautes
wie eine Entscheidung. */
.chat__eingabe #text:disabled,
.chat__eingabe .chat__senden:disabled {
opacity: .5;
cursor: not-allowed;
}
@media (forced-colors: active) {
.chat__nachtruhe { border: 1px solid CanvasText; }
.chat__nachtruhe-zeichen svg { fill: CanvasText; }
}