Files
dogfather-universe/workspace/assets/css/bereich.css
T
DogFatherGitandClaude Opus 5 f05783ebc8 Link einfuegen, Video steht in der App -- Stufe A des Video-Plans
Filipe: "damit meine videos auch da auf der app rein kommen ... sobald
ich ein video poste erscheint es sofort in der app fuer die ganze
community ... dass man das Coverbild und den Text sieht ... fuer meinen
Account, dann DogFather Clips und HasiDog."

Der Weg, der HEUTE funktioniert -- ohne Freigabe, ohne Geheimnis, ohne
Wartezeit: Adresse einfuegen, alles andere geht von allein.

  Link -> oEmbed (Titel, Cover-Adresse, Account)
       -> Cover HERUNTERLADEN und bei uns ablegen
       -> Eintrag mit Bild, Text und Knopf zum Video

DAS COVER WIRD KOPIERT, NICHT VERLINKT -- der wichtigste Satz.
TikToks Bildadresse ist signiert und laeuft ab. Heute an einem echten
Video nachgemessen: x-expires = 1789812000, also in 48 Stunden. Wer sie
nur speichert, hat uebermorgen schwarze Kacheln. Beim Bauen merkt man
das nicht und beim Testen auch nicht -- es faellt erst am uebernaechsten
Tag auf, und dann sieht die ganze App kaputt aus.

Deshalb wandert das Bild in dieselbe Ablage wie jeder Anhang und geht
durch dieselbe Bytepruefung. Ein heruntergeladenes Cover ist eine
FREMDE Datei; dass der Typ hier von einem fremden Server behauptet wird
statt vom eigenen Browser, macht ihn nicht glaubwuerdiger.

NUR SEINE EIGENEN KANAELE. Der Account aus der Antwort wird gegen
KANAELE geprueft (kanalVonHandle). Genommen wird author_url (.../@name),
nicht author_name -- der Anzeigename aendert sich, wenn jemand ihn
umstellt. Ein fremdes Video in Filipes Highlights waere nicht bloss
falsch einsortiert, es waere fremder Inhalt unter seinem Namen: 403.

DIE PRUEFUNG SCHALTET TIKTOK AB (server/pruef-video.mjs, 37 Pruefungen)
Ein nachgebauter Dienst auf 127.0.0.1 antwortet wie TikTok, mitsamt
Ablaufstempel. Im letzten Abschnitt wird er ABGESCHALTET. Danach muss
die alte Cover-Adresse ins Leere laufen und unsere weiterhin ein Bild
liefern -- beides wird gemessen, nebeneinander. Waere das Bild nur
verlinkt, waeren beide tot, genau wie uebermorgen im Betrieb.

Die Adresse des Dienstes kommt aus TIKTOK_OEMBED_BASIS. Steht sie nicht
da, gilt TikTok -- kein Verhalten, das sich still aendert. Eine
Pruefung, die das echte TikTok braucht, misst fremde Verfuegbarkeit
statt unseren Code und wird irgendwann rot, ohne dass etwas kaputt ist.

VIER GEGENPROBEN, weil 37 von 37 im ersten Lauf kein Beweis ist:
  a) Cover nicht mehr kopieren      -> 9 Pruefungen rot
  b) author_name statt author_url   -> 22 rot
  c) Bytepruefung entfernen         -> 2 rot (genau Abschnitt 5)
  d) Dublettenpruefung entfernen    -> 4 rot (genau Abschnitt 4)
Jede schlaegt dort an, wo sie soll. Und eine fuenfte Gegenprobe ist ins
Leere gelaufen: Der Patch lief ueber python3, das es hier nicht gibt --
die Datei blieb unveraendert und der Lauf war gruen. Haette ich die
Ausgabe nicht gelesen, haette ich behauptet, die Pruefung koenne rot
werden, ohne sie je rot gesehen zu haben. Der dritte Ausgang, an mir
selbst.

DAZU:
- eintraege.quelle_url / quelle_kanal / quelle_geholt_am (Umstellung)
- KANAELE bekommt handle, dazu kanalVonHandle()
- videoRouter steht VOR bereicheRouter, sonst schluckt /:bereich ihn
- Eingabefeld und Kanal-Knopf in bereich.html/.js, Farben wie bei den
  Aufgaben-Kanaelen
- Stempel 202609171249

Nicht darin: die Kanal-Filterzeile in der Galerie, die Handy-Verknuepfung
(Teilen -> Workspace) und der Zustand "nicht mehr da" fuer geloeschte
Videos. Stufe B (Display API) braucht Filipes Entwickler-Freigabe.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-17 12:50:42 +02:00

1167 lines
46 KiB
CSS

