Filipes Notiz nennt acht: "Host-Steuerung fuer Kamera, Mikrofon,
Video, Gaeste, Lautstaerke, Chat, Layout und Start/Ende."
Nachgezaehlt war sechsmal etwas da und zweimal nichts.
KAMERA
Es gab keinen Weg, das eigene Bild abzuschalten. Wer kurz aufstehen,
trinken oder etwas holen wollte, musste die Sendung verlassen oder
sich dabei filmen lassen.
Jetzt liegt eine SENDERLEISTE ueber dem Bild -- Kamera, Mikro und ein
Pegel. Sie gehoert jedem, der sendet, Host wie Gast: Ein Gast, der
sein eigenes Bild nicht abschalten kann, muesste den Host darum
bitten, und das ist keine Bedienung, sondern eine Bitte.
DAS BILD WIRD AM GERAET ABGESCHALTET (`track.enabled = false`), nicht
am Server: Die Verbindung bleibt stehen, der Ton laeuft weiter, und
beim Wiedereinschalten ist das Bild sofort da. Der Server erfaehrt es
nur, damit bei den ANDEREN "Kamera aus" im Fenster steht. Ohne diese
Beschriftung sind ein abgeschaltetes und ein kaputtes Bild dasselbe
schwarze Rechteck -- und dann fragt jemand im Chat, ob die Technik
hakt.
Erst das Geraet, dann die Ansage. Andersherum stuende bei allen
"Kamera aus", waehrend noch ein Bild fliesst; man glaubte sich
unsichtbar. Geht die Ansage nicht durch, wird das Geraet
zurueckgesetzt -- ein Knopf, der halb wirkt, ist schlimmer als einer,
der gar nicht wirkt.
Das Mikro laeuft denselben Weg. Erst wollte ich es rein oertlich
lassen; das waere dieselbe stille Falle gewesen: Wer sich selbst
stummschaltet und trotzdem redet, saehe bei allen anderen ein ganz
normales Fenster.
CHAT
Es gab Moderation -- Beitraege wegnehmen -- aber keine Steuerung des
Chats selbst. Einen Beitrag zu loeschen, nachdem er stand, ist etwas
anderes, als ihn gar nicht erst zuzulassen.
Drei Stufen: OFFEN, TEAM (wer moderiert, darf -- wer aufraeumen soll,
muss dabei reden koennen) und ZU (nur die zwei, die fuehren). Zwei
Stufen waeren zu wenig: "zu" ist in einer Sendung fast immer zu viel,
dann sitzen alle vor einem stummen Fenster. Die mittlere ist die, die
man wirklich braucht.
Die Schalter stehen im Kopf der Chatschiene, nicht im Regiepult: Man
moderiert, wo man liest. Ein Umweg ueber ein Register waere in dem
Moment, in dem es laut wird, genau ein Umweg zu viel.
EIN GESPERRTES FELD SAGT, WARUM. "Gerade schreibt nur das Team" statt
eines Feldes, das sich nicht beschreiben laesst und schweigt --
sonst schreibt jemand in den Hauschat, dass die Reaction hakt. Und
die Stufe gilt AM SERVER: Ein ausgegrautes Feld haelt niemanden auf,
der die Schnittstelle kennt. Beide Antworten kommen aus derselben
Funktion; zwei Rechnungen waeren zwei Gelegenheiten, dass ein Feld da
ist und mit 403 antwortet.
EIN FUND NEBENBEI: "MEIN MIKRO" WAR EIN PLACEBO
Gemessen: `staende.mikro` wird nirgends gelesen. Der Schieber liess
sich bewegen, die Zahl daneben aenderte sich -- und es passierte
nichts. Das ist schlimmer als ein fehlender Regler: Man glaubt, man
haette leiser gestellt.
Technisch ist das auch richtig. Die eigene Lautstaerke laesst sich
nicht am Regler aendern; man muesste den Ton umrechnen und die Spur
in jeder Verbindung austauschen. Was man beim eigenen Mikro braucht,
ist AN oder AUS -- und ein Pegel, der zeigt, dass es ankommt. Genau
das steht jetzt dort, als vierte Spalte im Pult, mit demselben
Zustand wie die Senderleiste. Die drei anderen Regler bleiben Regler:
Sie steuern, was ICH hoere, und das geht am Empfaenger.
UND EINER IN MEINER EIGENEN ARBEIT
`kasten.append(el("div","pegel")).append(el("i"))` -- `Node.append()`
gibt `undefined` zurueck, nicht das angehaengte Element. Ein
TypeError beim Aufbau des Pults, den `node --check` nicht sieht.
Beim Verkuerzen nicht nachgesehen, was die Methode zurueckgibt.
Dazu: Die Pegel-Takte liefen in `pultAufbauen()`. Das Pult hat nur,
wer die Sendung fuehrt -- ein Gast haette seinen Pegel nie gesehen,
und genau er braucht ihn am dringendsten.
GEMESSEN
mess-reaktion Der Host schaltet ab, und bei der Zuschauerin steht
"Kamera aus" bei DogFather, Bild verdeckt.
Stufe "Team": Feld gesperrt mit Grund, und der
Server lehnt denselben Versuch mit 403 ab.
pruef-reaktion 154 Punkte, 0 Fehler (vorher 132), neuer Abschnitt
13 mit 22 Punkten und Gegenprobe (es geht auch
wieder auf -- eine Sperre, die man nicht loesen
kann, ist keine Stufe, sondern ein Ende)
dazu gruen handy 180, css-klassen 33, struktur 35,
tippziele 11, aufbewahrung 45, meldungen 8
Der neue Abschnitt baut sich seine Buehne selbst. Abschnitt 9 beendet
die Sendung; sich auf den Stand eines frueheren Abschnitts zu
verlassen ist die Kopplung, die spaeter jemand aus Versehen
zerreisst.
SCHEMA: drei Spalten (reaktion_dabei.kamera_aus, .mikro_aus,
reaktion.chat_modus), alle per ALTER TABLE. Auf einer Kopie der
echten Datenbank durchgespielt: 20 Personen, keine Tabelle verliert
eine Spalte.
1347 lines
46 KiB
CSS
1347 lines
46 KiB
CSS
/* =====================================================================
|
|
DIE REACTION (28.09.2026)
|
|
|
|
Diese Seite ist absichtlich anders gebaut als jede andere im Haus.
|
|
Überall sonst gilt: Kacheln, Karten, Listen -- man liest etwas,
|
|
entscheidet und geht wieder. Hier sitzt man. Eine Stunde lang, mit
|
|
anderen zusammen, und schaut auf EINE Sache.
|
|
|
|
Daraus folgen drei Entscheidungen, die sonst nirgends gelten:
|
|
|
|
1. DIE SEITE SCROLLT NICHT. Sie füllt genau den Bildschirm. Ein
|
|
Video, das beim Tippen im Chat nach oben rutscht, ist der
|
|
schnellste Weg, dass jemand aufhört zu schreiben.
|
|
|
|
2. DIE FLÄCHE IST DUNKLER ALS ÜBERALL SONST. Der Rest des Hauses
|
|
steht auf #07060f mit Licht in den Ecken; hier ist es fast
|
|
schwarz. Nicht als Stil, sondern weil daneben ein Video läuft:
|
|
Alles, was selbst leuchtet, zieht den Blick vom Bild weg.
|
|
|
|
3. DIE FARBE IST ROT -- und zwar nur hier und nur beim Senden.
|
|
Das Haus ist augenschonend gebaut, und Rot ist das Gegenteil
|
|
davon. Es ist aber kein Dauerzustand: ein bis zwei Stunden im
|
|
Monat, und in dieser Zeit SOLL es rufen. Gedeckt (#d8404a statt
|
|
reinem Rot), und was pulst, pulst in vier Sekunden -- das ist
|
|
Atmen und kein Blinken.
|
|
|
|
---------------------------------------------------------------------
|
|
DREI HÄUTE, EINE SEITE
|
|
|
|
`data-stand` am `.saal` schaltet um: zu / vorbereitung / live.
|
|
Alle drei stehen im Dokument. Beim Wechsel von „gleich" auf „live"
|
|
wird deshalb nichts neu geladen -- weder der Chat, in dem jemand
|
|
mitten im Satz ist, noch die Verbindung zur Kamera.
|
|
===================================================================== */
|
|
|
|
.reaktion-seite {
|
|
--saal: #050408;
|
|
--saal-hoch: #0b0a12;
|
|
--rand: rgba(150, 160, 190, .14);
|
|
--rand-hell: rgba(170, 180, 210, .26);
|
|
--schrift: #e9e6f2;
|
|
--schrift-leise: #a9a3bd;
|
|
--an: #d8404a;
|
|
--an-hell: #ff8b92;
|
|
--gleich: #e0a13a;
|
|
--zu: #8b93a4;
|
|
|
|
background: var(--saal);
|
|
/* Kein Scrollen: Der Saal ist so hoch wie das Fenster. `dvh` und
|
|
nicht `vh` -- auf dem Handy wandert die Adressleiste, und `vh`
|
|
rechnet mit dem Zustand von vorhin. */
|
|
min-height: 100dvh;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.saal {
|
|
position: relative;
|
|
display: grid;
|
|
/* Die Kopfleiste ist 69 px hoch (gemessen, nicht geschätzt -- siehe
|
|
pruef-handy, das sie über alle Breiten abmisst). */
|
|
height: calc(100dvh - 69px);
|
|
padding: 0;
|
|
max-width: none;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
DAS SCHILD
|
|
|
|
Oben mittig, in allen drei Zuständen. Es beantwortet die einzige
|
|
Frage, die jeder beim Öffnen hat: läuft schon was?
|
|
--------------------------------------------------------------------- */
|
|
.buehne-schild {
|
|
position: absolute;
|
|
top: 14px; left: 50%;
|
|
transform: translateX(-50%);
|
|
z-index: 40;
|
|
display: flex; align-items: center; gap: 9px;
|
|
padding: 7px 15px 8px;
|
|
border-radius: 999px;
|
|
background: rgba(8, 7, 14, .82);
|
|
border: 1px solid var(--rand);
|
|
backdrop-filter: blur(14px) saturate(1.2);
|
|
-webkit-backdrop-filter: blur(14px) saturate(1.2);
|
|
box-shadow: 0 16px 38px -18px #000;
|
|
font-size: .72rem; font-weight: 800;
|
|
letter-spacing: .14em; text-transform: uppercase;
|
|
color: var(--schrift-leise);
|
|
}
|
|
.buehne-schild__punkt {
|
|
width: 8px; height: 8px; border-radius: 50%;
|
|
background: var(--zu);
|
|
flex: none;
|
|
}
|
|
.buehne-schild__zahl {
|
|
padding-left: 9px;
|
|
border-left: 1px solid var(--rand);
|
|
color: var(--schrift);
|
|
letter-spacing: .06em;
|
|
}
|
|
|
|
.saal[data-stand="vorbereitung"] .buehne-schild {
|
|
border-color: color-mix(in srgb, var(--gleich) 40%, transparent);
|
|
color: color-mix(in srgb, var(--gleich) 30%, #ffffff);
|
|
}
|
|
.saal[data-stand="vorbereitung"] .buehne-schild__punkt { background: var(--gleich); }
|
|
|
|
.saal[data-stand="live"] .buehne-schild {
|
|
border-color: color-mix(in srgb, var(--an-hell) 50%, transparent);
|
|
color: #ffe9ea;
|
|
box-shadow: 0 0 30px -10px var(--an), 0 16px 38px -18px #000;
|
|
}
|
|
.saal[data-stand="live"] .buehne-schild__punkt {
|
|
background: var(--an);
|
|
box-shadow: 0 0 12px 1px var(--an);
|
|
animation: reakt-atem 4s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes reakt-atem {
|
|
0%, 100% { opacity: 1; transform: scale(1); }
|
|
50% { opacity: .5; transform: scale(.82); }
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
HÄUTE EIN- UND AUSBLENDEN
|
|
--------------------------------------------------------------------- */
|
|
#teil-zu, #teil-warte, #teil-live { display: none; }
|
|
.saal[data-stand="zu"] #teil-zu { display: grid; }
|
|
.saal[data-stand="vorbereitung"] #teil-warte { display: grid; }
|
|
.saal[data-stand="live"] #teil-live { display: grid; }
|
|
|
|
/* =====================================================================
|
|
ZU — der Vorhang
|
|
===================================================================== */
|
|
.vorhang {
|
|
position: relative;
|
|
place-items: center;
|
|
padding: 0 28px;
|
|
text-align: center;
|
|
}
|
|
.vorhang__licht {
|
|
position: absolute; inset: 0;
|
|
background:
|
|
radial-gradient(90% 55% at 50% 0%, rgba(120, 130, 165, .12), transparent 62%),
|
|
radial-gradient(120% 70% at 50% 104%, rgba(70, 80, 115, .10), transparent 60%);
|
|
pointer-events: none;
|
|
}
|
|
.vorhang__innen { position: relative; max-width: 30rem; }
|
|
.vorhang__marke {
|
|
display: flex; align-items: center; justify-content: center; gap: 10px;
|
|
font-size: .74rem; font-weight: 700;
|
|
letter-spacing: .38em; text-transform: uppercase;
|
|
color: var(--schrift-leise);
|
|
}
|
|
.vorhang__marke i {
|
|
display: block; width: 26px; height: 1px;
|
|
background: linear-gradient(90deg, transparent, var(--schrift-leise));
|
|
}
|
|
.vorhang__marke i + i { background: linear-gradient(90deg, var(--schrift-leise), transparent); }
|
|
|
|
.vorhang__titel {
|
|
margin: 16px 0 0;
|
|
font-size: clamp(1.9rem, 7vw, 2.7rem);
|
|
font-weight: 800; line-height: 1.08;
|
|
letter-spacing: -.024em;
|
|
color: var(--schrift);
|
|
text-wrap: balance;
|
|
}
|
|
.vorhang__satz {
|
|
margin: 14px 0 0;
|
|
font-size: .96rem; line-height: 1.6;
|
|
color: var(--schrift-leise);
|
|
text-wrap: pretty;
|
|
}
|
|
.vorhang__naechste {
|
|
margin: 22px 0 0;
|
|
display: inline-block;
|
|
padding: 9px 16px;
|
|
border-radius: 12px;
|
|
background: color-mix(in srgb, var(--gleich) 12%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--gleich) 30%, transparent);
|
|
color: color-mix(in srgb, var(--gleich) 24%, #ffffff);
|
|
font-size: .86rem; font-weight: 700;
|
|
}
|
|
|
|
/* =====================================================================
|
|
VORBEREITUNG — der Wartebereich
|
|
===================================================================== */
|
|
.warte { place-items: center; padding: 0 20px; }
|
|
.warte__buehne {
|
|
display: grid; gap: 26px;
|
|
width: min(54rem, 100%);
|
|
grid-template-columns: 1fr;
|
|
text-align: center;
|
|
}
|
|
.warte__bild {
|
|
aspect-ratio: 16 / 9;
|
|
border-radius: 20px;
|
|
background: linear-gradient(160deg, #131120, #08070e);
|
|
border: 1px solid var(--rand);
|
|
background-size: cover; background-position: center;
|
|
box-shadow: 0 40px 80px -46px #000;
|
|
}
|
|
.warte__kicker {
|
|
font-size: .74rem; font-weight: 800;
|
|
letter-spacing: .34em; text-transform: uppercase;
|
|
color: color-mix(in srgb, var(--gleich) 26%, #ffffff);
|
|
}
|
|
.warte__titel {
|
|
margin: 12px 0 0;
|
|
font-size: clamp(1.6rem, 6vw, 2.3rem);
|
|
font-weight: 800; line-height: 1.1;
|
|
letter-spacing: -.022em; color: var(--schrift);
|
|
text-wrap: balance;
|
|
}
|
|
.warte__satz { margin: 14px 0 0; color: var(--schrift-leise); font-size: .92rem; }
|
|
/* Was nach dem ersten Stück kommt. Eine Zeile, kein Programmheft --
|
|
der Abend soll nicht vorher im Netz stehen. */
|
|
.warte__danach {
|
|
margin: 12px 0 0;
|
|
display: inline-block;
|
|
padding: 6px 13px;
|
|
border-radius: 999px;
|
|
background: rgba(255, 255, 255, .05);
|
|
border: 1px solid var(--rand);
|
|
color: var(--schrift-leise);
|
|
font-size: .78rem;
|
|
max-width: 100%;
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
}
|
|
|
|
.countdown {
|
|
display: inline-flex; align-items: baseline; gap: 10px;
|
|
margin: 18px 0 0; padding: 10px 20px 12px;
|
|
border-radius: 16px;
|
|
background: color-mix(in srgb, var(--gleich) 10%, rgba(8, 7, 14, .7));
|
|
border: 1px solid color-mix(in srgb, var(--gleich) 32%, transparent);
|
|
}
|
|
.countdown__zahl {
|
|
font-size: 2rem; font-weight: 800;
|
|
letter-spacing: -.03em;
|
|
color: color-mix(in srgb, var(--gleich) 22%, #ffffff);
|
|
/* Tabellenziffern: Ohne sie springt die ganze Zeile bei jedem
|
|
Sekundenwechsel, weil die 1 schmaler ist als die 8. */
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.countdown__wort { font-size: .78rem; color: var(--schrift-leise); letter-spacing: .04em; }
|
|
|
|
/* =====================================================================
|
|
LIVE — der Kinosaal
|
|
===================================================================== */
|
|
.kino {
|
|
grid-template-columns: 1fr minmax(19rem, 23rem);
|
|
gap: 0;
|
|
height: 100%;
|
|
min-height: 0; /* sonst wächst das Raster über das Fenster */
|
|
}
|
|
|
|
.leinwand {
|
|
position: relative;
|
|
min-width: 0; min-height: 0;
|
|
display: grid; place-items: center;
|
|
background: #000;
|
|
overflow: hidden;
|
|
}
|
|
.leinwand__video { position: relative; width: 100%; height: 100%; }
|
|
.leinwand__video iframe {
|
|
position: absolute; inset: 0;
|
|
width: 100%; height: 100%;
|
|
border: 0;
|
|
}
|
|
.leinwand__warte {
|
|
position: absolute; inset: 0;
|
|
display: grid; place-items: center;
|
|
color: var(--schrift-leise); font-size: .9rem;
|
|
}
|
|
|
|
/* ---- Die Kamerafenster ----------------------------------------------
|
|
Sie liegen ÜBER dem Video. Genau so sieht eine Reaction aus: das
|
|
Bild groß, das Gesicht klein davor.
|
|
|
|
`pointer-events: none` am Behälter und `auto` an den Fenstern: Der
|
|
Bereich dazwischen gehört dem Video (Pause, Lautstärke), die
|
|
Fenster selbst nehmen Klicks an. Ohne das läge eine unsichtbare
|
|
Scheibe über der ganzen Leinwand.
|
|
--------------------------------------------------------------------- */
|
|
.kameras {
|
|
position: absolute;
|
|
right: 16px; bottom: 16px;
|
|
display: flex; flex-direction: column; gap: 12px;
|
|
pointer-events: none;
|
|
z-index: 20;
|
|
}
|
|
.kamera {
|
|
position: relative;
|
|
width: clamp(120px, 17vw, 208px);
|
|
aspect-ratio: 4 / 3;
|
|
border-radius: 16px;
|
|
overflow: hidden;
|
|
background: #0b0a12;
|
|
border: 1px solid var(--rand-hell);
|
|
box-shadow: 0 24px 50px -22px #000;
|
|
pointer-events: auto;
|
|
}
|
|
.kamera video {
|
|
width: 100%; height: 100%;
|
|
object-fit: cover;
|
|
display: block;
|
|
background: #0b0a12;
|
|
}
|
|
.kamera__name {
|
|
position: absolute; left: 8px; bottom: 8px;
|
|
padding: 3px 9px 4px;
|
|
border-radius: 999px;
|
|
font-size: .72rem; font-weight: 700;
|
|
background: rgba(6, 5, 11, .76);
|
|
border: 1px solid var(--rand);
|
|
color: var(--schrift);
|
|
backdrop-filter: blur(6px);
|
|
max-width: calc(100% - 16px);
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
}
|
|
.kamera[data-host="ja"] { border-color: color-mix(in srgb, var(--an-hell) 46%, transparent); }
|
|
.kamera[data-stumm="ja"]::after {
|
|
content: "stumm";
|
|
position: absolute; right: 8px; top: 8px;
|
|
padding: 3px 8px 4px; border-radius: 999px;
|
|
font-size: .72rem; font-weight: 800; letter-spacing: .08em;
|
|
background: rgba(216, 64, 74, .82); color: #fff;
|
|
}
|
|
.kamera--leer {
|
|
display: grid; place-items: center;
|
|
font-size: .72rem; color: var(--schrift-leise);
|
|
border-style: dashed;
|
|
}
|
|
|
|
/* Anordnung „gleich": Video und Kameras nebeneinander statt übereinander. */
|
|
.kino[data-layout="gleich"] .kameras {
|
|
position: static;
|
|
flex-direction: row;
|
|
justify-content: center;
|
|
padding: 10px;
|
|
background: #07060d;
|
|
}
|
|
.kino[data-layout="gleich"] .leinwand {
|
|
grid-template-rows: 1fr auto;
|
|
align-content: stretch;
|
|
}
|
|
/* Anordnung „kamera": die Kameras groß, das Video klein in der Ecke. */
|
|
.kino[data-layout="kamera"] .kamera { width: clamp(160px, 30vw, 380px); }
|
|
.kino[data-layout="kamera"] .kameras {
|
|
right: auto; left: 50%; top: 50%; bottom: auto;
|
|
transform: translate(-50%, -50%);
|
|
flex-direction: row;
|
|
}
|
|
.kino[data-layout="kamera"] .leinwand__video {
|
|
position: absolute; right: 14px; bottom: 14px;
|
|
width: clamp(140px, 22vw, 260px); height: auto; aspect-ratio: 16/9;
|
|
border-radius: 14px; overflow: hidden;
|
|
border: 1px solid var(--rand-hell);
|
|
z-index: 25;
|
|
}
|
|
|
|
/* ---- Die Chatschiene ------------------------------------------------- */
|
|
.schiene {
|
|
display: grid;
|
|
grid-template-rows: auto 1fr auto auto;
|
|
min-height: 0;
|
|
background: #07060d;
|
|
border-left: 1px solid var(--rand);
|
|
}
|
|
.schiene__kopf {
|
|
display: flex; align-items: center; gap: 10px;
|
|
padding: 14px 16px 12px;
|
|
border-bottom: 1px solid var(--rand);
|
|
}
|
|
.schiene__titel {
|
|
margin: 0; font-size: .74rem; font-weight: 800;
|
|
letter-spacing: .16em; text-transform: uppercase;
|
|
color: var(--schrift-leise);
|
|
}
|
|
.schiene__zahl {
|
|
margin-left: auto;
|
|
font-size: .72rem; font-weight: 700;
|
|
padding: 2px 9px 3px; border-radius: 999px;
|
|
background: rgba(255, 255, 255, .06);
|
|
border: 1px solid var(--rand);
|
|
color: var(--schrift-leise);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.schiene__zu { display: none; }
|
|
|
|
.schiene__liste {
|
|
margin: 0; padding: 12px 14px;
|
|
list-style: none;
|
|
overflow-y: auto;
|
|
min-height: 0;
|
|
display: flex; flex-direction: column; gap: 9px;
|
|
scrollbar-width: thin;
|
|
}
|
|
.beitrag {
|
|
display: grid; gap: 2px;
|
|
padding: 8px 11px 9px;
|
|
border-radius: 12px;
|
|
background: rgba(255, 255, 255, .035);
|
|
border: 1px solid transparent;
|
|
font-size: .86rem; line-height: 1.42;
|
|
color: var(--schrift);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
.beitrag__wer {
|
|
font-size: .72rem; font-weight: 800;
|
|
letter-spacing: .02em;
|
|
color: var(--schrift-leise);
|
|
display: flex; align-items: center; gap: 7px;
|
|
}
|
|
.beitrag__weg {
|
|
margin-left: auto;
|
|
appearance: none; border: 0; background: none;
|
|
color: var(--schrift-leise);
|
|
cursor: pointer; padding: 2px 4px; border-radius: 6px;
|
|
font-size: .72rem;
|
|
}
|
|
.beitrag__weg:hover { color: var(--an-hell); background: rgba(216, 64, 74, .12); }
|
|
.beitrag[data-host="ja"] {
|
|
background: color-mix(in srgb, var(--an) 12%, transparent);
|
|
border-color: color-mix(in srgb, var(--an) 30%, transparent);
|
|
}
|
|
.beitrag[data-host="ja"] .beitrag__wer { color: var(--an-hell); }
|
|
.beitrag[data-team="ja"] .beitrag__wer { color: #9ab7ff; }
|
|
|
|
.schiene__form {
|
|
display: flex; gap: 8px;
|
|
padding: 12px 14px;
|
|
border-top: 1px solid var(--rand);
|
|
}
|
|
.schiene__feld {
|
|
flex: 1 1 auto; min-width: 0;
|
|
appearance: none;
|
|
padding: 11px 13px;
|
|
border-radius: 12px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .04);
|
|
color: var(--schrift);
|
|
font: inherit; font-size: .9rem;
|
|
}
|
|
.schiene__feld:focus-visible {
|
|
outline: none;
|
|
border-color: var(--rand-hell);
|
|
box-shadow: 0 0 0 3px rgba(154, 183, 255, .16);
|
|
}
|
|
.schiene__senden {
|
|
flex: none;
|
|
width: 44px; height: 44px;
|
|
display: grid; place-items: center;
|
|
border-radius: 12px;
|
|
border: 1px solid color-mix(in srgb, var(--an) 42%, transparent);
|
|
background: color-mix(in srgb, var(--an) 24%, transparent);
|
|
color: #ffd9db; cursor: pointer;
|
|
}
|
|
.schiene__senden svg { width: 19px; height: 19px; fill: currentColor; }
|
|
|
|
.danke {
|
|
display: flex; align-items: center; justify-content: center; gap: 9px;
|
|
margin: 0 14px 14px;
|
|
padding: 12px 14px;
|
|
min-height: 44px;
|
|
border-radius: 12px;
|
|
text-decoration: none;
|
|
font-size: .86rem; font-weight: 700;
|
|
color: #0a2a1c;
|
|
background: linear-gradient(180deg, #7de2a8, #47c97f);
|
|
box-shadow: 0 14px 30px -16px #47c97f;
|
|
}
|
|
.danke svg { width: 18px; height: 18px; fill: currentColor; flex: none; }
|
|
|
|
|
|
/* =====================================================================
|
|
DIE REGIE
|
|
|
|
Sie ist nach dem Vorbild eines echten Regieplatzes gebaut und
|
|
nicht nach dem eines Formulars. Drei Dinge machen den Unterschied:
|
|
|
|
1. EINE LEISTE, DIE IMMER STEHT. Lampe, Laufzeit, Zahlen und die
|
|
drei grossen Knoepfe liegen ausserhalb des einklappbaren
|
|
Teils. Wer mitten in der Sendung „Beenden" drueckt, drueckt es,
|
|
weil etwas passiert ist -- das darf nicht hinter einer
|
|
Bewegung liegen.
|
|
|
|
2. REGISTER STATT STAPEL. Vorher lagen fuenf Kaesten untereinander
|
|
in einem Bereich, der hoechstens die halbe Bildschirmhoehe hat.
|
|
Man sah fuenf halbe Dinge. Jetzt eines ganz.
|
|
|
|
3. RUHIGE FLAECHEN. Ein Regieplatz, der selbst leuchtet, kaempft
|
|
mit dem Bild um die Aufmerksamkeit. Farbe gibt es nur dort, wo
|
|
sie etwas SAGT: rot heisst auf Sendung, bernstein heisst
|
|
gleich, alles andere ist grau.
|
|
===================================================================== */
|
|
/* ==== DAS PULT SCHIEBT, ES DECKT NICHT ZU =========================
|
|
(28.09.2026, gefunden im ersten Bild.)
|
|
|
|
Erst lag es als `position: fixed` ueber der Seite. Aufgeklappt
|
|
verdeckte es die untere Haelfte: Das Video war abgeschnitten, der
|
|
Chat auch -- ausgerechnet fuer den, der sendet und beides im Blick
|
|
haben muss.
|
|
|
|
Jetzt ist es die zweite Zeile des Saals. Der Saal ist ein Raster
|
|
mit `1fr auto`; klappt das Pult auf, wird der Kinosaal darueber
|
|
von selbst kleiner. Nichts wird verdeckt, und niemand muss eine
|
|
Hoehe ausrechnen, die spaeter nicht mehr stimmt. */
|
|
/* 197 PIXEL ZUM SCROLLEN -- gemessen am 28.09.2026, sobald die Regie
|
|
aufgeklappt war.
|
|
|
|
`1fr` heisst nicht „nimm, was uebrig ist", sondern
|
|
`minmax(auto, 1fr)`: Die Zeile darf nie kleiner werden als ihr
|
|
Inhalt. Der Kinosaal hat aber einen Mindestinhalt, und mit
|
|
aufgeklapptem Pult passte beides nicht mehr in die Hoehe -- also
|
|
wuchs die Seite nach unten. Wer sendet, scrollte dann mitten in
|
|
der Sendung, um an das Bild oder an die Knoepfe zu kommen.
|
|
|
|
`minmax(0, 1fr)` erlaubt der Zeile zu schrumpfen. Der Kinosaal
|
|
wird kleiner, der Chat rollt in sich -- was er ohnehin tut. */
|
|
.saal { grid-template-rows: minmax(0, 1fr) auto; }
|
|
|
|
.pult {
|
|
z-index: 60;
|
|
background:
|
|
linear-gradient(180deg, rgba(255, 255, 255, .045), transparent 90px),
|
|
rgba(7, 6, 13, .95);
|
|
backdrop-filter: blur(18px) saturate(1.2);
|
|
-webkit-backdrop-filter: blur(18px) saturate(1.2);
|
|
border-top: 1px solid var(--rand-hell);
|
|
box-shadow: 0 -30px 70px -40px #000;
|
|
}
|
|
|
|
/* ---- Die Leiste, die immer steht ------------------------------------- */
|
|
.pult__leiste {
|
|
display: flex; align-items: center; flex-wrap: wrap;
|
|
gap: 10px 16px;
|
|
padding: 11px 16px;
|
|
border-bottom: 1px solid var(--rand);
|
|
}
|
|
|
|
/* Die Lampe. In jedem Studio haengt sie ueber der Tuer, und sie ist
|
|
dort das Erste, was man sieht -- deshalb steht sie hier ganz
|
|
links und ist das Einzige, was Farbe traegt. */
|
|
.lampe {
|
|
display: inline-flex; align-items: center; gap: 9px;
|
|
padding: 7px 14px 7px 12px;
|
|
border-radius: 999px;
|
|
border: 1px solid var(--rand-hell);
|
|
background: rgba(255, 255, 255, .04);
|
|
font-size: .74rem; font-weight: 800;
|
|
letter-spacing: .14em; text-transform: uppercase;
|
|
color: var(--zu);
|
|
white-space: nowrap;
|
|
}
|
|
.lampe__punkt {
|
|
width: 9px; height: 9px; border-radius: 50%;
|
|
background: currentColor;
|
|
flex: none;
|
|
}
|
|
.pult[data-stand="vorbereitung"] .lampe {
|
|
color: color-mix(in srgb, var(--gleich) 26%, #ffffff);
|
|
border-color: color-mix(in srgb, var(--gleich) 44%, transparent);
|
|
background: color-mix(in srgb, var(--gleich) 10%, transparent);
|
|
}
|
|
.pult[data-stand="live"] .lampe {
|
|
color: #ffe2e4;
|
|
border-color: color-mix(in srgb, var(--an) 62%, transparent);
|
|
background: color-mix(in srgb, var(--an) 22%, transparent);
|
|
box-shadow: 0 0 26px -12px var(--an);
|
|
}
|
|
.pult[data-stand="live"] .lampe__punkt {
|
|
background: var(--an-hell);
|
|
box-shadow: 0 0 10px 1px var(--an);
|
|
animation: lampe-puls 4s ease-in-out infinite;
|
|
}
|
|
/* Vier Sekunden, und nur zwischen zwei nahen Werten. Ein schnelles
|
|
Blinken waere auf einem dunklen Bild ein Stroboskop. */
|
|
@keyframes lampe-puls {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: .45; }
|
|
}
|
|
|
|
/* Die Laufzeit. Der Grund, warum in Regieraeumen ueberall Uhren
|
|
haengen: Ohne sie verschaetzt man sich um Viertelstunden. */
|
|
.laufzeit { display: flex; align-items: baseline; gap: 7px; }
|
|
.laufzeit__zahl {
|
|
/* Tabellenziffern -- sonst wackelt die Zeile bei jeder Sekunde. */
|
|
font-variant-numeric: tabular-nums;
|
|
font-size: 1.06rem; font-weight: 800;
|
|
letter-spacing: .01em;
|
|
color: var(--schrift);
|
|
}
|
|
.laufzeit__wort {
|
|
font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
|
|
color: var(--schrift-leise);
|
|
}
|
|
|
|
/* Die Zahlen. Vier Werte, jeder in zwei Zeilen -- Wort klein
|
|
darueber, Zahl gross darunter. So liest man sie im Vorbeisehen. */
|
|
.messwerte {
|
|
display: flex; flex-wrap: wrap; gap: 4px 18px;
|
|
margin: 0;
|
|
}
|
|
.messwerte__paar { display: grid; gap: 1px; }
|
|
.messwerte dt {
|
|
font-size: .72rem; letter-spacing: .06em;
|
|
color: var(--schrift-leise);
|
|
white-space: nowrap;
|
|
}
|
|
.messwerte dd {
|
|
margin: 0;
|
|
font-size: .95rem; font-weight: 800;
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--schrift);
|
|
}
|
|
/* Wenn die Kameraplaetze voll sind, ist das keine Warnung, sondern
|
|
eine Tatsache -- aber eine, die man sehen muss, bevor jemand
|
|
fragt, warum er kein Bild hat. */
|
|
.messwerte dd[data-eng="ja"] { color: color-mix(in srgb, var(--gleich) 22%, #ffffff); }
|
|
.messwerte dd[data-eng="voll"] { color: var(--an-hell); }
|
|
|
|
/* Die drei Knoepfe. Sie stehen rechts und wachsen in die Luecke --
|
|
auf einem breiten Schirm liegen sie damit am rechten Rand, auf
|
|
einem schmalen in einer eigenen Zeile. Keine Schwelle noetig:
|
|
`flex-wrap` misst, statt zu rechnen. */
|
|
.pult__tun { display: flex; gap: 9px; margin-left: auto; flex-wrap: wrap; }
|
|
.tun {
|
|
appearance: none; cursor: pointer;
|
|
min-height: 44px; padding: 0 18px;
|
|
border-radius: 12px;
|
|
border: 1px solid var(--rand-hell);
|
|
background: rgba(255, 255, 255, .05);
|
|
color: var(--schrift);
|
|
font-size: .86rem; font-weight: 800;
|
|
letter-spacing: .01em;
|
|
white-space: nowrap;
|
|
}
|
|
.tun--vor {
|
|
border-color: color-mix(in srgb, var(--gleich) 44%, transparent);
|
|
background: color-mix(in srgb, var(--gleich) 13%, transparent);
|
|
color: color-mix(in srgb, var(--gleich) 24%, #ffffff);
|
|
}
|
|
.tun--live {
|
|
border-color: color-mix(in srgb, var(--an) 56%, transparent);
|
|
background: linear-gradient(180deg,
|
|
color-mix(in srgb, var(--an) 74%, #000),
|
|
color-mix(in srgb, var(--an) 46%, #000));
|
|
color: #fff3f3;
|
|
box-shadow: 0 14px 30px -20px var(--an);
|
|
}
|
|
.tun--aus { color: var(--schrift-leise); }
|
|
.tun[disabled] { opacity: .38; cursor: default; box-shadow: none; }
|
|
|
|
.pult__klapp {
|
|
appearance: none; cursor: pointer;
|
|
width: 44px; height: 44px;
|
|
display: grid; place-items: center;
|
|
border-radius: 12px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .03);
|
|
color: var(--schrift-leise);
|
|
}
|
|
.pult__klapp svg {
|
|
width: 20px; height: 20px;
|
|
fill: none; stroke: currentColor; stroke-width: 2;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
transition: transform .18s ease;
|
|
}
|
|
.pult[data-auf="ja"] .pult__klapp svg { transform: rotate(180deg); }
|
|
|
|
/* ---- Der einklappbare Teil ------------------------------------------- */
|
|
.pult__innen {
|
|
display: none;
|
|
gap: 14px;
|
|
padding: 13px 16px 16px;
|
|
/* Hoechstens die halbe Hoehe -- darueber bleibt vom Saal nichts
|
|
mehr uebrig, und wer sendet, schaut auf das Bild und nicht auf
|
|
die Knoepfe. Was nicht hineinpasst, rollt. */
|
|
/* KLEINER ALS DAS BILD. Gemessen mit 46dvh: Kinosaal 372 Pixel,
|
|
Regie 459 -- die Knoepfe waren groesser als das, worum es geht.
|
|
Mit 19rem bleibt das Bild der groessere Teil, und die
|
|
Sendungs-Tafel (264 Pixel) passt trotzdem ohne Rollen hinein. */
|
|
max-height: min(40dvh, 19rem);
|
|
overflow-y: auto;
|
|
}
|
|
.pult[data-auf="ja"] .pult__innen { display: grid; }
|
|
|
|
/* ---- Die Register ----------------------------------------------------- */
|
|
.reiter {
|
|
display: flex; gap: 4px; flex-wrap: wrap;
|
|
padding: 4px;
|
|
border-radius: 13px;
|
|
background: rgba(0, 0, 0, .35);
|
|
border: 1px solid var(--rand);
|
|
}
|
|
.reiter__knopf {
|
|
appearance: none; cursor: pointer;
|
|
display: inline-flex; align-items: center; gap: 7px;
|
|
min-height: 38px; padding: 0 14px;
|
|
border: 0; border-radius: 10px;
|
|
background: none;
|
|
color: var(--schrift-leise);
|
|
font-size: .82rem; font-weight: 700;
|
|
}
|
|
.reiter__knopf[aria-selected="true"] {
|
|
background: rgba(255, 255, 255, .08);
|
|
color: var(--schrift);
|
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
|
|
}
|
|
.reiter__zahl {
|
|
min-width: 20px; padding: 1px 6px;
|
|
border-radius: 999px;
|
|
background: rgba(255, 255, 255, .09);
|
|
font-size: .72rem; font-variant-numeric: tabular-nums;
|
|
text-align: center;
|
|
}
|
|
.reiter__zahl[data-leer="ja"] { opacity: .45; }
|
|
|
|
.pult-tafel { display: grid; gap: 12px; align-content: start; }
|
|
/* AUSDRUECKLICH. `display: grid` auf einer Klasse schlaegt die
|
|
eingebaute Regel `[hidden] { display: none }` des Browsers --
|
|
je nach Browser und Reihenfolge. Genau so ist in dieser Datei
|
|
schon einmal eine Chatschiene aufgegangen, die zu sein sollte.
|
|
Eine Zeile ist billiger als die Frage, wer gewinnt. */
|
|
.pult-tafel[hidden] { display: none; }
|
|
|
|
/* ---- Die Videospur ----------------------------------------------------
|
|
Vorher gab es fuer das laufende Video im Pult ueberhaupt keine
|
|
Bedienung. Wer spulen wollte, musste in das YouTube-Bild fassen --
|
|
und was dort passiert, passiert nur bei einem selbst, waehrend
|
|
alle anderen weiterlaufen.
|
|
--------------------------------------------------------------------- */
|
|
.spur {
|
|
display: grid; gap: 11px;
|
|
padding: 13px 14px 14px;
|
|
border-radius: 14px;
|
|
background: linear-gradient(180deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, .02));
|
|
border: 1px solid var(--rand);
|
|
}
|
|
.spur__kopf { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
|
|
.spur__marke {
|
|
flex: none;
|
|
padding: 3px 9px;
|
|
border-radius: 7px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .05);
|
|
font-size: .72rem; font-weight: 800;
|
|
letter-spacing: .1em; text-transform: uppercase;
|
|
color: var(--schrift-leise);
|
|
}
|
|
.spur[data-laeuft="ja"] .spur__marke {
|
|
color: #ffe2e4;
|
|
border-color: color-mix(in srgb, var(--an) 50%, transparent);
|
|
background: color-mix(in srgb, var(--an) 18%, transparent);
|
|
}
|
|
.spur__titel {
|
|
min-width: 0;
|
|
font-size: .94rem; font-weight: 700;
|
|
color: var(--schrift);
|
|
/* Ein Videotitel kann sehr lang sein. Eine Zeile mit Auslassung
|
|
ist hier richtig: Die Spur soll nicht wachsen, nur weil jemand
|
|
ein Video mit langem Namen eingetragen hat. */
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
}
|
|
.spur__titel[data-roh="ja"] {
|
|
color: var(--schrift-leise);
|
|
font-family: ui-monospace, "Cascadia Mono", Menlo, monospace;
|
|
font-size: .82rem;
|
|
}
|
|
.spur__band { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
|
|
.spur__knopf {
|
|
appearance: none; cursor: pointer;
|
|
min-height: 40px; min-width: 44px; padding: 0 12px;
|
|
border-radius: 11px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .05);
|
|
color: var(--schrift);
|
|
font-size: .8rem; font-weight: 700;
|
|
font-variant-numeric: tabular-nums;
|
|
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
}
|
|
.spur__knopf--gross {
|
|
min-width: 52px;
|
|
background: rgba(255, 255, 255, .1);
|
|
}
|
|
.spur__knopf--gross svg { width: 18px; height: 18px; fill: currentColor; }
|
|
.spur__knopf--weiter {
|
|
border-color: rgba(154, 183, 255, .34);
|
|
background: rgba(154, 183, 255, .12);
|
|
color: #cfe0ff;
|
|
}
|
|
.spur__knopf[disabled] { opacity: .35; cursor: default; }
|
|
.spur__zeit {
|
|
font-size: .78rem; font-variant-numeric: tabular-nums;
|
|
color: var(--schrift-leise);
|
|
white-space: nowrap;
|
|
}
|
|
.spur__schiene {
|
|
appearance: none; -webkit-appearance: none;
|
|
flex: 1 1 10rem; min-width: 8rem;
|
|
height: 30px; background: none; cursor: pointer;
|
|
}
|
|
.spur__schiene::-webkit-slider-runnable-track {
|
|
height: 5px; border-radius: 3px;
|
|
background: linear-gradient(90deg, var(--an) var(--fortschritt, 0%),
|
|
rgba(255, 255, 255, .12) var(--fortschritt, 0%));
|
|
}
|
|
.spur__schiene::-webkit-slider-thumb {
|
|
-webkit-appearance: none;
|
|
width: 15px; height: 15px; margin-top: -5px;
|
|
border-radius: 50%;
|
|
background: #f4f1fb;
|
|
border: 1px solid rgba(0, 0, 0, .4);
|
|
}
|
|
.spur__schiene::-moz-range-track {
|
|
height: 5px; border-radius: 3px;
|
|
background: rgba(255, 255, 255, .12);
|
|
}
|
|
.spur__schiene::-moz-range-progress {
|
|
height: 5px; border-radius: 3px; background: var(--an);
|
|
}
|
|
.spur__schiene::-moz-range-thumb {
|
|
width: 15px; height: 15px; border-radius: 50%;
|
|
background: #f4f1fb; border: 1px solid rgba(0, 0, 0, .4);
|
|
}
|
|
|
|
/* ---- Die Warteschlange ------------------------------------------------ */
|
|
.warteliste { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
|
|
.warte-zeile {
|
|
display: flex; align-items: center; gap: 10px;
|
|
padding: 7px 9px 7px 7px;
|
|
border-radius: 12px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .03);
|
|
}
|
|
.warte-zeile__nr {
|
|
flex: none;
|
|
width: 22px; text-align: center;
|
|
font-size: .78rem; font-weight: 800;
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--schrift-leise);
|
|
}
|
|
/* Das Vorschaubild kommt von YouTube selbst -- ohne es sind zehn
|
|
Zeilen Text kaum auseinanderzuhalten. */
|
|
.warte-zeile__bild {
|
|
flex: none;
|
|
width: 68px; aspect-ratio: 16 / 9;
|
|
border-radius: 7px; object-fit: cover;
|
|
background: #12101a;
|
|
border: 1px solid var(--rand);
|
|
}
|
|
.warte-zeile__titel {
|
|
flex: 1 1 8rem; min-width: 0;
|
|
font-size: .84rem; color: var(--schrift);
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
}
|
|
.warte-zeile__titel[data-roh="ja"] {
|
|
color: var(--schrift-leise);
|
|
font-family: ui-monospace, "Cascadia Mono", Menlo, monospace;
|
|
font-size: .78rem;
|
|
}
|
|
.warte-zeile__knoepfe { display: flex; gap: 5px; flex: none; }
|
|
.warte-zeile__knoepfe button {
|
|
appearance: none; cursor: pointer;
|
|
min-height: 34px; min-width: 34px; padding: 0 9px;
|
|
border-radius: 9px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .04);
|
|
color: var(--schrift-leise);
|
|
font-size: .78rem; font-weight: 700;
|
|
}
|
|
.warte-zeile__knoepfe button[data-was="jetzt"] {
|
|
border-color: rgba(154, 183, 255, .34);
|
|
color: #cfe0ff;
|
|
}
|
|
.warte-zeile__knoepfe button[disabled] { opacity: .3; cursor: default; }
|
|
.warte-leer {
|
|
margin: 0; padding: 14px 4px;
|
|
font-size: .82rem; color: var(--schrift-leise);
|
|
}
|
|
|
|
/* ---- Die Regler -------------------------------------------------------
|
|
Senkrecht, nebeneinander, mit Pegel daneben. Ein Mischpult sieht
|
|
so aus, und das ist kein Zitat: Vier waagerechte Regler
|
|
untereinander liest man als Formular, vier senkrechte nebeneinander
|
|
als EINEN Zustand.
|
|
|
|
DER PEGEL IST DAS EIGENTLICHE. Er beantwortet die Frage, die man
|
|
sich sonst erst nach der Sendung stellt: „War mein Mikro
|
|
ueberhaupt an?" Ein Regler auf 100 sagt darueber nichts.
|
|
--------------------------------------------------------------------- */
|
|
.regler-reihe { display: flex; gap: 10px; flex-wrap: wrap; }
|
|
.regler {
|
|
display: grid;
|
|
grid-template-columns: auto auto;
|
|
grid-template-areas: "wort wort" "schieber pegel" "zahl zahl" "stumm stumm";
|
|
justify-items: center; align-items: center;
|
|
gap: 7px 6px;
|
|
padding: 11px 11px 10px;
|
|
border-radius: 13px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .03);
|
|
}
|
|
.regler__wort {
|
|
grid-area: wort;
|
|
font-size: .72rem; font-weight: 800;
|
|
letter-spacing: .05em;
|
|
color: var(--schrift-leise);
|
|
white-space: nowrap;
|
|
}
|
|
.regler input[type="range"] {
|
|
grid-area: schieber;
|
|
appearance: none; -webkit-appearance: none;
|
|
writing-mode: vertical-lr; direction: rtl;
|
|
width: 26px; height: 92px;
|
|
background: none; cursor: pointer;
|
|
}
|
|
/* DER FADER IST GRAU, DER PEGEL IST FARBIG -- so herum, und nicht
|
|
umgekehrt. Ein roter Fader steht bei jedem auf 100 und schreit
|
|
dauerhaft „Achtung", ohne etwas zu sagen. Die Farbe gehoert
|
|
dorthin, wo sie eine Auskunft ist: an den gemessenen Ausschlag. */
|
|
.regler input[type="range"]::-webkit-slider-runnable-track {
|
|
width: 5px; border-radius: 3px;
|
|
background: linear-gradient(180deg, rgba(255, 255, 255, .28), rgba(255, 255, 255, .08));
|
|
}
|
|
.regler input[type="range"]::-webkit-slider-thumb {
|
|
-webkit-appearance: none;
|
|
width: 22px; height: 13px; margin-left: -9px;
|
|
border-radius: 4px;
|
|
background: linear-gradient(180deg, #f6f3fc, #b9b3cc);
|
|
border: 1px solid rgba(0, 0, 0, .45);
|
|
}
|
|
.regler input[type="range"]::-moz-range-track {
|
|
width: 5px; border-radius: 3px;
|
|
background: linear-gradient(180deg, rgba(255, 255, 255, .28), rgba(255, 255, 255, .08));
|
|
}
|
|
.regler input[type="range"]::-moz-range-thumb {
|
|
width: 22px; height: 13px; border-radius: 4px;
|
|
background: linear-gradient(180deg, #f6f3fc, #b9b3cc);
|
|
border: 1px solid rgba(0, 0, 0, .45);
|
|
}
|
|
|
|
/* Der Pegel. Er waechst von unten und faellt langsam zurueck --
|
|
ein Balken, der sofort abfaellt, flackert und ist unlesbar. */
|
|
.pegel {
|
|
grid-area: pegel;
|
|
position: relative;
|
|
width: 7px; height: 92px;
|
|
border-radius: 4px;
|
|
background: rgba(255, 255, 255, .07);
|
|
overflow: hidden;
|
|
}
|
|
.pegel i {
|
|
position: absolute; left: 0; right: 0; bottom: 0;
|
|
height: var(--stand, 0%);
|
|
border-radius: 4px;
|
|
background: linear-gradient(0deg, #4fb27a 0%, #4fb27a 62%, var(--gleich) 84%, var(--an) 100%);
|
|
transition: height .09s linear;
|
|
}
|
|
.pegel[data-still="ja"] i { background: rgba(255, 255, 255, .16); }
|
|
.regler__zahl {
|
|
grid-area: zahl;
|
|
font-size: .74rem; font-variant-numeric: tabular-nums;
|
|
color: var(--schrift-leise);
|
|
}
|
|
.regler__stumm {
|
|
grid-area: stumm;
|
|
appearance: none; cursor: pointer;
|
|
width: 100%; min-height: 32px; padding: 0 9px;
|
|
border-radius: 9px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .04);
|
|
color: var(--schrift-leise);
|
|
font-size: .74rem; font-weight: 700;
|
|
}
|
|
.regler[data-stumm="ja"] .regler__stumm {
|
|
background: color-mix(in srgb, var(--an) 30%, transparent);
|
|
border-color: color-mix(in srgb, var(--an) 50%, transparent);
|
|
color: #ffe2e4;
|
|
}
|
|
|
|
/* ---- Gäste ----------------------------------------------------------- */
|
|
.gast-reihe { display: flex; flex-wrap: wrap; gap: 9px; }
|
|
.gast-karte {
|
|
display: flex; align-items: center; gap: 9px;
|
|
padding: 8px 9px 8px 12px;
|
|
border-radius: 12px;
|
|
background: rgba(255, 255, 255, .04);
|
|
border: 1px solid var(--rand);
|
|
font-size: .82rem; color: var(--schrift);
|
|
}
|
|
.gast-karte__platz {
|
|
font-size: .72rem; font-weight: 800;
|
|
color: var(--schrift-leise); letter-spacing: .08em;
|
|
}
|
|
.gast-karte button {
|
|
appearance: none; cursor: pointer;
|
|
min-height: 32px; padding: 0 10px;
|
|
border-radius: 9px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .04);
|
|
color: var(--schrift-leise);
|
|
font-size: .74rem; font-weight: 700;
|
|
}
|
|
.gast-leer { font-size: .8rem; color: var(--schrift-leise); margin: 0; }
|
|
|
|
/* ---- Anordnung ------------------------------------------------------- */
|
|
.layout-reihe { display: flex; gap: 9px; flex-wrap: wrap; }
|
|
.layout-knopf {
|
|
appearance: none; cursor: pointer;
|
|
min-height: 44px; padding: 9px 15px;
|
|
border-radius: 11px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(255, 255, 255, .04);
|
|
color: var(--schrift-leise);
|
|
font-size: .82rem; font-weight: 700;
|
|
}
|
|
.layout-knopf[aria-pressed="true"] {
|
|
background: rgba(154, 183, 255, .14);
|
|
border-color: rgba(154, 183, 255, .38);
|
|
color: #cfe0ff;
|
|
}
|
|
|
|
/* ---- Die Kürzel ------------------------------------------------------- */
|
|
.kuerzel {
|
|
margin: 0;
|
|
display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center;
|
|
font-size: .72rem; color: var(--schrift-leise);
|
|
}
|
|
.kuerzel kbd {
|
|
display: inline-block;
|
|
padding: 1px 6px; margin-right: 2px;
|
|
border-radius: 6px;
|
|
border: 1px solid var(--rand-hell);
|
|
border-bottom-width: 2px;
|
|
background: rgba(255, 255, 255, .05);
|
|
font-family: inherit; font-size: .72rem; font-weight: 700;
|
|
color: var(--schrift);
|
|
}
|
|
|
|
/* ---- Felder im Pult --------------------------------------------------- */
|
|
.pult__block {
|
|
display: grid; gap: 10px;
|
|
padding: 13px 14px 14px;
|
|
border-radius: 14px;
|
|
background: rgba(255, 255, 255, .03);
|
|
border: 1px solid var(--rand);
|
|
}
|
|
.pult__ueber {
|
|
margin: 0;
|
|
display: flex; align-items: baseline; gap: 9px;
|
|
font-size: .74rem; font-weight: 800;
|
|
letter-spacing: .12em; text-transform: uppercase;
|
|
color: var(--schrift-leise);
|
|
}
|
|
.pult__klein { margin: 0; font-size: .72rem; letter-spacing: .02em; text-transform: none; opacity: .85; }
|
|
.pult__zeile { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
|
|
.pult__feld { display: grid; gap: 5px; flex: 1 1 14rem; min-width: 0; }
|
|
.pult__feld--kurz { flex: 0 1 12rem; }
|
|
.pult__feld > span {
|
|
font-size: .72rem; font-weight: 700;
|
|
color: var(--schrift-leise); letter-spacing: .04em;
|
|
}
|
|
.pult__feld input, .pult__wahl {
|
|
min-height: 44px; padding: 0 12px;
|
|
border-radius: 11px;
|
|
border: 1px solid var(--rand);
|
|
background: rgba(0, 0, 0, .34);
|
|
color: var(--schrift); font: inherit; font-size: .88rem;
|
|
min-width: 0;
|
|
}
|
|
.pult__wahl { flex: 1 1 12rem; }
|
|
|
|
/* =====================================================================
|
|
DAS HANDY
|
|
|
|
Aus zwei Spalten wird ein Stapel, und der Chat wird zur Lade. Das
|
|
Video bleibt oben und behält sein Seitenverhältnis -- es ist der
|
|
Grund, warum jemand hier ist.
|
|
===================================================================== */
|
|
@media (max-width: 860px) {
|
|
.kino {
|
|
grid-template-columns: 1fr;
|
|
grid-template-rows: auto 1fr;
|
|
}
|
|
.leinwand {
|
|
aspect-ratio: 16 / 9;
|
|
height: auto;
|
|
width: 100%;
|
|
}
|
|
.schiene {
|
|
border-left: 0;
|
|
border-top: 1px solid var(--rand);
|
|
min-height: 0;
|
|
}
|
|
.kameras {
|
|
right: 10px; bottom: 10px;
|
|
flex-direction: row;
|
|
}
|
|
.kamera { width: clamp(88px, 26vw, 140px); }
|
|
|
|
/* ==== KEINE LADE, SONDERN EIN STAPEL =========================
|
|
(28.09.2026, nach der ersten Messung auf dem Handy.)
|
|
|
|
Hier stand eine Lade: Der Chat lag zugeklappt über allem und
|
|
fuhr auf Knopfdruck von unten ein. Gemessen war das Ergebnis
|
|
ein 390x775 großer Saal mit einem 219 Pixel hohen Video und
|
|
556 Pixeln Leere darunter -- weil der Knopf, der die Lade
|
|
öffnet, gar nicht erschien.
|
|
|
|
Statt den Knopf zu reparieren, ist die Lade weg. Sie war die
|
|
falsche Lösung für ein Problem, das es nicht gibt: Auf einem
|
|
844 Pixel hohen Telefon bleiben unter Kopfleiste und Video
|
|
rund 550 Pixel übrig. Das ist mehr Chat, als eine Lade je
|
|
zeigen würde -- und es gibt keinen Zustand, in dem etwas
|
|
klemmen kann.
|
|
|
|
Ein Zustand weniger ist besser als ein Zustand, der
|
|
funktioniert. */
|
|
.schiene { display: grid; }
|
|
.schiene__zu { display: none !important; }
|
|
|
|
/* Das Schild wird kleiner und rueckt hoch: Auf 390 Pixeln teilt es
|
|
sich den Platz mit der Titelzeile von YouTube, und zwei Zeilen
|
|
Grossbuchstaben sind dort ein Klotz. */
|
|
.buehne-schild {
|
|
top: 8px;
|
|
padding: 5px 11px 6px;
|
|
/* NICHT KLEINER ALS .72rem -- das sind 11,52 px, die Untergrenze
|
|
des Hauses. Gemessen wurden hier .64rem = 10,24 px. Den Platz
|
|
holt sich die engere Sperrung zurueck: Bei Grossbuchstaben
|
|
kostet .14em Abstand mehr Breite als die zwei fehlenden
|
|
Zehntel Schriftgroesse. */
|
|
font-size: .72rem;
|
|
letter-spacing: .06em;
|
|
gap: 7px;
|
|
white-space: nowrap;
|
|
}
|
|
.buehne-schild__zahl { padding-left: 7px; }
|
|
|
|
/* Der Ton-Knopf in die MITTE des Bildes. Unten liegen bei 219
|
|
Pixeln Hoehe schon die Kamerafenster -- der Knopf lag halb
|
|
darueber. In der Mitte steht er dort, wo ohnehin hingesehen
|
|
wird, und verdeckt nur das, was man gleich sowieso hoert. */
|
|
.ton-an {
|
|
bottom: auto;
|
|
top: 50%;
|
|
transform: translate(-50%, -50%);
|
|
}
|
|
|
|
.warte__buehne { gap: 18px; }
|
|
.pult__innen { max-height: 62dvh; }
|
|
|
|
/* ==== DIE REGIE AM HANDY ======================================
|
|
Die Leiste bleibt -- sie ist der Teil, den man im Notfall
|
|
braucht. Sie wird nur kleiner und legt die Knöpfe in eine
|
|
eigene Zeile, sobald es eng wird. Das macht `flex-wrap` von
|
|
selbst; hier steht nur, was dabei schrumpfen darf. */
|
|
.pult__leiste { gap: 8px 12px; padding: 9px 12px; }
|
|
.messwerte { gap: 3px 13px; }
|
|
.messwerte dd { font-size: .88rem; }
|
|
.laufzeit__zahl { font-size: .98rem; }
|
|
.tun { padding: 0 13px; font-size: .8rem; }
|
|
.pult__innen { padding: 11px 12px 14px; }
|
|
/* Die Register rollen waagerecht statt umzubrechen: Fünf Reiter in
|
|
zwei Zeilen sehen aus wie zehn Knöpfe. */
|
|
.reiter { flex-wrap: nowrap; overflow-x: auto; }
|
|
.reiter__knopf { white-space: nowrap; }
|
|
.regler-reihe { gap: 8px; }
|
|
.regler { padding: 9px 9px 8px; }
|
|
.regler input[type="range"], .pegel { height: 76px; }
|
|
.warte-zeile__bild { width: 54px; }
|
|
}
|
|
|
|
/* Wer weniger Bewegung eingestellt hat, bekommt keinen Puls. Die
|
|
Aussage bleibt -- der Punkt steht dann einfach da. */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.buehne-schild__punkt,
|
|
.lampe__punkt { animation: none !important; }
|
|
.pult__klapp svg,
|
|
.pegel i { transition: none !important; }
|
|
}
|
|
|
|
/* ---- Der Ton-Knopf ---------------------------------------------------
|
|
Er liegt über der Leinwand, mittig unten -- dort, wo der Blick
|
|
ohnehin ist, und weit genug von den Kamerafenstern entfernt. Er
|
|
verschwindet in dem Moment, in dem der Ton läuft; ein Knopf, der
|
|
bleibt, nachdem er getan hat, was er soll, wird zur Deko. */
|
|
.ton-an {
|
|
position: absolute;
|
|
left: 50%; bottom: 20px;
|
|
transform: translateX(-50%);
|
|
z-index: 30;
|
|
display: flex; align-items: center; gap: 9px;
|
|
appearance: none; cursor: pointer;
|
|
min-height: 44px; padding: 10px 18px;
|
|
border-radius: 999px;
|
|
border: 1px solid color-mix(in srgb, var(--an-hell) 50%, transparent);
|
|
background: rgba(10, 8, 16, .88);
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
color: #ffe9ea;
|
|
font-size: .88rem; font-weight: 700;
|
|
box-shadow: 0 18px 40px -18px #000, 0 0 26px -10px var(--an);
|
|
}
|
|
.ton-an svg {
|
|
width: 19px; height: 19px;
|
|
fill: none; stroke: currentColor; stroke-width: 1.8;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
}
|
|
|
|
/* =====================================================================
|
|
DIE SENDERLEISTE (28.09.2026)
|
|
|
|
Kamera und Mikro gehoeren dem, der sendet -- Host wie Gast. Sie
|
|
liegen UEBER dem Bild und nicht im Regiepult: Waehrend einer
|
|
Sendung sieht man auf das Bild, und ein Gast hat ueberhaupt kein
|
|
Pult.
|
|
|
|
SIE IST LEISE, SOLANGE ALLES AN IST. Zwei dunkle Knoepfe am Rand.
|
|
Erst wenn etwas AUS ist, wird der Knopf rot -- dann ist es eine
|
|
Auskunft und keine Verzierung.
|
|
===================================================================== */
|
|
.senderleiste {
|
|
position: absolute;
|
|
left: 16px; bottom: 16px;
|
|
z-index: 30;
|
|
display: flex; align-items: center; gap: 8px;
|
|
padding: 6px;
|
|
border-radius: 999px;
|
|
background: rgba(10, 8, 16, .82);
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
border: 1px solid var(--rand);
|
|
box-shadow: 0 16px 38px -20px #000;
|
|
}
|
|
.sender-knopf {
|
|
appearance: none; cursor: pointer;
|
|
display: inline-flex; align-items: center; gap: 8px;
|
|
min-height: 40px; padding: 0 14px 0 11px;
|
|
border-radius: 999px;
|
|
border: 1px solid transparent;
|
|
background: rgba(255, 255, 255, .06);
|
|
color: var(--schrift);
|
|
font-size: .8rem; font-weight: 700;
|
|
}
|
|
.sender-knopf svg {
|
|
width: 19px; height: 19px;
|
|
fill: none; stroke: currentColor; stroke-width: 1.7;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
}
|
|
/* Der Schraegstrich erscheint nur, wenn es AUS ist -- dasselbe
|
|
Zeichen, das jedes Geraet dafuer benutzt. */
|
|
.sender-knopf__strich { opacity: 0; }
|
|
.sender-knopf[aria-pressed="true"] {
|
|
background: color-mix(in srgb, var(--an) 34%, transparent);
|
|
border-color: color-mix(in srgb, var(--an) 58%, transparent);
|
|
color: #ffe2e4;
|
|
}
|
|
.sender-knopf[aria-pressed="true"] .sender-knopf__strich { opacity: 1; }
|
|
|
|
/* Der Pegel in der Leiste: der kuerzeste Weg zur Antwort auf
|
|
„kommt mein Ton ueberhaupt an?". */
|
|
.sender-pegel {
|
|
display: block;
|
|
width: 5px; height: 26px;
|
|
margin: 0 8px 0 2px;
|
|
border-radius: 3px;
|
|
background: rgba(255, 255, 255, .1);
|
|
position: relative; overflow: hidden;
|
|
}
|
|
.sender-pegel i {
|
|
position: absolute; left: 0; right: 0; bottom: 0;
|
|
height: var(--stand, 0%);
|
|
border-radius: 3px;
|
|
background: linear-gradient(0deg, #4fb27a 0%, #4fb27a 64%, var(--gleich) 86%, var(--an) 100%);
|
|
transition: height .09s linear;
|
|
}
|
|
|
|
/* ---- „Kamera aus" im Fenster ----------------------------------------
|
|
Ein abgeschaltetes Bild ist nicht dasselbe wie ein kaputtes. Ohne
|
|
diese Beschriftung sind beide ein schwarzes Rechteck -- und dann
|
|
fragt jemand im Chat, ob die Technik hakt. */
|
|
.kamera__aus {
|
|
position: absolute; inset: 0;
|
|
display: grid; place-items: center;
|
|
background: rgba(8, 7, 14, .88);
|
|
color: var(--schrift-leise);
|
|
font-size: .74rem; font-weight: 700;
|
|
letter-spacing: .06em;
|
|
border-radius: inherit;
|
|
}
|
|
.kamera[data-kamera="aus"] video { opacity: 0; }
|
|
|
|
/* ---- Der Mikro-Schalter im Pult -------------------------------------
|
|
Dieselbe Spalte wie die drei Regler, nur ohne Schieber: Die eigene
|
|
Lautstaerke laesst sich nicht am Regler aendern. Was man braucht,
|
|
ist an/aus -- und der Pegel daneben. */
|
|
.regler--schalter {
|
|
grid-template-areas: "wort" "pegel" "stumm";
|
|
grid-template-columns: auto;
|
|
}
|
|
.regler--schalter .pegel { width: 9px; }
|
|
|
|
/* ---- Die Chat-Stufe --------------------------------------------------
|
|
Drei Schalter im Kopf der Schiene. Man moderiert, wo man liest.
|
|
===================================================================== */
|
|
.stufen {
|
|
display: flex; gap: 3px;
|
|
margin-left: auto;
|
|
padding: 3px;
|
|
border-radius: 10px;
|
|
background: rgba(0, 0, 0, .35);
|
|
border: 1px solid var(--rand);
|
|
}
|
|
.stufe {
|
|
appearance: none; cursor: pointer;
|
|
min-height: 28px; padding: 0 9px;
|
|
border: 0; border-radius: 7px;
|
|
background: none;
|
|
color: var(--schrift-leise);
|
|
font-size: .72rem; font-weight: 700;
|
|
}
|
|
.stufe[aria-pressed="true"] {
|
|
background: rgba(255, 255, 255, .1);
|
|
color: var(--schrift);
|
|
}
|
|
/* Ist der Chat eingeschraenkt, sieht man es der ganzen Schiene an --
|
|
nicht nur dem kleinen Schalter oben. */
|
|
.schiene[data-chat="team"] .schiene__form,
|
|
.schiene[data-chat="zu"] .schiene__form {
|
|
border-top-color: color-mix(in srgb, var(--gleich) 40%, transparent);
|
|
background: color-mix(in srgb, var(--gleich) 7%, transparent);
|
|
}
|
|
.schiene__feld[disabled] { opacity: .75; cursor: not-allowed; }
|
|
.schiene__senden[disabled] { opacity: .4; cursor: not-allowed; }
|
|
|
|
@media (max-width: 860px) {
|
|
/* Am Handy liegen unten rechts die Kamerafenster -- die Leiste
|
|
rueckt nach oben links unter das Schild. */
|
|
.senderleiste { left: 10px; bottom: auto; top: 46px; padding: 4px; gap: 5px; }
|
|
.sender-knopf { min-height: 38px; padding: 0 11px 0 9px; font-size: .74rem; }
|
|
.sender-pegel { height: 22px; margin: 0 5px 0 1px; }
|
|
}
|