/* ===================================================================
Gemeinsame Ansicht für LIVE, Content, Technik, Community und Schutz.
=================================================================== */
.eintrag-karte {
padding: 15px 17px; margin-bottom: 10px;
background: var(--flaeche);
border: 1px solid var(--rand);
border-left: 3px solid var(--rand);
border-radius: var(--radius-klein);
}
.eintrag-karte[data-dringlich="hoch"] { border-left-color: #d8656e; }
.eintrag-karte[data-dringlich="mittel"] { border-left-color: #4b6c8a; }
.eintrag-karte[data-dringlich="niedrig"] { border-left-color: #3c4a5a; }
.eintrag-karte[data-status="erledigt"] { opacity: .55; }
.eintrag-kopf {
display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px;
}
.eintrag-titel { font-weight: 600; font-size: .96rem; flex: 1 1 240px; }
.marke-art {
padding: 1px 9px; border-radius: 999px;
background: rgba(63, 189, 245, .14); color: #7fd2fb;
font-size: .68rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
white-space: nowrap;
}
/* Bewertung als Punktreihe statt als Zahl -- auf einen Blick erfassbar,
und ohne Sterne, die im Dunkeln flimmern. */
.bewertung { display: inline-flex; gap: 3px; align-items: center; }
.bewertung__punkt {
width: 7px; height: 7px; border-radius: 50%;
background: rgba(150, 186, 220, .22);
}
.bewertung__punkt[data-voll="ja"] { background: var(--akzent); }
.eintrag-text {
margin: 9px 0 0; font-size: .87rem; color: var(--text-leise);
line-height: 1.55; white-space: pre-wrap;
}
.eintrag-fuss {
display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
margin-top: 11px; font-size: .77rem; color: var(--text-still);
}
.eintrag-knoepfe { display: flex; gap: 6px; margin-left: auto; flex-wrap: wrap; }
/* =====================================================================
DER TREFF (11.09.2026)
Drei Zusaetze, und nur auf den sieben Brettern der Community.
SIE STEHEN IN EINER EIGENEN ZEILE UNTER DEM FUSS und nicht darin.
Der Fuss ist eine Auskunft (Datum, wer, Stand); hier stehen Dinge,
die man TUT. Zusammen in einer Reihe waere "von Frida" so breit wie
"Will ich auch" -- und auf einem Handy laege beides ineinander.
===================================================================== */
.treff-knoepfe {
display: flex; gap: 7px; flex-wrap: wrap; align-items: center;
margin-top: 10px; padding-top: 10px;
border-top: 1px solid var(--rand);
}
/* Der Rollenname am Beitrag. Leise, aber nicht versteckt: Er soll
beim Lesen auffallen, ohne den Beitrag zu ueberschreiben. Deshalb
dieselbe Groesse wie der Fuss und nur ein kraeftigerer Ton. */
.treff-rolle {
color: var(--text-leise);
font-weight: 600;
letter-spacing: .01em;
}
/* "Will ich auch". Der einzige Knopf auf diesen Brettern, der keine
Verwaltung ist, sondern eine Meinung -- er darf deshalb als
einziger einen Ton tragen.
GEDRUECKT WIRD ER RUHIGER, NICHT LAUTER. Der naheliegende Entwurf
waere ein kraeftiges Leuchten fuer "ich bin dabei". Nur sieht man
auf einer Wunschliste meist ZEHN Karten gleichzeitig, und wer bei
der Haelfte mitgestimmt hat, saehe zehn leuchtende Flaechen
untereinander. Das ist genau das, was diese Seite nicht sein soll
(Hausregel: augenschonend). Der gedrueckte Zustand bekommt deshalb
eine gefuellte Flaeche in gedecktem Ton, der ungedrueckte bleibt
ein Umriss -- unterscheidbar, ohne zu blenden. */
.treff-will {
font: inherit; font-size: .8rem; font-weight: 600;
padding: 6px 12px; border-radius: 999px; cursor: pointer;
color: var(--text-leise);
background: transparent;
border: 1px solid var(--rand-hell);
transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.treff-will:hover:not(:disabled) {
color: var(--text);
border-color: color-mix(in srgb, var(--akzent) 45%, transparent);
}
.treff-will[aria-pressed="true"] {
color: var(--text);
background: color-mix(in srgb, var(--akzent) 14%, transparent);
border-color: color-mix(in srgb, var(--akzent) 42%, transparent);
}
.treff-will:disabled { opacity: .55; cursor: default; }
/* Dieselbe Ruecksicht wie ueberall: Wer Bewegung abbestellt hat,
bekommt keine. */
@media (prefers-reduced-motion: reduce) {
.treff-will { transition: none; }
}
.filter { display: flex; gap: 8px; margin: 0 0 20px; flex-wrap: wrap; }
.filter .schritt[aria-pressed="true"] {
/* Gedrueckt = der "voll"-Auftritt des Knopf-Systems. Vorher stand
hier eine eigene Flaeche, die den geschliffenen Rand ueberschrieb. */
--f: var(--akzent);
color: #fff;
background:
linear-gradient(color-mix(in srgb, var(--f) 20%, #121926),
color-mix(in srgb, var(--f) 12%, #0d1420)) padding-box,
linear-gradient(150deg, var(--f),
color-mix(in srgb, var(--f) 45%, transparent)) border-box;
box-shadow: 0 4px 16px -9px var(--f);
}
@media (max-width: 620px) {
.eintrag-knoepfe { margin-left: 0; width: 100%; }
}
/* =====================================================================
UNTERWEISUNGEN — beidseitig bestaetigen
Drei Stufen, drei Farben. Die mittlere ("halb") ist die wichtigste:
Ein Nachweis, bei dem nur einer unterschrieben hat, ist KEIN Nachweis.
Wer das nicht sieht, haelt ihn fuer fertig -- und merkt es erst, wenn
jemand danach fragt. Deshalb bekommt sie eine eigene, warnende Farbe
und nicht einfach ein blasses Gruen.
===================================================================== */
.schulung { margin: 0 0 30px; }
.schulung__kopf {
display: flex; align-items: flex-end; justify-content: space-between;
gap: 16px; flex-wrap: wrap; margin-bottom: 14px;
}
.schulung__unter {
margin: 4px 0 0; max-width: 68ch;
font-size: .86rem; line-height: 1.55; color: var(--text-leise);
}
.schulung__wahl { display: grid; gap: 4px; min-width: 0; }
.schulung__liste { display: grid; gap: 11px; }
.unterweisung {
--stufe-ton: var(--text-still);
position: relative; overflow: hidden;
padding: 15px 17px 14px;
border: 1px solid color-mix(in srgb, var(--stufe-ton) 26%, var(--rand));
border-radius: var(--radius-klein);
background:
linear-gradient(90deg, color-mix(in srgb, var(--stufe-ton) 8%, transparent), transparent 55%),
var(--flaeche);
}
.unterweisung::before {
content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
background: linear-gradient(180deg, var(--stufe-ton),
color-mix(in srgb, var(--stufe-ton) 30%, transparent));
}
.unterweisung[data-stufe="offen"] { --stufe-ton: #6f89a8; }
/* Bewusst warnend: halb bestaetigt sieht nach fertig aus, ist es aber
nicht. Diese Verwechslung ist genau die, die einen Nachweis wertlos
macht. */
.unterweisung[data-stufe="halb"] { --stufe-ton: #e0a33c; }
.unterweisung[data-stufe="fertig"] { --stufe-ton: #4dab77; }
.unterweisung__kopf {
display: flex; align-items: flex-start; justify-content: space-between;
gap: 14px; margin-bottom: 12px;
}
.unterweisung__titel { margin: 0 0 3px; font-size: .98rem; font-weight: 650; color: var(--text); }
.unterweisung__datei { margin: 0; font-size: .8rem; color: var(--ton, var(--akzent)); }
.unterweisung__text { margin: 5px 0 0; font-size: .85rem; color: var(--text-leise); }
.unterweisung__marke {
flex: none; padding: 3px 11px;
border: 1px solid color-mix(in srgb, var(--stufe-ton) 36%, transparent);
border-radius: 999px;
background: color-mix(in srgb, var(--stufe-ton) 12%, transparent);
color: var(--stufe-ton);
font-size: .72rem; letter-spacing: .06em;
}
/* Die beiden Unterschriften nebeneinander -- man soll auf einen Blick
sehen, WER fehlt, nicht nur DASS etwas fehlt. */
.unterschriften {
display: grid; gap: 8px;
grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
margin-bottom: 12px;
}
/* =====================================================================
SIE SIND UNTERSCHRIFTEN -- ALSO SEHEN SIE JETZT AUCH SO AUS
(screen6, 09.09.2026)
Filipe, mit Bildschirmfoto der beiden Felder: "die sollen geiler
sein."
WAS SIE WIRKLICH SIND, stand nur im Klassennamen: Auf einer
Unterweisung bestaetigen ZWEI Personen, dass sie sie gelesen haben
-- der Creator und seine Betreuung. Das ist kein Statusfeld, das ist
eine Gegenzeichnung. Gezeichnet waren sie aber als zwei graue
Kaesten mit abgerundeten Ecken, die man auf dem dunklen Grund kaum
sah. Zwei Rechtecke sagen "hier steht etwas". Eine Unterschriftszeile
sagt "hier fehlt jemand".
ZWEI ZUSTAENDE, ZWEI BILDER -- und beide gab es im Code schon als
`data-da="ja"/"nein"`, nur unterschieden sie sich um einen Hauch
Gruen:
OFFEN eine gestrichelte Linie mit einem leeren Platz darauf.
Sie WARTET sichtbar. Der Federstrich links davor deutet
an, wo man ansetzt.
DA eine durchgezogene gruene Linie, der Name darueber, und
rechts oben ein gepraegtes Siegel mit Haken -- wie ein
abgestempeltes Formular.
GLEICHE HOEHE IN BEIDEN ZUSTAENDEN, und das ist keine Kosmetik: Die
beiden Felder stehen nebeneinander in einem Raster. Waere das
unterschriebene hoeher, spraenge die Karte in dem Moment, in dem
jemand unterschreibt -- und zwar unter dem Finger dessen, der gerade
auf den Knopf gedrueckt hat.
KEINE ZWEITE FASE. Die Karte drumherum (`.unterweisung`) hat schon
eine aus der Modulliste. Eine abgeschraegte Ecke IN einer
abgeschraegten Ecke liest sich als Fehler, nicht als Absicht. Das
Feld traegt deshalb die andere Formensprache des Hauses: die Linie.
================================================================== */
.unterschrift {
position: relative;
display: grid; gap: 3px;
padding: 9px 12px 11px 15px;
border: 0;
border-radius: 0;
background: linear-gradient(100deg, rgba(255, 255, 255, .035), transparent 60%);
}
/* Der Federstrich links: ein kurzer senkrechter Anstrich, der zeigt,
wo eine Unterschrift beginnt. Offen ist er blass, gesetzt traegt er
das Gruen der Bestaetigung. */
.unterschrift::before {
content: "";
position: absolute; left: 0; top: 8px; bottom: 8px; width: 2px;
background: rgba(150, 186, 220, .22);
transition: background .18s ease;
}
/* Die Zeile selbst -- unter der Angabe, nicht um sie herum. */
.unterschrift::after {
content: "";
position: absolute; left: 15px; right: 12px; bottom: 6px; height: 0;
border-bottom: 1px dashed rgba(150, 186, 220, .30);
}
.unterschrift[data-da="ja"] {
background: linear-gradient(100deg, rgba(95, 201, 154, .11), transparent 62%);
}
.unterschrift[data-da="ja"]::before { background: rgba(95, 201, 154, .8); }
.unterschrift[data-da="ja"]::after {
border-bottom: 1px solid rgba(95, 201, 154, .55);
}
.unterschrift__wer {
font-size: .7rem; letter-spacing: .1em; text-transform: uppercase;
color: var(--text-still);
}
.unterschrift__wann { font-size: .84rem; color: var(--text); }
.unterschrift[data-da="nein"] .unterschrift__wann { color: var(--text-still); font-style: italic; }
/* DAS SIEGEL. Es sitzt in der oberen rechten Ecke des Feldes und ist
nur da, wenn wirklich unterschrieben wurde.
Gebaut aus zwei Radialverlaeufen und einem Haken als Maske -- kein
Element, kein Bild, kein Zeichensatz. Ein Zeichensatz-Haken (✓) sieht
in jeder Schrift anders aus und faellt weg, wenn eine fehlt; ein
`mask-image` mit einem SVG-Pfad sieht ueberall gleich aus.
`content: ""` auf einem dritten Pseudoelement geht nicht -- es gibt
nur zwei. Deshalb haengt es am Wer-Text, der ohnehin oben steht. */
.unterschrift[data-da="ja"] .unterschrift__wer { position: relative; }
.unterschrift[data-da="ja"] .unterschrift__wer::after {
content: "";
/* INNERHALB des Feldes, nicht daneben. Der erste Anlauf schob es mit
`translate(100%)` ueber die rechte Kante hinaus -- bei der breiten
Ansicht sah das gut aus, auf einem schmalen Feld waere es aus der
Karte gelaufen. Ein Siegel gehoert auf das Blatt, nicht daneben. */
position: absolute; right: 0; top: 50%;
transform: translateY(-50%);
width: 15px; height: 15px; border-radius: 50%;
background:
radial-gradient(circle at 50% 26%, rgba(255, 255, 255, .2), transparent 60%),
radial-gradient(circle at 50% 50%, rgba(95, 201, 154, .3) 55%, rgba(10, 24, 19, .95) 100%);
box-shadow:
inset 0 0 0 1px rgba(95, 201, 154, .6),
inset 0 1px 2px -1px rgba(255, 255, 255, .25);
}
/* DER HAKEN IM SIEGEL. Als Maske ueber einer hellgruenen Flaeche --
kein Zeichensatz-Haken (der sieht in jeder Schrift anders aus und
faellt weg, wenn eine fehlt) und kein Bild (eine Datei mehr fuer
fuenfzehn Pixel).
Er liegt auf `::before` desselben Elements, weil es nur zwei
Pseudoelemente je Element gibt und `::after` schon die Muenze
traegt. Beide sind absolut gesetzt und liegen deshalb genau
uebereinander. */
.unterschrift[data-da="ja"] .unterschrift__wer::before {
content: "";
position: absolute; right: 0; top: 50%;
transform: translateY(-50%);
width: 15px; height: 15px;
z-index: 1;
background: #a8ecc8;
-webkit-mask: center / 9px 9px no-repeat
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m5 12.6 4.4 4.4L19 7.4' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
mask: center / 9px 9px no-repeat
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m5 12.6 4.4 4.4L19 7.4' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion: reduce) {
.unterschrift::before { transition: none; }
}
.unterweisung__fuss { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.unterweisung__fest { font-size: .82rem; color: #6fbd95; }
.unterweisung__wartet { font-size: .82rem; color: #e0b45c; }
/* Ausgetauschtes Dokument: Das ist der einzige Fall, in dem ein
abgeschlossener Nachweis seinen Wert verliert -- und dann muss es
auch laut sein. */
.unterweisung__warnung {
padding: 3px 10px;
border: 1px solid rgba(255, 154, 162, .4); border-radius: 999px;
background: rgba(255, 154, 162, .1);
color: var(--warn); font-size: .8rem; font-weight: 600;
}
.schulung__neu {
margin-top: 18px; padding: 16px 17px;
border: 1px dashed var(--rand); border-radius: var(--radius-klein);
background: var(--flaeche);
}
.schulung__neu .neu__raster { margin-top: 12px; }
.schulung__neu .knopf { margin-top: 12px; }
@media (max-width: 560px) {
.schulung__kopf { flex-direction: column; align-items: stretch; }
.unterweisung__kopf { flex-direction: column; }
.unterweisung__marke { align-self: flex-start; }
}
/* =====================================================================
AMPEL UND RUECKMELDUNG
Drei Stufen, drei Farben. Die Stufe steht IMMER da -- auch fuer den
Creator, auch wenn sie "noch nicht angesehen" lautet. Das ist der
ganze Sinn: Er soll sehen, wo er steht, ohne fragen zu muessen.
===================================================================== */
.ampel {
--a-ton: #6f89a8;
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
margin-top: 11px; padding-top: 11px;
border-top: 1px solid var(--rand);
}
.ampel[data-stufe="gut"] { --a-ton: #4dab77; }
.ampel[data-stufe="verbessern"] { --a-ton: #e0a33c; }
.ampel[data-stufe="offen"] { --a-ton: #6f89a8; }
.ampel__marke {
display: inline-flex; align-items: center; gap: 7px;
padding: 3px 11px;
border: 1px solid color-mix(in srgb, var(--a-ton) 38%, transparent);
border-radius: 999px;
background: color-mix(in srgb, var(--a-ton) 13%, transparent);
color: var(--a-ton);
font-size: .76rem; font-weight: 600;
}
.ampel__marke::before {
content: ""; width: 8px; height: 8px; border-radius: 50%;
background: var(--a-ton);
box-shadow: 0 0 8px color-mix(in srgb, var(--a-ton) 70%, transparent);
}
.ampel__von { font-size: .76rem; color: var(--text-still); }
/* Der Grund steht auf einer eigenen Zeile und in voller Breite --
"noch verbessern" ohne Grund ist nicht umsetzbar, nur entmutigend.
Deshalb darf er nicht in eine Ecke gequetscht werden. */
.ampel__grund {
flex-basis: 100%; margin: 4px 0 0;
padding: 8px 11px;
border-left: 2px solid var(--a-ton);
border-radius: 0 6px 6px 0;
background: color-mix(in srgb, var(--a-ton) 8%, transparent);
font-size: .85rem; line-height: 1.5; color: var(--text);
}
.ampel .schritt { margin-left: auto; }
/* ---------- Der ausgeklappte Bereich ------------------------------------ */
.rueckmeldung {
margin-top: 11px; padding: 13px 14px;
border: 1px solid var(--rand); border-radius: var(--radius-klein);
background: rgba(0, 0, 0, .2);
}
.rueckmeldung__hinweis {
margin: 0 0 12px; font-size: .84rem; color: var(--text-leise);
}
.rueckmeldung__bewerten { margin-bottom: 14px; }
.ampel__wahl { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 8px; }
.ampel__knopf {
padding: 8px 14px;
border: 1px solid var(--rand); border-radius: 999px;
background: var(--flaeche);
color: var(--text-leise);
font: inherit; font-size: .84rem; cursor: pointer;
transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.ampel__knopf[data-stufe="gut"]:hover,
.ampel__knopf[data-stufe="gut"][data-an="ja"] {
border-color: rgba(77, 171, 119, .5); color: #6fbd95;
background: rgba(77, 171, 119, .12);
}
.ampel__knopf[data-stufe="verbessern"]:hover,
.ampel__knopf[data-stufe="verbessern"][data-an="ja"] {
border-color: rgba(224, 163, 60, .5); color: #e0b45c;
background: rgba(224, 163, 60, .12);
}
/* ---------- Das Gespraech ------------------------------------------------ */
.nachrichten { display: grid; gap: 8px; margin-bottom: 12px; }
.nachrichten__leer { margin: 0; font-size: .84rem; color: var(--text-still); }
.nachricht {
padding: 9px 12px;
border: 1px solid var(--rand); border-radius: 9px;
background: var(--flaeche);
}
/* Eigene Nachrichten heben sich ab -- in einem Gespraech will man auf
einen Blick sehen, was man selbst gesagt hat. */
.nachricht[data-eigen="ja"] {
border-color: color-mix(in srgb, var(--akzent) 26%, transparent);
background: color-mix(in srgb, var(--akzent) 7%, var(--flaeche));
}
.nachricht__kopf {
display: flex; align-items: center; gap: 9px;
margin-bottom: 4px;
}
.nachricht__von { font-size: .8rem; font-weight: 650; color: var(--text); }
.nachricht__wann { font-size: .74rem; color: var(--text-still); }
.nachricht__weg {
margin-left: auto;
width: 24px; height: 24px;
border: 0; border-radius: 6px;
background: none; color: var(--text-still);
font-size: 1rem; line-height: 1; cursor: pointer;
}
.nachricht__weg:hover { color: var(--warn); background: rgba(255, 154, 162, .1); }
.nachricht__text {
margin: 0; font-size: .87rem; line-height: 1.55; color: var(--text);
white-space: pre-wrap; overflow-wrap: anywhere;
}
.nachricht-neu { display: grid; gap: 8px; }
/* Aussehen, Rahmen, Schrift und Fokusring stehen seit dem 01.09.2026
EINMAL in start.css (":where(.inhalt) :where(input, textarea, select)").
Die Kopie, die hier stand, war Wort fuer Wort dieselbe -- und genau so
entstehen zwei Feld-Optiken auf einer Seite, sobald eine der beiden
verbessert wird. Hier bleibt nur, was WIRKLICH nur hier gilt. */
.nachricht-neu textarea { width: 100%; min-height: 44px; }
.nachricht-neu .knopf { justify-self: start; }
@media (max-width: 560px) {
.ampel .schritt { margin-left: 0; }
.ampel__knopf { flex: 1 1 auto; text-align: center; }
}
/* =====================================================================
AGENTUR-EVENTS (07.09.2026)
Ein Event ist die einzige Eintragsart, die eine LAUFZEIT hat. Alles
andere in diesen Bereichen ist ein Vermerk zu einem Tag; ein Event
ist eine Einladung, an der man teilnehmen kann -- oder eben nicht
mehr. Deshalb ist der Zustand (kommt / läuft / vorbei) das Erste auf
der Karte und nicht eine Fussnote.
Farbe wird hier als AUSKUNFT eingesetzt, nicht als Schmuck: gedecktes
Grün heisst "du kannst mitmachen", Bernstein "noch nicht", Grau
"vorbei". Die Farben stammen aus derselben Familie wie die Ampel
(--k-gut / --k-mittel), damit nicht zwei Bedeutungssysteme
nebeneinander laufen. Und weil Farbe allein nie ausreicht, steht der
Zustand zusaetzlich als WORT da ("läuft bis 30.09.2026").
===================================================================== */
.event-zeitraum {
display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
margin: 2px 0 10px;
font-size: .82rem;
}
.event-zeitraum__marke {
--f: var(--k-neutral);
display: inline-flex; align-items: center; gap: 6px;
padding: 3px 10px;
border: 1px solid color-mix(in srgb, var(--f) 34%, transparent);
border-radius: 999px;
background: color-mix(in srgb, var(--f) 12%, transparent);
color: color-mix(in srgb, var(--f) 82%, #fff);
font-weight: 600; letter-spacing: .01em;
font-variant-numeric: tabular-nums;
}
/* Der Punkt davor ist reine Zierde und darf deshalb NICHT vorgelesen
werden -- ein Screenreader saehe sonst ein Aufzaehlungszeichen mitten
im Satz. */
.event-zeitraum__marke::before {
content: ""; width: 7px; height: 7px; border-radius: 50%;
background: var(--f); flex: none;
}
.event-zeitraum[data-stand="laeuft"] .event-zeitraum__marke { --f: var(--k-gut); }
.event-zeitraum[data-stand="kommt"] .event-zeitraum__marke { --f: var(--k-mittel); }
.event-zeitraum[data-stand="vorbei"] .event-zeitraum__marke { --f: var(--k-neutral); }
.event-zeitraum__spanne {
color: var(--text-leise);
font-variant-numeric: tabular-nums;
}
/* Ein vorbeigelaufenes Event bleibt lesbar, tritt aber zurueck. Kein
display:none -- was gelaufen ist, will man nachschlagen koennen.
Gedaempft wird nur die Flaeche, nicht die Schrift: Text unter 4.5:1
waere nicht mehr lesbar, und "alt" ist kein Grund, jemanden
auszuschliessen. */
.eintrag-karte[data-event="vorbei"] { opacity: .82; }
.event-block {
margin: 10px 0 0;
padding: 10px 12px;
border: 1px solid var(--rand);
border-radius: var(--radius-klein);
background: rgba(255, 255, 255, .022);
}
.event-block__schild {
margin: 0 0 4px;
/* .74rem = 11.84 px, nicht .7rem. Die Schriftgroessen-Pruefung zieht
die Grenze bei 11.5 px, und sie hat recht: In Grossbuchstaben mit
Sperrung wirkt eine Schrift kleiner, als die Zahl sagt -- und das
hier ist die Beschriftung, an der man die Regeln vom Aufgabenteil
unterscheidet. */
font-size: .74rem; font-weight: 700;
letter-spacing: .09em; text-transform: uppercase;
color: var(--text-still);
}
.event-block__text {
margin: 0;
font-size: .87rem; line-height: 1.6; color: var(--text);
/* pre-line, nicht pre-wrap: Zeilenumbrueche bleiben (die Aufzaehlung
ist der Sinn dieser Felder), aber eine versehentlich eingefuegte
Einrueckung aus einer Chatnachricht reisst die Karte nicht auf. */
white-space: pre-line;
overflow-wrap: anywhere;
}
/* .feld-hinweis steht seit dem 07.09.2026 in aufgaben.css -- bei den
uebrigen Formularstilen. Grund: Die Dashboard-Seite braucht ihn jetzt
auch (Creator anlegen), laedt aber diese Datei hier nicht. Ein
Formularbaustein, der in der Bereichsdatei liegt, ist nur so lange
richtig, wie ihn keine zweite Seite braucht. */
@media (max-width: 560px) {
/* Auf dem Handy untereinander: Marke und Spanne nebeneinander
ergaeben bei "vorbei seit 30.09.2026" einen Umbruch mitten im
Datum. */
.event-zeitraum { gap: 6px; }
.event-zeitraum__spanne { flex-basis: 100%; }
}
/* =====================================================================
RÜCKMELDUNG: „fürs Team" oder „nur an DogFather" (10.09.2026)
Kapitel 5 des Pflichtenhefts. Der Schalter steht ÜBER der
Dringlichkeit und nicht darunter: Wer schreibt, soll wissen, wer
mitliest, BEVOR er den Text formuliert -- danach ist die Entscheidung
nur noch eine Korrektur.
===================================================================== */
.vertraulich-zeile {
display: flex; align-items: flex-start; gap: 10px;
padding: 10px 12px;
border: 1px solid var(--rand); border-radius: var(--radius-klein);
background: rgba(255, 255, 255, .02);
cursor: pointer;
}
.vertraulich-zeile input {
/* 18 px und nicht die Vorgabe des Browsers: Das Kästchen ist die
eigentliche Entscheidung auf diesem Formular und darf nicht das
kleinste Element darauf sein. */
flex: none; width: 18px; height: 18px; margin-top: 1px;
accent-color: var(--akzent);
}
.vertraulich-zeile strong {
display: block; font-size: .86rem; color: var(--text);
}
.vertraulich-zeile em {
display: block; margin-top: 2px;
font-size: .76rem; font-style: normal; color: var(--text-still);
}
.vertraulich-zeile:hover { border-color: var(--rand-hell); }
.vertraulich-zeile:focus-within {
outline: 2px solid var(--akzent); outline-offset: 2px;
}
/* Das Kennzeichen an der Zeile selbst. Bewusst eine ANDERE Farbe als
die Art daneben -- zwei gleich aussehende Fähnchen liest man als
eines. Bernstein wie beim angehefteten Chat: derselbe Gedanke
("das hier ist besonders"), dieselbe Farbe. */
.marke-art--nur {
background: rgba(217, 174, 98, .16);
color: #d9ae62;
}
/* =====================================================================
ENTWICKLUNG: der Weg zur Person (11.09.2026)
Der Knopf steht IM KOPF der Karte, neben der Art -- nicht unten bei
den anderen Handgriffen. Er ist keine Bearbeitung, sondern der eine
Schritt, der den Eintrag aus der Aufzeichnung heraus zur Person
bringt; unten zwischen „Ändern" und „Löschen" wäre er einer von
dreien statt der besondere.
===================================================================== */
.eintrag-schicken {
appearance: none;
padding: 2px 11px; border-radius: 999px;
border: 1px solid color-mix(in srgb, var(--akzent) 40%, transparent);
background: color-mix(in srgb, var(--akzent) 12%, transparent);
color: var(--text);
/* .72rem und nicht .68 -- unter 11,5 px gilt im Haus als zu klein,
und dieser Knopf traegt den einzigen Schritt, der einen Eintrag
zur Person bringt. Gefunden von pruef-css-klassen. */
font: inherit; font-size: .72rem; font-weight: 700;
letter-spacing: .04em; text-transform: uppercase;
white-space: nowrap; cursor: pointer;
transition: background var(--tempo), border-color var(--tempo);
}
.eintrag-schicken:hover {
background: color-mix(in srgb, var(--akzent) 22%, transparent);
border-color: color-mix(in srgb, var(--akzent) 60%, transparent);
}
.eintrag-schicken:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
.eintrag-schicken[disabled] { opacity: .5; cursor: default; }
/* Schon geschickt: kein Knopf mehr, sondern eine Auskunft. Leise --
sie ist eine Fußnote, keine Meldung. */
.marke-art--weg {
background: rgba(255, 255, 255, .05);
color: var(--text-still);
text-transform: none; letter-spacing: 0; font-weight: 600;
}
/* =====================================================================
AUS EINER IDEE WURDE ARBEIT (15.09.2026)
Der Verweis steht dort, wo vorher der Knopf stand -- er ersetzt ihn.
Er sieht deshalb aus wie ein Zustand und nicht wie eine Schaltflaeche:
Wer ihn sieht, soll wissen, dass etwas passiert IST, nicht dass er
etwas tun kann.
===================================================================== */
.eintrag__aufgabe {
display: inline-flex; align-items: center; gap: 6px;
font-size: .78rem; font-weight: 600;
padding: 3px 10px; border-radius: 999px;
text-decoration: none;
color: var(--text-leise);
border: 1px solid color-mix(in srgb, #668e6e 50%, transparent);
}
.eintrag__aufgabe:hover { color: var(--text); border-color: #668e6e; }
/* =====================================================================
DER COUNTDOWN BEI „WAS ANSTEHT" (17.09.2026)
Filipe wollte für den Community-Bereich „eine richtige perfektion".
Hier ist das keine Frage der Optik: Es gibt genau EINE Frage, die ein
Zuschauer auf dieser Seite hat — *wann* — und sie stand bisher in
Zeile vier einer Liste.
GROSS, ABER NICHT LAUT. Die Zeitangabe ist das Größte auf der Seite,
weil sie die Antwort ist. Sie leuchtet aber nicht: kein Neon, kein
Blinken, keine Animation. Auf dieser Seite steht niemand unter
Zeitdruck — er will es nur wissen.
DER TON FOLGT DER NÄHE, nicht der Wichtigkeit: Was gleich anfängt,
ist wärmer; was in vier Wochen kommt, ist ruhig. Das ist die einzige
Information, die eine Farbe hier tragen kann, ohne zu behaupten, ein
Termin sei „besser" als ein anderer.
------------------------------------------------------------------- */
.countdown {
--c-ton: #6f89a8;
margin: 0 0 22px;
padding: 20px 22px;
border: 1px solid color-mix(in srgb, var(--c-ton) 30%, var(--rand));
border-radius: var(--radius);
background:
linear-gradient(180deg,
color-mix(in srgb, var(--c-ton) 13%, transparent),
transparent 64%),
var(--flaeche);
}
.countdown[data-stufe="jetzt"] { --c-ton: #d97a45; }
.countdown[data-stufe="bald"] { --c-ton: #e0a33c; }
.countdown[data-stufe="woche"] { --c-ton: #5f93c4; }
.countdown[data-stufe="spaeter"] { --c-ton: #6f89a8; }
.countdown__schild {
margin: 0 0 4px;
font-size: .72rem; font-weight: 600;
letter-spacing: .1em; text-transform: uppercase;
color: color-mix(in srgb, var(--c-ton) 62%, #ffffff);
}
/* DIE ANTWORT. clamp statt fester Größe: Auf 390 px soll sie die Zeile
nicht sprengen, auf dem Rechner soll sie wirken. Eine feste Zahl wäre
an einem der beiden Enden falsch. */
.countdown__wann {
margin: 0;
font-size: clamp(1.7rem, 6vw, 2.5rem);
font-weight: 700; line-height: 1.05;
letter-spacing: -.01em;
color: var(--text);
font-variant-numeric: tabular-nums;
}
.countdown__titel {
margin: 8px 0 0;
font-size: 1.02rem; font-weight: 600; color: var(--text);
}
.countdown__datum {
margin: 3px 0 0;
font-size: .86rem; color: var(--text-leise);
}
.countdown__weitere {
margin: 12px 0 0; padding-top: 10px;
border-top: 1px solid var(--rand);
font-size: .8rem; color: var(--text-still);
}
/* Wenn nichts ansteht: ein Satz, keine leere Fläche. Ein Bereich, der
schweigt, wenn nichts da ist, sieht kaputt aus statt leer. */
.countdown[data-leer] { --c-ton: #6f89a8; }
.countdown__leer { margin: 0; font-size: .95rem; color: var(--text-leise); }
/* ---------------------------------------------------------------------
DER ZEITSTRAHL — die Abschnitte in der Liste darunter
------------------------------------------------------------------- */
.zeitstrahl__schild {
display: flex; align-items: center; gap: 9px;
margin: 26px 0 12px;
font-size: .76rem; font-weight: 650;
letter-spacing: .09em; text-transform: uppercase;
color: var(--text-still);
}
.zeitstrahl__schild:first-child { margin-top: 4px; }
/* Eine Linie, die nach rechts ausläuft — sie trennt, ohne eine Wand zu
bauen. Dieselbe Überlegung wie bei den Spalten des Aufgabenbretts. */
.zeitstrahl__schild::after {
content: ""; flex: 1; height: 1px;
background: linear-gradient(90deg, var(--rand), transparent);
}
.zeitstrahl__zahl {
padding: 1px 8px; border-radius: 999px;
background: rgba(255, 255, 255, .06);
font-size: .74rem; letter-spacing: normal; color: var(--text-still);
font-variant-numeric: tabular-nums;
}
/* =====================================================================
DIE WUNSCHLISTE ALS RANGFOLGE (17.09.2026)
Aus dem Plan im Vault, Stufe 3. Eine Wunschliste ist keine Liste —
sie ist eine Rangfolge mit einem Zustand. Ohne beides ist sie ein
Briefkasten ohne Postbote: Nach dem dritten unbeantworteten Wunsch
schreibt niemand mehr.
------------------------------------------------------------------- */
/* DER RANGBALKEN. Er zeigt den ABSTAND zum meistgewünschten, nicht die
absolute Zahl — die steht ohnehin auf dem Knopf daneben. Ein Wunsch
mit 12 Stimmen neben einem mit 14 sieht sonst aus wie einer mit 1
neben einem mit 40.
Drei Pixel hoch und ohne Beschriftung: Er ist ein Hinweis, kein
Diagramm. Wer die Zahl will, liest sie. */
.wunsch-rang {
height: 3px; margin: 10px 0 2px;
border-radius: 999px;
background: rgba(255, 255, 255, .05);
overflow: hidden;
}
.wunsch-rang__fuellung {
height: 100%; border-radius: inherit;
background: linear-gradient(90deg,
color-mix(in srgb, var(--akzent) 70%, transparent),
color-mix(in srgb, var(--akzent) 30%, transparent));
transition: width .3s ease;
}
/* Der meistgewünschte bekommt etwas mehr — aber nur etwas. Er ist der
erste unter Gleichen, nicht der Gewinner. */
.wunsch-rang[data-spitze="ja"] .wunsch-rang__fuellung {
background: linear-gradient(90deg, var(--akzent),
color-mix(in srgb, var(--akzent) 45%, transparent));
}
@media (prefers-reduced-motion: reduce) {
.wunsch-rang__fuellung { transition: none; }
}
/* DER ZUSTAND. Er steht im Kopf neben dem Titel, weil er das ist,
weswegen jemand wiederkommt.
„Diesmal nicht" ist bewusst NICHT rot. Ein Nein ist eine Antwort und
keine Strafe — und wer ein rotes Schild an seinem Wunsch sieht,
schreibt keinen zweiten. */
.wunsch-stand {
--w-ton: #6f89a8;
display: inline-flex; align-items: center;
padding: 2px 9px; border-radius: 999px;
font-size: .74rem; font-weight: 600; white-space: nowrap;
color: color-mix(in srgb, var(--w-ton) 72%, #ffffff);
background: color-mix(in srgb, var(--w-ton) 14%, transparent);
border: 1px solid color-mix(in srgb, var(--w-ton) 32%, transparent);
}
.wunsch-stand[data-stand="offen"] { --w-ton: #6f89a8; }
.wunsch-stand[data-stand="angenommen"] { --w-ton: #5f93c4; }
.wunsch-stand[data-stand="erledigt"] { --w-ton: #4dab77; }
.wunsch-stand[data-stand="abgelehnt"] { --w-ton: #8e8577; }
/* DIE ENTSCHEIDUNG — vier Knöpfe statt eines Umschalters. Der aktuelle
Zustand ist abgeschaltet: Ein Knopf, der nichts tut, gehört nicht
anfassbar auszusehen. */
.wunsch-wahl { display: flex; flex-wrap: wrap; gap: 6px; }
.wunsch-wahl__knopf {
font: inherit; font-size: .78rem; font-weight: 600;
padding: 6px 12px; border-radius: 999px; cursor: pointer;
color: var(--text-leise);
background: transparent;
border: 1px solid var(--rand-hell);
transition: color var(--tempo), border-color var(--tempo), background var(--tempo);
}
.wunsch-wahl__knopf:hover:not(:disabled) {
color: var(--text); border-color: var(--rand);
background: rgba(255, 255, 255, .04);
}
.wunsch-wahl__knopf[aria-pressed="true"] {
color: var(--text);
border-color: color-mix(in srgb, var(--akzent) 50%, transparent);
background: color-mix(in srgb, var(--akzent) 12%, transparent);
cursor: default;
}
/* =====================================================================
HIGHLIGHTS ALS GALERIE (17.09.2026)
Aus dem Plan im Vault, Stufe 5. „Eure Clips und Bilder" zeigte
bisher Textkarten mit einem Anhang darunter. **Ein Bild als Anhang
unter einer Überschrift ist kein Highlight** — dieser Bereich lebt
vom Sehen. Der Text wird zur Bildunterschrift, nicht umgekehrt.
------------------------------------------------------------------- */
/* Das Raster. `auto-fill` mit `minmax` statt einer festen Spaltenzahl:
Auf 390 px wird es eine Spalte, auf dem Rechner drei — und zwar
gemessen, nicht gerechnet. Eine feste Zahl wäre an einem der beiden
Enden falsch. */
#liste[data-galerie="ja"] {
display: grid; gap: 16px;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
align-items: start;
}
/* Der Bildstreifen auf einer Karte. */
.bildstreifen {
display: grid; gap: 4px; margin: -4px -4px 12px;
border-radius: var(--radius-klein); overflow: hidden;
}
/* Bei mehreren Bildern zwei Spalten — mehr wird auf einer Karte zu
klein, um noch etwas zu erkennen. */
.bildstreifen[data-mehrere="ja"] { grid-template-columns: 1fr 1fr; }
.bildstreifen__feld {
display: block; position: relative;
aspect-ratio: 16 / 9;
background: rgba(255, 255, 255, .03);
border-radius: var(--radius-klein);
overflow: hidden;
/* Ein Bild, das man anfassen kann, muss auch anspringbar sein — der
Fokusring kommt aus start.css und darf nicht abgeschnitten werden. */
outline-offset: 2px;
}
.bildstreifen__bild {
width: 100%; height: 100%;
object-fit: cover; display: block;
/* Beim Überfahren ganz leicht näher — genug, um zu sagen „das geht
auf", zu wenig, um zu zappeln. */
transition: transform var(--tempo);
}
.bildstreifen__feld:hover .bildstreifen__bild,
.bildstreifen__feld:focus-visible .bildstreifen__bild { transform: scale(1.02); }
@media (prefers-reduced-motion: reduce) {
.bildstreifen__bild { transition: none; }
.bildstreifen__feld:hover .bildstreifen__bild { transform: none; }
}
/* =====================================================================
DER STARTKATALOG (17.09.2026)
Filipe, mit drei Bildschirmfotos leerer Bretter: „ich will fertige
sachen schon drin". Im Plan stand es sogar (§5.1): „Acht leere Seiten
sind schlimmer als keine."
DER KASTEN SIEHT ANDERS AUS ALS DIE EINTRÄGE DARUNTER — und das ist
der Punkt: Was hier steht, ist noch nichts. Sähe er aus wie ein
Beitrag, würde man ihn für einen halten und sich fragen, warum er
sich nicht anfassen lässt. Deshalb: gestrichelter Rand statt
durchgezogener. Das Zeichen für „Platzhalter" ist alt und wird
sofort verstanden.
------------------------------------------------------------------- */
.startkatalog {
margin: 0 0 24px; padding: 18px 20px;
border: 1px dashed color-mix(in srgb, var(--akzent) 34%, var(--rand));
border-radius: var(--radius);
background: color-mix(in srgb, var(--akzent) 5%, transparent);
}
.startkatalog__kopf {
display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px;
margin-bottom: 14px;
}
.startkatalog__titel {
margin: 0; font-size: 1.02rem; font-weight: 650; color: var(--text);
}
.startkatalog__unter {
margin: 0; flex: 1 1 260px;
font-size: .85rem; color: var(--text-leise);
}
.startkatalog__alle { flex: 0 0 auto; }
/* Auto-fill: Auf dem Handy eine Spalte, am Rechner drei — gemessen,
nicht gerechnet. */
.startkatalog__liste {
display: grid; gap: 12px;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.startkatalog__karte {
display: flex; flex-direction: column; align-items: flex-start; gap: 7px;
padding: 13px 14px;
border: 1px solid var(--rand);
border-radius: var(--radius-klein);
background: color-mix(in srgb, var(--tinte) 92%, #ffffff 8%);
}
.startkatalog__name {
margin: 0; font-size: .95rem; font-weight: 640; color: var(--text);
}
.startkatalog__text {
margin: 0; flex: 1;
font-size: .84rem; line-height: 1.5; color: var(--text-leise);
}
/* =====================================================================
DIE KETTE (17.09.2026) — Stufe 8 des Plans
Bisher waren die acht Bretter acht Silos. Ein Wunsch wurde
angenommen, irgendwann passierte etwas im Stream, irgendwann lag ein
Clip bei den Highlights — und nichts davon wusste voneinander. Wer
den Wunsch geschrieben hatte, erfuhr nie, dass er erfüllt wurde.
ZWEI RICHTUNGEN, ZWEI TÖNE: Woher etwas kam, steht ruhig da — es ist
Herkunft, kein Ergebnis. Was daraus wurde, ist grün: Das ist die
Nachricht, auf die jemand gewartet hat.
KLEIN GEHALTEN. Die Kette erklärt den Eintrag, sie ersetzt ihn
nicht — eine Zeile, kein Kasten.
------------------------------------------------------------------- */
.kette {
--k-ton: #6f89a8;
display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
margin: 8px 0 0; padding: 6px 10px;
border-left: 2px solid color-mix(in srgb, var(--k-ton) 55%, transparent);
border-radius: 0 var(--radius-klein) var(--radius-klein) 0;
background: color-mix(in srgb, var(--k-ton) 8%, transparent);
font-size: .82rem;
}
/* „Daraus wurde" ist die gute Nachricht — sie darf als Einzige
auffallen. */
.kette--hin { --k-ton: #4dab77; }
.kette__wort {
font-weight: 650; letter-spacing: .02em;
color: color-mix(in srgb, var(--k-ton) 70%, #ffffff);
}
.kette__weg { color: var(--text); text-decoration: none; }
.kette__weg:hover { text-decoration: underline; }
.kette__wer { color: var(--text-still); }
/* =====================================================================
DAS GESPRÄCH (17.09.2026) — Stufe 6 des Plans
„Der Treff" war eine Liste aus Karten. Der einzige Bereich, in dem
Menschen MITEINANDER reden sollen, zwang sie, nebeneinander zu reden.
EINE STUFE EINGERÜCKT, NICHT MEHR. Auf 390 px ist bei der zweiten
Schluss — dann steht der Text in einer Spalte von vier Wörtern. Die
Linie links macht die Zugehörigkeit deutlicher als jeder Abstand.
------------------------------------------------------------------- */
.antworten {
margin: 12px 0 0 0; padding-left: 14px;
border-left: 2px solid color-mix(in srgb, var(--akzent) 22%, var(--rand));
}
.antwort { padding: 8px 0; }
.antwort + .antwort { border-top: 1px solid color-mix(in srgb, var(--rand) 60%, transparent); }
.antwort__kopf {
display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
margin: 0 0 3px; font-size: .78rem;
}
.antwort__wer { font-weight: 640; color: var(--text); }
/* Wer aus dem Team antwortet, ist eine andere Auskunft als wer
mitredet — deshalb sichtbar, aber leise. */
.antwort__rolle {
padding: 0 7px; border-radius: 999px;
/* .74rem und nicht .7rem: Bei 11,2 px liegt die Marke unter der
Grenze, die pruef-css-klassen im Haus haelt (11,5 px). Die Grenze
anzuheben waere der bequeme Weg gewesen -- und ab da haette die
Pruefung nichts mehr gehalten. */
font-size: .74rem; font-weight: 600;
color: color-mix(in srgb, var(--akzent) 70%, #ffffff);
background: color-mix(in srgb, var(--akzent) 13%, transparent);
}
.antwort__wann { color: var(--text-still); margin-left: auto; }
.antwort__text {
margin: 0; font-size: .88rem; line-height: 1.55; color: var(--text-leise);
overflow-wrap: anywhere;
}
.antwort__weg {
margin-top: 4px; padding: 0;
background: none; border: 0; cursor: pointer;
font: inherit; font-size: .74rem; color: var(--text-still);
text-decoration: underline;
}
.antwort__weg:hover { color: var(--text-leise); }
/* Das Feld steht immer da — ein leeres Feld ist die deutlichste
Einladung, die es gibt. */
.antwort-neu { display: flex; gap: 8px; margin-top: 10px; }
.antwort-neu__feld {
flex: 1 1 auto; min-width: 0;
font: inherit; font-size: .88rem;
}
.antwort-neu__ab {
flex: 0 0 auto;
font: inherit; font-size: .82rem; font-weight: 600;
padding: 0 14px; border-radius: 999px; cursor: pointer;
color: var(--text-leise);
background: transparent;
border: 1px solid var(--rand-hell);
transition: color var(--tempo), border-color var(--tempo), background var(--tempo);
}
.antwort-neu__ab:hover:not(:disabled) {
color: var(--text); background: rgba(255, 255, 255, .05);
}
/* =====================================================================
STUFE 7: JEDES BRETT BEKOMMT SEINE FORM (17.09.2026)
„Regeln & Hilfe" ist ein Nachschlagewerk, kein Feed — man schlägt es
im Streitfall auf und will **finden**, nicht scrollen. „Mitmachen"
ist ein Weg. „Anschlagbrett" ist ein schwarzes Brett: wenige, große
Aushänge.
------------------------------------------------------------------- */
/* Die Sprungmarken — der Unterschied zwischen einem Dokument und einer
langen Seite. */
.brettmarken {
display: flex; flex-wrap: wrap; gap: 6px;
margin: 0 0 18px; padding-bottom: 14px;
border-bottom: 1px solid var(--rand);
}
.brettmarken__weg {
padding: 5px 12px; border-radius: 999px;
font-size: .8rem; font-weight: 600; text-decoration: none;
color: var(--text-leise);
border: 1px solid var(--rand-hell);
transition: color var(--tempo), border-color var(--tempo), background var(--tempo);
}
.brettmarken__weg:hover {
color: var(--text); background: rgba(255, 255, 255, .04);
}
/* Die Abschnittsüberschrift. scroll-margin, damit die Überschrift beim
Anspringen nicht unter der Kopfleiste verschwindet — ohne das landet
man auf dem Text darunter und glaubt, der Sprung sei ins Leere
gegangen. */
.brettabschnitt {
display: flex; align-items: baseline; gap: 10px;
margin: 30px 0 12px; scroll-margin-top: 80px;
font-size: .82rem; font-weight: 650;
letter-spacing: .09em; text-transform: uppercase;
color: var(--text-still);
}
.brettabschnitt:first-child { margin-top: 4px; }
.brettabschnitt::after {
content: ""; flex: 1; height: 1px;
background: linear-gradient(90deg, var(--rand), transparent);
}
.brettabschnitt__zahl {
order: 3; padding: 1px 8px; border-radius: 999px;
background: rgba(255, 255, 255, .06);
font-size: .74rem; letter-spacing: normal; color: var(--text-still);
font-variant-numeric: tabular-nums;
}
/* ---------------------------------------------------------------------
DAS ANSCHLAGBRETT — wenige, große Aushänge
Ein Aushang zwischen dreißig anderen ist kein Aushang. Größerer
Titel, mehr Luft, ein Rahmen, der nach Papier aussieht statt nach
Zeile.
------------------------------------------------------------------- */
#liste[data-aushang="ja"] { display: grid; gap: 18px; }
#liste[data-aushang="ja"] .eintrag-karte { padding: 22px 24px; }
#liste[data-aushang="ja"] .eintrag-titel {
font-size: 1.32rem; line-height: 1.25;
}
#liste[data-aushang="ja"] .eintrag-text {
font-size: .98rem; line-height: 1.6;
}
@media (max-width: 560px) {
#liste[data-aushang="ja"] .eintrag-karte { padding: 17px 16px; }
#liste[data-aushang="ja"] .eintrag-titel { font-size: 1.12rem; }
}
/* =====================================================================
EIN VIDEO EINLESEN (17.09.2026) — Stufe A des Video-Plans
------------------------------------------------------------------- */
.videoholen {
margin: 0 0 20px; padding: 16px 18px;
border: 1px solid var(--rand);
border-radius: var(--radius);
background: var(--flaeche);
}
.videoholen__form { margin: 0; }
.videoholen__zeile { display: flex; gap: 10px; }
.videoholen__zeile input {
flex: 1 1 auto; min-width: 0;
font: inherit; font-size: .9rem;
}
.videoholen__zeile .knopf { flex: 0 0 auto; }
/* Der Knopf zum Video. Er ist die Antwort auf „und dann liken": Er
führt dorthin, wo das Liken zählt. Deshalb steht er deutlich da und
nicht als kleiner Textlink unter dem Datum. */
.videozeile {
display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px;
margin-top: 12px;
}
.videozeile__kanal {
--v-ton: #6f89a8;
padding: 2px 10px; border-radius: 999px;
font-size: .74rem; font-weight: 650; letter-spacing: .02em;
white-space: nowrap;
color: color-mix(in srgb, var(--v-ton) 76%, #ffffff);
background: color-mix(in srgb, var(--v-ton) 13%, transparent);
border: 1px solid color-mix(in srgb, var(--v-ton) 32%, transparent);
}
/* Dieselben drei Töne wie am Kanal einer Aufgabe — ein Kanal sieht im
ganzen Haus gleich aus, sonst lernt man sie zweimal. */
.videozeile__kanal[data-kanal="dogfather"] { --v-ton: #c2544f; }
.videozeile__kanal[data-kanal="hasidog"] { --v-ton: #7d6bbd; }
.videozeile__kanal[data-kanal="clips"] { --v-ton: #3f9c8a; }
.videozeile__weg { flex: 0 0 auto; text-decoration: none; }