VanVan im Support, Meldung #11, VIERMAL gemeldet: „Hier im Supportbereich kann man immer nur ein Bild hinzufuegen bei einer Meldung. 2-3 waeren besser." Und in der zweiten Runde der Satz, auf den es ankommt: „wenn man es nacheinander versucht hinzuzufuegen wird das Bild immer nur ersetzt." EINE TABELLE STATT NEUER SPALTEN `support_bilder` haelt ab jetzt JEDES Supportbild -- das der Meldung (`runde_nr` NULL) und das einer Antwort (`runde_nr` = Runde). Die Alternative waere `bild2_datei`, `bild3_datei` gewesen, und beim vierten Bild wieder. Eine Zeile je Bild kennt keine Obergrenze im Schema; die Grenze steht an EINER Stelle im Code (`BILDER_MAX = 3`) und kommt von dort in die Oberflaeche, statt dort ein zweites Mal zu stehen. DIE ACHT VORHANDENEN BILDER WANDERN MIT. Ohne diesen Schritt haette die neue Tabelle ab heute recht und die alten Bilder waeren unsichtbar -- ohne Fehler, ohne rote Zeile, nur acht leere Karten. Der Umzug steht NACH der Spaltennachruestung: Er liest `urteil_bild_datei`, und die gibt es in einer bestehenden Datenbank erst, nachdem sie ergaenzt wurde. Stuende er davor, scheiterte er genau dort, wo es darauf ankommt -- live, waehrend lokal alles gruen bliebe, weil jede Pruefung ihre Datenbank frisch anlegt. DREI BILDER IN EINER ANFRAGE `x-bilder: 20481,15320` sagt, wo zu schneiden ist, der Rumpf ist die Aneinanderreihung. `multipart/form-data` haette einen Zerleger gebraucht, den dieses Haus nicht hat; drei Anfragen nacheinander haetten den Zustand „Meldung da, Bild zwei laedt noch" erzeugt -- genau den, gegen den die Kommentare an dieser Route schon vorher argumentieren. Die Summe muss auf das Byte stimmen, und jedes Stueck wird einzeln an seinen ersten Bytes erkannt: Wer falsch schneidet, bekommt eine Absage, kein verfaelschtes Bild. Ohne den Kopf gilt der ganze Rumpf als ein Bild -- derselbe Satz mit einer Laenge, damit eine Seite aus dem Zwischenspeicher weiterlaeuft. EINE ROUTE STATT DREI. `/:id/bild` und `/:id/runde/:nr/bild` sind weg; es gibt `/:id/bild/:bid`. Wohin ein Bild gehoert, steht in seiner Zeile -- der Weg muss es nicht wiederholen. Die Meldungsnummer bleibt trotzdem im Pfad: Sie ist die Sichtbarkeitsfrage, und beides muss zusammenpassen (gemessen). ZWEI FUNDE, DIE DIE PRUEFUNG GEMACHT HAT UND NICHT ICH 1. UEBER DIE SEITE KAM GAR KEIN BILD MEHR AN. Beim Melden stand kein `Content-Type`. Das ging gut, solange der Rumpf eine einzelne Datei war -- ein `File` bringt seinen Typ mit. Ein `Blob` aus mehreren hat keinen, `fetch` schickt die Zeile dann gar nicht, `express.raw` fuehlt sich nicht zustaendig, und der Server bekam einen leeren Rumpf. Die Meldung waere durchgegangen, der Text angekommen, die Bilder weg -- ohne Fehlermeldung. Alle Pruefungen am Server waren dabei gruen; gefunden hat es erst der echte Browser. 2. DAS KREUZ DES DRITTEN BILDES LAG AUF DEM ZWEITEN. Der Entfernen-Knopf ist 44 px breit und absolut gesetzt, der Kasten aber nur so breit wie sein Bild. Bei einem schmalen Bild ragt er darueber hinaus -- wer „das zweite weg" antippt, loescht das dritte. `min-width`/`min-height` loesen das an der Ursache: Ein Kasten ist nie schmaler als der Knopf in ihm. WAS ICH FALSCH ANGENOMMEN HATTE: Ich hatte eingebaut, dass ein Nachtrag in derselben Runde die Bilder ersetzt. Die Pruefung dazu wurde rot -- zu Recht: Eine zweite Antwort in derselben Runde kann es nicht geben, die erste verlaesst den Stand „wartet". Der Code waere nie gelaufen und damit nie pruefbar gewesen. Er ist weg; an seiner Stelle steht der Beweis, dass er nicht fehlt. DREI WEITERE ROTE ZEILEN, DIE NICHT ZU DIESEM UMBAU GEHOERTEN * `manager-ziele.js` hatte einen ZWEITEN Notnagel (`frageNach ? … : confirm(…)`). `nachfrage.js` hat denselben laengst, und zwar mit dem vollstaendigen Text; der hiesige war der kuerzere und haette gewonnen. Zwei Antworten auf dieselbe Frage -- gemeldet von `pruef-nachfrage`. * Zwei Mittelpunkte in `reaktion.css` standen woertlich im `content`. Sie liegen im Latin-1-Block, wo `pruef-zeichen` die Truemmer einer verunglueckten Kodierung sucht. Jetzt als Escape -- im Browser nachgemessen, es steht Zeichen fuer Zeichen dasselbe da. * Das Aufraeumen nach 90 Tagen loeschte nur das EINE Bild der Meldung; die Bilder aus den Antwortrunden blieben ohne Zeile auf der Platte liegen. Die Liste kommt jetzt aus einer Abfrage statt aus einer Spalte und kann deshalb nicht wieder unvollstaendig sein. GEPRUEFT pruef-support 78 -> 104 ok darunter: der Umzug der alten Bilder auf einer eigenen Wegwerf-Datenbank -- zweimal und dreimal gestartet, nichts verdoppelt, Datum von damals erhalten pruef-support-bilder NEU, 36 ok (echter Browser) dreimal nacheinander waehlen ergibt drei, das vierte wird mit einem Satz abgelehnt, dasselbe zaehlt nicht doppelt, einzeln entfernen laesst die anderen stehen, alle drei laden wirklich (naturalWidth), Kreuze 44x44 und keines verdeckt (mit Gegenprobe per Deckel), nichts ragt auf 390 px heraus pruef-nachfrage 69 -> 74 ok pruef-struktur 102 ok, 413 Routen (vorher 414: zwei weg, eine neu) pruef-zeichen 7 ok (vorher 1 Fehler) pruef-aufbewahrung 45 ok pruef-manager-ziele 216 ok pruef-ports 10 ok · pruef-portnummern 41 ok (die neue Pruefdatei verschiebt die abgeleiteten Nummern) NUR DAS AGENTURHAUS IST BETROFFEN. Die Supportseite liegt unter `/workspace`; am Crew-Haus aendert sich keine Zeile. Co-Authored-By: Claude Opus 5 <[email protected]>
3907 lines
151 KiB
CSS
3907 lines
151 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.
|
||
===================================================================== */
|
||
|
||
/* `body.reaktion-seite`, NICHT NUR `.reaktion-seite`.
|
||
|
||
`start.css` setzt `body.start { display: block; min-height: 100svh }`
|
||
-- Staerke (0,1,1). Eine Regel mit nur einer Klasse ist (0,1,0)
|
||
und verliert, ganz gleich welche Datei spaeter geladen wird.
|
||
Gemessen: Die Spalte kam gar nicht zustande, der Saal wuchs auf
|
||
1615 Pixel. Vierter Fall dieser Art an einem Tag; deshalb steht
|
||
der Grund hier und nicht nur die Loesung. */
|
||
body.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.
|
||
|
||
EINE SPALTE, KEINE RECHNUNG. Der Saal stand bis zum 28.09.2026
|
||
auf `height: calc(100dvh - 69px)` -- 69 war einmal die Hoehe
|
||
der Kopfleiste. Sie ist inzwischen 73 Pixel hoch, und der Saal
|
||
ragte damit 4 Pixel unter den Fensterrand; die Transportleiste
|
||
mit dem Play-Knopf war nur noch mit Scrollen zu erreichen.
|
||
Als Spalte misst es sich von selbst: Die Kopfleiste nimmt, was
|
||
sie braucht, der Saal bekommt den Rest. Waechst sie wieder,
|
||
rechnet niemand nach. */
|
||
display: flex;
|
||
flex-direction: column;
|
||
/* `height`, nicht `min-height`: Mit einer Mindesthoehe hat der
|
||
Saal als Flex-Kind nichts, wogegen er schrumpfen koennte --
|
||
gemessen wuchs er auf 1615 Pixel. Erst eine feste Hoehe am
|
||
Container gibt ihm die Grenze, innerhalb derer er sich
|
||
einrichtet. */
|
||
height: 100dvh;
|
||
overflow: hidden;
|
||
}
|
||
/* Der Saal bekommt den Rest -- `min-height: 0`, sonst besteht er
|
||
als Flex-Kind auf der Hoehe seines Inhalts und schiebt die
|
||
Rechnung wieder auf. */
|
||
body.reaktion-seite > .saal { flex: 1 1 auto; min-height: 0; }
|
||
body.reaktion-seite > .kopfleiste { flex: none; }
|
||
|
||
.saal {
|
||
position: relative;
|
||
display: grid;
|
||
/* ==== DREI ZEILEN, UND NUR DIE MITTLERE DEHNT SICH ===============
|
||
|
||
Vorher standen hier nur zwei Kinder und gar keine Zeilenangabe --
|
||
der Browser verteilte den Platz zwischen Saal und Regie, wie er
|
||
wollte. Mit der Regieleiste oben wären es drei, und das Bild
|
||
hätte gegen zwei Leisten um Platz gekämpft.
|
||
|
||
`minmax(0, 1fr)` und nicht `1fr`: Ein Raster-Kind mit `1fr` hat
|
||
eine Mindestgröße von `auto` — es kann also größer werden als
|
||
sein Anteil, wenn sein Inhalt das verlangt, und schiebt dann
|
||
alles darunter aus dem Fenster. Genau das ist am 28.09. mit der
|
||
Regie passiert (197 px Überlauf). Die Null nimmt ihm das Recht.
|
||
|
||
DIESE ANGABE STEHT NUR HIER — und das ist der eigentliche
|
||
Punkt. Bis zum 28.09.2026 gab es 900 Zeilen weiter unten eine
|
||
ZWEITE (`minmax(0, 1fr) auto`, aus der Zeit, als der Saal zwei
|
||
Zeilen hatte). Sie stand später in der Datei und gewann: Die
|
||
Regieleiste landete in der `1fr`-Zeile, bekam null Pixel, und
|
||
ihre Register ragten über das Video.
|
||
|
||
WIE MICH DAS FAST IN DIE FALSCHE REPARATUR GEFÜHRT HÄTTE: Ich
|
||
habe im Browser vier Möglichkeiten durchprobiert und dabei
|
||
`style.gridTemplateRows` gesetzt — ein Stilattribut am Element
|
||
schlägt JEDE Regel im Stilblatt. Damit sah es so aus, als läge
|
||
es an `auto` gegen `min-content`; beide „funktionierten", weil
|
||
beide die zweite Regel aushebelten. Erst nachdem die Doppelung
|
||
weg war, hat die Gegenprobe gezeigt: `auto` tut es genauso.
|
||
Eine Probe, die mehr ändert als das, wonach man sucht,
|
||
beantwortet eine andere Frage. */
|
||
grid-template-rows: auto minmax(0, 1fr) auto auto;
|
||
/* KEINE HOEHE MEHR. Bis zum 28.09.2026 stand hier
|
||
`height: calc(100dvh - 69px)`; die 69 waren die damals
|
||
gemessene Kopfleiste. Sie ist 73 geworden. Jetzt ist der
|
||
Koerper eine Spalte und der Saal ihr dehnbares Kind -- die
|
||
Hoehe ergibt sich, statt gerechnet zu werden. */
|
||
height: auto;
|
||
padding: 0;
|
||
max-width: none;
|
||
}
|
||
.regieleiste { grid-row: 1; }
|
||
/* DER RAUM steht in der zweiten Zeile -- nicht mehr die drei Häute.
|
||
Sie liegen seit dem 30.09.2026 in ihm und werden dort platziert
|
||
(siehe „DER RAUM" weiter unten). Stünde die Angabe weiter an
|
||
ihnen, legte sie sie in eine stillschweigende zweite Zeile DES
|
||
RAUMS; gemessen war das Kino danach 0 px hoch. */
|
||
.raum { grid-row: 2; }
|
||
.pult { grid-row: 3; }
|
||
.transport { grid-row: 4; }
|
||
.transport[hidden] { display: none; }
|
||
|
||
/* =====================================================================
|
||
DIE REGIE STEHT LINKS -- NICHT NUR UNTEN (28.09.2026)
|
||
|
||
Filipe: „anstatt alles nur unten zu haben wieso nicht rechts und
|
||
links noch ausnutzen um mehr ueberblick zu haben."
|
||
|
||
Die Regie klebte als 272 Pixel hoher Streifen unten, waehrend
|
||
darueber das ganze Bild frei war. Man sah entweder das Video oder
|
||
die Bedienung.
|
||
|
||
AUFGEKLAPPT steht sie jetzt LINKS neben dem Video, ueber die volle
|
||
Hoehe. Rechts der Chat, unten die Senderleiste und der Transport.
|
||
Das ist die Anordnung jedes Sendepults: Was man bedient, liegt
|
||
neben dem, was man dabei ansieht.
|
||
|
||
ZUGEKLAPPT bleibt alles, wie es war -- eine schmale Leiste unten.
|
||
Wer die Regie zumacht, will das Bild gross, und dann waere eine
|
||
leere Spalte daneben genau das Gegenteil.
|
||
|
||
`:has()` UND KEINE KLASSE AM KOERPER. Der Zustand steht schon am
|
||
Pult (`data-auf`); ein zweiter Merker am `body` waere die zweite
|
||
Antwort auf dieselbe Frage -- und die laeuft irgendwann von der
|
||
ersten weg.
|
||
|
||
ERST AB 1100 PIXELN. Darunter bliebe fuer das Video keine Breite
|
||
mehr uebrig: 26rem Regie plus 23rem Chat sind schon 784 Pixel. Die
|
||
Zahl ist gerechnet, nicht geraten. */
|
||
@media (min-width: 1100px) {
|
||
.saal:has(.pult[data-auf="ja"]) {
|
||
grid-template-columns: clamp(21rem, 25vw, 27rem) minmax(0, 1fr);
|
||
grid-template-areas:
|
||
"leiste leiste"
|
||
"pult kino"
|
||
"pult kino"
|
||
"transport transport";
|
||
grid-template-rows: auto minmax(0, 1fr) auto auto;
|
||
}
|
||
.saal:has(.pult[data-auf="ja"]) .regieleiste { grid-area: leiste; }
|
||
/* Das Feld „kino" nimmt der RAUM ein -- darin stehen dann Bild und
|
||
Chat nebeneinander, wie der Satz oben es beschreibt. Vor dem
|
||
30.09.2026 standen hier die drei Häute; seit sie im Raum liegen,
|
||
zeigte die Angabe auf ein Feld, das es in ihrem Raster nicht
|
||
gibt, und das Kino landete mit 0 px neben dem Bild. */
|
||
.saal:has(.pult[data-auf="ja"]) .raum { grid-area: kino; }
|
||
.saal:has(.pult[data-auf="ja"]) .transport { grid-area: transport; }
|
||
|
||
.saal:has(.pult[data-auf="ja"]) .pult {
|
||
grid-area: pult;
|
||
display: grid;
|
||
/* Der Kopf oben, der Inhalt darunter -- und der Inhalt nimmt,
|
||
was uebrig ist. `minmax(0, 1fr)` und nicht `1fr`: Sonst kann
|
||
die Spalte von ihrem Inhalt aufgezogen werden, statt zu
|
||
rollen. Genau diese Falle hat am selben Tag der Regieleiste
|
||
null Pixel gegeben. */
|
||
grid-template-rows: auto minmax(0, 1fr);
|
||
border-top: 0;
|
||
border-right: 1px solid var(--rand);
|
||
}
|
||
/* ENDLICH PLATZ. Unten waren es 272 Pixel fuer drei Felder
|
||
untereinander -- sie passten nicht, und der Transport verdeckte
|
||
den Rest. Hier ist die Hoehe die des Saals. */
|
||
.saal .pult__innen {
|
||
max-height: none;
|
||
height: 100%;
|
||
overflow-y: auto;
|
||
}
|
||
/* In einer schmalen Spalte stehen die Kacheln UNTEREINANDER. Zwei
|
||
nebeneinander waeren auf 21rem je 10rem breit -- dort passt kein
|
||
Videotitel und kein Datumsfeld hinein. */
|
||
.saal:has(.pult[data-auf="ja"]) .regieplatz {
|
||
grid-template-columns: minmax(0, 1fr);
|
||
grid-template-areas: "laeuft" "sendung" "bereit";
|
||
}
|
||
/* Die Senderleiste des Pults bleibt oben in der Spalte stehen,
|
||
damit „Auf Sendung" nicht wegrollt. */
|
||
.saal:has(.pult[data-auf="ja"]) .pult__leiste {
|
||
position: sticky; top: 0; z-index: 2;
|
||
}
|
||
}
|
||
|
||
/* =====================================================================
|
||
DIE REGIELEISTE — über dem Saal (28.09.2026)
|
||
|
||
Filipe: „ich hätte das gerne oben also nicht in dieser kachel
|
||
sondern über der kachel wo die videos laufen werden."
|
||
|
||
SIE IST FLACH UND DUNKEL. Eine Leiste am oberen Rand steht neben
|
||
dem Video und über allem, was im Saal passiert — alles, was dort
|
||
selbst leuchtet, zieht den Blick vom Bild weg. Sie bekommt deshalb
|
||
keine Farbe, nur eine Kante nach unten und einen Hauch Licht
|
||
darüber, damit sie als Körper lesbar bleibt und nicht als Strich.
|
||
===================================================================== */
|
||
.regieleiste {
|
||
position: relative;
|
||
z-index: 50;
|
||
min-width: 0;
|
||
/* Schild und Register nebeneinander. Das Schild steht AUSSERHALB
|
||
des rollenden Teils -- es soll stehenbleiben, wenn die Register
|
||
unter dem Finger wandern. */
|
||
display: flex; align-items: stretch;
|
||
padding: 0;
|
||
background:
|
||
linear-gradient(180deg, rgba(255, 255, 255, .05), transparent 60%),
|
||
rgba(7, 6, 13, .96);
|
||
border-bottom: 1px solid var(--rand-hell);
|
||
box-shadow: 0 10px 26px -20px #000;
|
||
backdrop-filter: blur(16px) saturate(1.15);
|
||
-webkit-backdrop-filter: blur(16px) saturate(1.15);
|
||
}
|
||
.regieleiste[hidden] { display: none; }
|
||
|
||
/* Das Schild. Klein, gesperrt, leise -- es soll benennen, nicht
|
||
rufen. Rechts eine haarfeine Kante als Trennung; ein Abstand
|
||
allein liest sich bei sieben Wörtern daneben nicht als Grenze. */
|
||
/* AM RECHNER GIBT ES DEN KLAPPKNOPF NICHT. Dort ist Platz, und ein
|
||
Knopf, der nichts zu tun hat, ist ein Knopf, den man ausprobiert. */
|
||
.reiter__auf { display: none; }
|
||
|
||
.regieleiste__schild {
|
||
flex: none;
|
||
display: flex; align-items: center;
|
||
padding: 0 14px 0 16px;
|
||
margin-right: 4px;
|
||
border-right: 1px solid var(--rand);
|
||
font-size: .68rem; font-weight: 800;
|
||
letter-spacing: .22em; text-transform: uppercase;
|
||
color: color-mix(in srgb, var(--schrift-leise) 72%, transparent);
|
||
user-select: none;
|
||
}
|
||
/* AM HANDY WEG. Dort zählt jeder Millimeter für die Register
|
||
selbst -- und wer die Regie auf dem Handy öffnet, weiß, was er
|
||
geöffnet hat. */
|
||
@media (max-width: 560px) {
|
||
.regieleiste__schild { display: 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
|
||
--------------------------------------------------------------------- */
|
||
/* ==== DER RAUM: zwei Spalten, und die rechte bleibt ===============
|
||
|
||
Filipe, 30.09.2026: „mach dass ich die chat kiste immer sehe bitte
|
||
und nicht erst wenn das video läuft."
|
||
|
||
Die Schiene lag bis dahin IM Kino und ging mit ihm weg — sichtbar
|
||
war sie damit nur im Live. Jetzt hält der Raum die Spalten: Links
|
||
wechseln sich die drei Häute ab, rechts steht der Chat.
|
||
|
||
DIE SPALTEN STEHEN NUR HIER. `.kino` hatte sie vorher selbst;
|
||
blieben sie dort, wären es zwei Antworten auf dieselbe Frage — und
|
||
genau daran ist am 28.09. die Regieleiste auf null Pixel gelaufen,
|
||
weil zwei `grid-template-rows` in dieser Datei standen und die
|
||
spätere gewann. */
|
||
.raum {
|
||
display: grid;
|
||
grid-template-columns: 1fr minmax(19rem, 23rem);
|
||
/* DIE ZEILE MUSS FEST SEIN. Ohne Angabe hat ein Raster eine
|
||
stillschweigende Zeile, die sich am Inhalt bemisst — und darin
|
||
steht `.kino` mit `height: 100%`, also „so hoch wie die Zeile".
|
||
Zwei Angaben, die aufeinander zeigen; der Browser löst das mit
|
||
NULL auf. Gemessen: Kino 613 px → 0 px, und mit der Leinwand
|
||
rutschten Spendenkarte und Kamera-Schild aus dem Bild.
|
||
|
||
Vorher lag `.kino` unmittelbar in der Zeile `minmax(0, 1fr)` des
|
||
Saals — die Festigkeit wandert hier mit. */
|
||
grid-template-rows: minmax(0, 1fr);
|
||
height: 100%;
|
||
min-height: 0; /* sonst wächst das Raster über das Fenster */
|
||
}
|
||
/* ALLE DREI HÄUTE IN DIESELBE ZELLE. Nicht nebeneinander: Sichtbar
|
||
ist immer genau eine, und die soll die ganze Spalte haben. */
|
||
#teil-zu, #teil-warte, #teil-live { grid-area: 1 / 1; }
|
||
.raum > .schiene { grid-area: 1 / 2; }
|
||
|
||
#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 {
|
||
/* KEINE SPALTEN MEHR — die hält seit dem 30.09.2026 `.raum`, weil
|
||
die Chatschiene nicht mehr hier drinliegt. Hier stünde sonst die
|
||
zweite Antwort auf dieselbe Frage. */
|
||
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;
|
||
}
|
||
/* Links oben und nicht rechts: Rechts unten liegen die Kamerafenster,
|
||
rechts oben das Stumm-Schild. Gedeckt und klein -- es soll
|
||
beantworten, nicht rufen. */
|
||
.leinwand__tempo {
|
||
position: absolute; left: 14px; top: 14px;
|
||
z-index: 22;
|
||
padding: 3px 9px 4px;
|
||
border-radius: 999px;
|
||
font-size: .72rem; font-weight: 800;
|
||
font-variant-numeric: tabular-nums;
|
||
letter-spacing: .04em;
|
||
background: rgba(6, 5, 11, .76);
|
||
border: 1px solid var(--rand);
|
||
color: var(--schrift-leise);
|
||
backdrop-filter: blur(6px);
|
||
}
|
||
.leinwand__tempo[hidden] { display: none; }
|
||
|
||
/* ---- 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.
|
||
--------------------------------------------------------------------- */
|
||
/* ==== EINE GRUNDBREITE FUER ALLE ANORDNUNGEN ======================
|
||
|
||
`--kam` ist die Breite EINES Kamerafensters. Sie steht an einer
|
||
Stelle und wird von den Anordnungen nur nachjustiert; `--kam-gross`
|
||
ist der Faktor, den die Regie setzt (0,6 bis 2).
|
||
|
||
WARUM EINE VARIABLE UND NICHT FUENF ZAHLEN: Vorher stand die
|
||
Breite zweimal im Stilblatt -- einmal als Grundregel, einmal für
|
||
„Kameras gross". Wer die Größe einstellbar macht, müsste beide
|
||
Stellen mitdenken, und die zweite wird vergessen. Das ist genau
|
||
die Doppelung, die am selben Tag der Regieleiste null Pixel
|
||
gegeben hat. */
|
||
.kino {
|
||
/* `--kam-grund` wie breit ein Fenster ohne Zutun ist.
|
||
`--kam-gross` der Faktor, den die Regie setzt (0,6 bis 2).
|
||
`--kam` das Ergebnis -- an EINER Stelle gerechnet.
|
||
`--kam-rand` wie weit der Stapel von der Kante der Leinwand
|
||
wegsitzt; am Handy enger, weil dort jeder
|
||
Pixel Video zählt.
|
||
|
||
Wer etwas ändern will, ändert `--kam-grund` oder `--kam-rand`.
|
||
Wer `--kam` selbst überschreibt, baut die zweite Antwort auf
|
||
dieselbe Frage -- und die gewinnt dann irgendwo still. */
|
||
--kam-gross: 1;
|
||
--kam-grund: clamp(120px, 17vw, 208px);
|
||
--kam: calc(var(--kam-grund) * var(--kam-gross));
|
||
--kam-rand: 16px;
|
||
}
|
||
.kameras {
|
||
position: absolute;
|
||
/* Standardecke: unten rechts. `inset` statt `right`/`bottom`
|
||
einzeln -- die Ecken-Regeln weiter unten setzen dann ALLE vier
|
||
Werte auf einmal, statt drei zurückzunehmen und einen zu
|
||
setzen. Ein halb zurückgenommener Rand ist eine Ecke, die
|
||
manchmal klebt. */
|
||
inset: auto var(--kam-rand) var(--kam-rand) auto;
|
||
width: var(--kam);
|
||
/* NIE MEHR ALS FAST DIE HAELFTE. Bei Faktor 2 auf einem schmalen
|
||
Bildschirm deckte ein einzelnes Fenster sonst das halbe Video
|
||
zu -- und auf dem Handy mehr. Der Prozentwert bezieht sich auf
|
||
die Leinwand, weil der Behälter absolut darin liegt. */
|
||
max-width: 46%;
|
||
display: flex; flex-direction: column; gap: 12px;
|
||
pointer-events: none;
|
||
z-index: 20;
|
||
}
|
||
|
||
/* ---- Die vier Ecken ---------------------------------------------------
|
||
Filipe: „die verschiedenen groessen von kamera und so."
|
||
|
||
WOFUER DAS DA IST: Unten rechts liegt bei TikTok die Knopfreihe,
|
||
bei YouTube die Fortschrittsleiste, und Untertitel stehen fast
|
||
immer unten. Eine feste Ecke ist eine, die bei jeder zweiten
|
||
Plattform genau im Weg steht.
|
||
|
||
Sie stehen VOR den Anordnungen: „Kameras gross" und „nur Kamera"
|
||
setzen den Behälter ohnehin in die Mitte, und bei gleicher
|
||
Stärke gewinnt die spätere Regel. */
|
||
.kino[data-ecke="ol"] .kameras { inset: var(--kam-rand) auto auto var(--kam-rand); }
|
||
.kino[data-ecke="or"] .kameras { inset: var(--kam-rand) var(--kam-rand) auto auto; }
|
||
.kino[data-ecke="ul"] .kameras { inset: auto auto var(--kam-rand) var(--kam-rand); }
|
||
.kino[data-ecke="ur"] .kameras { inset: auto var(--kam-rand) var(--kam-rand) auto; }
|
||
|
||
.kamera {
|
||
position: relative;
|
||
width: 100%;
|
||
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;
|
||
}
|
||
|
||
/* ==== EIN GETEILTER BILDSCHIRM WIRD NICHT ZUGESCHNITTEN ============
|
||
|
||
Filipe: „waere es nicht einfach eine bildschirm uebertragung zu
|
||
installieren?"
|
||
|
||
`cover` ist fuer ein Gesicht richtig: Es fuellt den Rahmen, und
|
||
was an den Seiten fehlt, fehlt niemandem. Bei einem Bildschirm
|
||
faellt genau das weg, worum es geht -- 16:9 in einem 4:3-Fenster
|
||
verliert links und rechts je ein Achtel, und dort steht die
|
||
Werkzeugleiste.
|
||
|
||
`contain` UND EIN SCHWARZER GRUND. Die schwarzen Streifen sind
|
||
kein Schoenheitsfehler, sondern die einzige Art, ein Bild ganz zu
|
||
zeigen, dessen Form man nicht kennt.
|
||
|
||
UND DAS SEITENVERHAELTNIS GEHT AUF 16:9. Ein Bildschirm ist fast
|
||
nie 4:3; das Fenster passt sich an, statt den Rahmen mit Schwarz
|
||
zu fuellen. */
|
||
.kamera[data-bildschirm="ja"] { aspect-ratio: 16 / 9; }
|
||
.kamera[data-bildschirm="ja"] video {
|
||
object-fit: contain;
|
||
background: #000;
|
||
}
|
||
/* Ein Schild, damit niemand ein stehendes Bild fuer eine
|
||
eingefrorene Kamera haelt. */
|
||
.kamera[data-bildschirm="ja"] .kamera__name::before {
|
||
/* DER MITTELPUNKT ALS ESCAPE (02.10.2026). Er liegt im
|
||
Latin-1-Block — genau dort, wo eine verunglückte Kodierung ihre
|
||
Trümmer hinterlässt, und `pruef-zeichen` meldet deshalb jedes
|
||
Zeichen von dort in einem `content`. Die Warnung ist berechtigt:
|
||
Stünde hier statt des Punktes ein Rest aus einer falsch
|
||
gelesenen Datei, sähe man das im Quelltext kaum. Als Escape ist
|
||
es eindeutig, zeigt dasselbe und bleibt prüfbar.
|
||
Das `\0020` dahinter ist das Leerzeichen: Ohne eigenes Escape
|
||
würde CSS es als Fortsetzung der Zahl lesen. */
|
||
content: "Bildschirm \00B7\0020";
|
||
color: var(--schrift-leise);
|
||
}
|
||
.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;
|
||
width: 100%; max-width: none;
|
||
padding: 10px;
|
||
background: #07060d;
|
||
}
|
||
/* Hier bestimmt das Fenster seine Breite selbst -- der Behälter ist
|
||
die ganze Zeile. `min-width: 0` erlaubt dem Flexraster, sie bei
|
||
zwei Gästen zu kürzen, statt die Zeile breiter zu machen. */
|
||
.kino[data-layout="gleich"] .kamera {
|
||
width: var(--kam);
|
||
flex: 0 1 auto;
|
||
min-width: 0;
|
||
}
|
||
.kino[data-layout="gleich"] .leinwand {
|
||
grid-template-rows: 1fr auto;
|
||
align-content: stretch;
|
||
}
|
||
/* Anordnung „kamera": die Kameras groß, das Video klein in der Ecke.
|
||
|
||
DER BEHAELTER LIEGT AUF DER GANZEN LEINWAND (`inset: 0`) und nicht
|
||
mehr an einem Punkt mit `transform`. Grund: Ein absolut gesetzter
|
||
Behälter mit nur EINER Kante bemisst sich nach seinem Inhalt und
|
||
kann ihn überlaufen -- am 28.09. waren das bei „nur Kamera"
|
||
2175 px in einer 1072 px breiten Leinwand, und ein Gast stand
|
||
komplett außerhalb. Mit `inset: 0` gibt es eine feste Breite, auf
|
||
die sich `max-width` beziehen kann. */
|
||
/* Nur die GRUNDBREITE ist hier eine andere -- der Faktor der Regie
|
||
gilt weiter, und gerechnet wird trotzdem nur an der einen Stelle
|
||
oben. */
|
||
.kino[data-layout="kamera"] { --kam-grund: clamp(160px, 30vw, 380px); }
|
||
.kino[data-layout="kamera"] .kamera {
|
||
width: var(--kam);
|
||
flex: 0 1 auto;
|
||
min-width: 0;
|
||
max-width: calc(50% - 8px);
|
||
}
|
||
.kino[data-layout="kamera"] .kameras {
|
||
inset: 0;
|
||
width: auto; max-width: none;
|
||
transform: none;
|
||
flex-direction: row;
|
||
justify-content: center; align-items: center;
|
||
gap: 14px; padding: 16px;
|
||
}
|
||
.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;
|
||
}
|
||
|
||
/* ==== WEGLASSEN IST KEINE ANORDNUNG MEHR, SONDERN EINE ANDERE FRAGE
|
||
|
||
Filipe: „nur mein bild, nur das video, möglichkeit zwischen allem
|
||
zu wechseln so wie ich will."
|
||
|
||
Die drei oben verschieben Größenverhältnisse. Diese zwei nehmen
|
||
etwas GANZ weg — und dafür gibt es einen sehr praktischen Grund:
|
||
In OBS liegt Filipes Kamera ohnehin als eigene Quelle (schärfer,
|
||
frei zu schieben). Die Bühnenseite soll dann nur noch das Video
|
||
zeigen, sonst steht sein Gesicht zweimal im Bild. Umgekehrt beim
|
||
Reden zwischen zwei Videos: Dann soll das stehengebliebene
|
||
YouTube-Bild verschwinden und nicht nur kleiner werden.
|
||
|
||
`display: none` UND NICHT `opacity: 0`. Ein unsichtbares
|
||
Videofenster spielt weiter, verbraucht Rechenzeit und — der
|
||
eigentliche Punkt — hält bei einem `iframe` den Ton. Man hörte
|
||
dann ein Video, das niemand sieht. */
|
||
.kino[data-layout="nur_video"] .kameras { display: none; }
|
||
.kino[data-layout="nur_kamera"] .leinwand__video { display: none; }
|
||
.kino[data-layout="nur_kamera"] .leinwand__warte { display: none; }
|
||
/* Die Kameras füllen die ganze Leinwand, nebeneinander und gleich
|
||
groß.
|
||
|
||
==== WARUM `absolute` UND `flex: 1 1 0` UND NICHT DAS NAHELIEGENDE
|
||
|
||
Der erste Versuch war `position: static; width: 100%; height: 100%`
|
||
und an den Fenstern `height: 100%; aspect-ratio: 4/3;
|
||
max-width: calc(50% - 8px)`. Klingt richtig. GEMESSEN war der
|
||
Behälter dann 2175 px breit in einer 1072 px breiten Leinwand, und
|
||
von zwei Gästen stand nur einer im Bild — der zweite lag komplett
|
||
außerhalb, hinter `overflow: hidden`.
|
||
|
||
Zwei Fehler auf einmal, und beide sind lehrreich:
|
||
|
||
1. `.leinwand` ist ein Raster mit einer Spalte nach Inhaltsbreite.
|
||
Ein im Fluss stehendes Kind, das zu breit wird, ZIEHT DIE SPALTE
|
||
MIT — und `width: 100%` bezieht sich danach auf die gewachsene
|
||
Spalte. Die Begrenzung wuchs also mit dem, was sie begrenzen
|
||
sollte. `position: absolute; inset: 0` nimmt das Kind aus dem
|
||
Fluss: Es kann das Raster nicht mehr aufziehen.
|
||
|
||
2. `max-width: calc(50% - 8px)` rechnete gegen denselben
|
||
gewachsenen Behälter und war damit wirkungslos.
|
||
|
||
`flex: 1 1 0` mit `min-width: 0` kann gar nicht überlaufen: Jedes
|
||
Fenster bekommt denselben Anteil des vorhandenen Platzes, bei
|
||
einem Gesicht alles, bei zweien die Hälfte. Das feste 4:3 fällt
|
||
dafür weg — das Bild darin steht auf `object-fit: cover` und füllt
|
||
den Rahmen, egal wie er steht. Eine Regel, die nicht rechnet,
|
||
kann sich nicht verrechnen. */
|
||
.kino[data-layout="nur_kamera"] .kameras {
|
||
position: absolute; inset: 0;
|
||
/* DER DECKEL MUSS HIER WEG. `.kameras` trägt seit dem 28.09. ein
|
||
`max-width: 46%` — richtig für „Video groß", wo ein Fenster
|
||
sonst bei doppelter Größe das halbe Video zudeckt. Hier füllen
|
||
die Kameras die ganze Leinwand, und der Deckel machte daraus
|
||
493 px in einer 1072 px breiten Leinwand. Gefunden hat das nicht
|
||
das Auge, sondern die Messung, die die Breite mit „Video groß"
|
||
vergleicht: 208 px gegen 225 px, wo ein Vielfaches stehen müsste.
|
||
Die Breite kommt aus `inset: 0`, nicht aus `width` — sonst
|
||
stünden wieder zwei Angaben für dieselbe Kante da. */
|
||
width: auto; height: auto; max-width: none;
|
||
flex-direction: row;
|
||
justify-content: center; align-items: stretch;
|
||
gap: 12px;
|
||
padding: 16px;
|
||
background: #050408;
|
||
}
|
||
.kino[data-layout="nur_kamera"] .kamera {
|
||
flex: 1 1 0;
|
||
min-width: 0;
|
||
width: auto; height: auto;
|
||
aspect-ratio: auto;
|
||
max-width: none;
|
||
}
|
||
|
||
/* ---- 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; }
|
||
|
||
/* ==== WER SPRICHT ==================================================
|
||
|
||
Filipe: „die modis, linke hand und rechte hand soll im chat extra
|
||
aussehen."
|
||
|
||
EIN WORT UND NICHT NUR EINE FARBE. Rund acht Prozent der Männer
|
||
unterscheiden Rot und Grün schlecht -- und genau hier hängt an der
|
||
Unterscheidung etwas: Ist das jemand vom Team oder irgendwer? Eine
|
||
Auskunft, die nur in der Farbe steckt, ist für sie keine.
|
||
|
||
KLEIN, ABER NICHT ZU KLEIN. 11,5 px ist die Untergrenze des
|
||
Hauses; .72rem sind 11,52 px. Darunter wird aus einer Auskunft
|
||
eine Andeutung.
|
||
|
||
UND NICHT GRELL. Der Chat steht neben einem laufenden Video.
|
||
Alles, was hier selbst leuchtet, zieht den Blick vom Bild weg --
|
||
deshalb gedeckte Töne auf einer sehr schwachen Fläche, kein
|
||
Vollton. */
|
||
.beitrag__rolle {
|
||
font-size: .72rem;
|
||
font-weight: 800;
|
||
letter-spacing: .06em;
|
||
text-transform: uppercase;
|
||
padding: 1px 7px 2px;
|
||
border-radius: 999px;
|
||
border: 1px solid transparent;
|
||
white-space: nowrap;
|
||
line-height: 1.5;
|
||
}
|
||
.beitrag__rolle[data-rolle="dogi"] {
|
||
color: var(--an-hell);
|
||
background: rgba(216, 64, 74, .16);
|
||
border-color: rgba(216, 64, 74, .34);
|
||
}
|
||
.beitrag__rolle[data-rolle="team"] {
|
||
color: #9ab7ff;
|
||
background: rgba(122, 156, 235, .14);
|
||
border-color: rgba(122, 156, 235, .30);
|
||
}
|
||
.beitrag__rolle[data-rolle="modi"] {
|
||
color: #86cdb2;
|
||
background: rgba(96, 175, 145, .14);
|
||
border-color: rgba(96, 175, 145, .30);
|
||
}
|
||
|
||
/* ---- Der Name als Angriffspunkt der Moderation -------------------
|
||
Er sieht aus wie der Name daneben und verrät sich nur beim
|
||
Darüberfahren. Ein Knopf, der wie ein Knopf aussieht, stünde in
|
||
jeder Zeile des Chats und würde ihn unruhig machen -- und die
|
||
Moderation weiß ohnehin, dass sie ihn hat. */
|
||
.beitrag__name {
|
||
appearance: none;
|
||
border: 0; background: none; padding: 0;
|
||
font: inherit; color: inherit;
|
||
letter-spacing: inherit;
|
||
cursor: pointer;
|
||
border-bottom: 1px dotted rgba(170, 180, 210, .34);
|
||
}
|
||
.beitrag__name:hover,
|
||
.beitrag__name:focus-visible { color: var(--schrift); border-bottom-color: currentColor; }
|
||
|
||
.beitrag__melden {
|
||
margin-left: auto;
|
||
appearance: none; border: 0; background: none;
|
||
color: rgba(169, 163, 189, .55);
|
||
cursor: pointer; padding: 2px 4px; border-radius: 6px;
|
||
font-size: .72rem;
|
||
}
|
||
.beitrag__melden:hover { color: var(--gleich); background: rgba(224, 161, 58, .12); }
|
||
.beitrag__melden:disabled { color: var(--gleich); cursor: default; opacity: .8; }
|
||
/* Stehen „weg" und „melden" zusammen, schiebt nur das erste. */
|
||
.beitrag__weg ~ .beitrag__melden { margin-left: 0; }
|
||
|
||
/* ---- Das Menü am Namen -------------------------------------------
|
||
Es liegt ÜBER dem Chat und schiebt ihn nicht auseinander. Ein
|
||
Menü, das die Liste aufklappt, verschiebt alle Beiträge darunter --
|
||
und im Live liest man gerade weiter. */
|
||
/* Lage und Groesse setzt das Skript -- siehe `menueHinstellen()`.
|
||
Hier steht nur, WIE es aussieht, nicht WO es liegt. */
|
||
.modmenue {
|
||
position: fixed;
|
||
z-index: 400;
|
||
overflow-y: auto;
|
||
min-width: 13.5rem;
|
||
max-width: min(20rem, 78vw);
|
||
display: grid;
|
||
padding: 5px;
|
||
border-radius: 12px;
|
||
background: #100e18;
|
||
border: 1px solid var(--rand-hell);
|
||
box-shadow: 0 14px 34px rgba(0, 0, 0, .55);
|
||
}
|
||
.modmenue--liste {
|
||
min-width: 17rem;
|
||
gap: 4px;
|
||
}
|
||
.modmenue__knopf {
|
||
appearance: none; border: 0; background: none;
|
||
display: block; width: 100%;
|
||
text-align: left;
|
||
/* 44 px hoch. Das ist keine Formsache: Hier wird jemand stumm
|
||
geschaltet, und ein Fehlgriff trifft den Falschen. */
|
||
min-height: 44px;
|
||
padding: 10px 12px;
|
||
border-radius: 9px;
|
||
font: inherit; font-size: .84rem; font-weight: 600;
|
||
color: var(--schrift);
|
||
cursor: pointer;
|
||
text-decoration: none;
|
||
}
|
||
.modmenue__knopf:hover,
|
||
.modmenue__knopf:focus-visible { background: rgba(255, 255, 255, .07); }
|
||
.modmenue__knopf--weg { color: var(--schrift-leise); font-weight: 500; }
|
||
|
||
.modmeldung {
|
||
display: grid; gap: 3px;
|
||
padding: 9px 10px;
|
||
border-radius: 10px;
|
||
background: rgba(255, 255, 255, .035);
|
||
border: 1px solid var(--rand);
|
||
}
|
||
.modmeldung__wer {
|
||
font-size: .72rem; font-weight: 800;
|
||
letter-spacing: .02em; color: var(--schrift-leise);
|
||
}
|
||
.modmeldung__text {
|
||
font-size: .84rem; line-height: 1.4; color: var(--schrift);
|
||
overflow-wrap: anywhere;
|
||
}
|
||
.modmeldung__schon { font-size: .72rem; color: var(--zu); }
|
||
.modmeldung__knoepfe { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
|
||
.modmeldung__knoepfe .modmenue__knopf {
|
||
width: auto; flex: 1 1 auto; text-align: center;
|
||
font-size: .78rem; padding: 10px 9px;
|
||
}
|
||
|
||
/* ---- Die Zahl im Kopf der Schiene --------------------------------
|
||
Sie steht nur da, wenn etwas offen ist. In Gold und nicht in Rot:
|
||
Rot gehört in diesem Haus dem Senden, und eine zweite rote Fläche
|
||
daneben würde beides entwerten. */
|
||
.schiene__meldungen {
|
||
appearance: none;
|
||
font-size: .72rem; font-weight: 800;
|
||
letter-spacing: .04em;
|
||
padding: 4px 10px 5px;
|
||
min-height: 28px;
|
||
border-radius: 999px;
|
||
background: rgba(224, 161, 58, .16);
|
||
border: 1px solid rgba(224, 161, 58, .38);
|
||
color: var(--gleich);
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
}
|
||
.schiene__meldungen:hover { background: rgba(224, 161, 58, .26); }
|
||
.schiene__meldungen[hidden] { display: none; }
|
||
|
||
/* ==== WER MIT DEM FINGER MODERIERT =================================
|
||
|
||
Nicht die Bildschirmbreite fragt hier, sondern womit jemand tippt:
|
||
Ein Tablet ist 1024 px breit und wird trotzdem mit dem Finger
|
||
bedient.
|
||
|
||
DIE ZWEI ZEICHEN AM BEITRAG WERDEN NICHT GROESSER, SIE BEKOMMEN
|
||
EINE FLAECHE. Ein 44 px hoher Knopf in jeder Chatzeile würde die
|
||
Schiene aufblähen und den Chat unlesbar machen; eine unsichtbare
|
||
Fläche darum herum kostet nichts und trifft genauso.
|
||
Nachgerechnet: 20 px hoch plus zweimal 12 px sind 44. */
|
||
@media (pointer: coarse) {
|
||
.schiene__meldungen { min-height: 44px; }
|
||
.beitrag__weg, .beitrag__melden { position: relative; }
|
||
.beitrag__weg::after, .beitrag__melden::after {
|
||
content: ''; position: absolute; inset: -12px;
|
||
}
|
||
/* Der Name ist der Angriffspunkt der Moderation -- und in einer
|
||
Chatzeile das kleinste Ziel überhaupt. */
|
||
.beitrag__name { position: relative; }
|
||
.beitrag__name::after { content: ''; position: absolute; inset: -12px -6px; }
|
||
}
|
||
|
||
/* ---- Aus der Sendung ---------------------------------------------
|
||
Eine ganze Fläche und kein Hinweisstreifen. Wer rausgenommen ist,
|
||
soll nicht daneben weiter zusehen -- und soll auch nicht raten, ob
|
||
gerade die Technik hakt. */
|
||
.raus {
|
||
position: fixed; inset: 0; z-index: 900;
|
||
display: grid; align-content: center; justify-items: center;
|
||
gap: 10px;
|
||
padding: 28px 24px;
|
||
text-align: center;
|
||
background: #050408;
|
||
}
|
||
.raus__titel {
|
||
margin: 0;
|
||
font-size: 1.24rem; font-weight: 800;
|
||
color: var(--schrift);
|
||
}
|
||
.raus__text {
|
||
margin: 0; max-width: 34rem;
|
||
font-size: .95rem; line-height: 1.6;
|
||
color: var(--schrift-leise);
|
||
}
|
||
|
||
.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; }
|
||
|
||
/* =====================================================================
|
||
DAS GEBEN-FELD
|
||
|
||
Vier Betraege statt eines Links. Ein Tipp oeffnet PayPal mit schon
|
||
eingetragener Summe; danach fragt das Feld EINMAL nach, ob es
|
||
geklappt hat -- mehr koennen wir von hier aus nicht wissen.
|
||
|
||
ES IST GRUEN UND ES BLEIBT GRUEN. Das ist die einzige Stelle im
|
||
ganzen Saal mit dieser Farbe: Rot heisst „auf Sendung", Bernstein
|
||
heisst „gleich", und was hier steht, ist weder das eine noch das
|
||
andere -- es ist das Einzige, was Geld betrifft.
|
||
===================================================================== */
|
||
.geben {
|
||
display: grid; gap: 8px;
|
||
margin: 0 14px 14px;
|
||
padding: 12px;
|
||
border-radius: 14px;
|
||
background: linear-gradient(180deg, rgba(125, 226, 168, .14), rgba(71, 201, 127, .07));
|
||
border: 1px solid rgba(125, 226, 168, .3);
|
||
}
|
||
.geben__kopf {
|
||
display: flex; align-items: center; gap: 8px;
|
||
font-size: .82rem; font-weight: 800;
|
||
color: #9ff0c2;
|
||
}
|
||
.geben__kopf svg { width: 17px; height: 17px; fill: currentColor; flex: none; }
|
||
|
||
.geben__betraege { display: flex; gap: 6px; flex-wrap: wrap; }
|
||
/* Auf dem Knopf darf die Muenze deutlich groesser sein als in einer
|
||
Textzeile: Hier ist sie das Erkennungszeichen und nicht die
|
||
Einheit hinter einer Zahl. */
|
||
.geben__betrag .dogen__zeichen { width: 1.6em; height: 1.6em; }
|
||
.geben__betrag {
|
||
/* Breiter als vorher: Auf dem Knopf steht jetzt ein Zeichen neben
|
||
der Zahl, und „0,2" mit Muenze braucht mehr Platz als „2 €".
|
||
Zwei passen weiter nebeneinander, vier brechen auf zwei Reihen
|
||
um -- das entscheidet `flex-wrap` und nicht eine Zahl, die man
|
||
beim naechsten Knopf vergisst. */
|
||
flex: 1 1 5.6rem;
|
||
min-height: 44px;
|
||
display: grid; place-items: center;
|
||
border-radius: 11px;
|
||
text-decoration: none;
|
||
font-size: .92rem; font-weight: 800;
|
||
color: #0a2a1c;
|
||
background: linear-gradient(180deg, #7de2a8, #47c97f);
|
||
box-shadow: 0 10px 22px -14px #47c97f;
|
||
}
|
||
/* ==== DER PREIS AM KAUFKNOPF ======================================
|
||
Filipe: „die leute sollen nur sehen was dogen kosten. sonst wissen
|
||
die ja nicht wie viel es kosten wird."
|
||
|
||
Klein und ruhig UNTER der Dogenzahl. Die Dogen sind die Waehrung
|
||
des Hauses, der Preis ist die Auskunft dazu -- andersherum waere
|
||
es ein Geldknopf mit Dogen als Beiwerk. Die Farbe ist dieselbe wie
|
||
der Knopftext, nur schwaecher: Ein zweiter Farbton auf einem Knopf
|
||
von 44 Pixeln ist einer zu viel. */
|
||
.geben__preis {
|
||
display: block;
|
||
margin-top: 1px;
|
||
font-size: .72rem; font-weight: 700;
|
||
font-variant-numeric: tabular-nums;
|
||
opacity: .62;
|
||
}
|
||
|
||
/* ==== UND DIE UMRECHNUNG FUER DIE LEITUNG =========================
|
||
Filipe: „damit ich auch immer weiss was es ist. aber nur ich."
|
||
|
||
Sie steht ueberall, wo er eine Dogenzahl EINTRAEGT oder PRUEFT --
|
||
an der Stufenleiter, beim Eintragen, in den Listen. Immer leise:
|
||
Sie ist die Nebenauskunft, nicht die Zahl, um die es geht.
|
||
|
||
Es gibt sie nur, wenn der Server den Kurs mitgeschickt hat -- und
|
||
den bekommt nur die Leitung. Ein Zuschauer sieht diese Klasse nie,
|
||
weil die Zeichenkette leer bleibt und `if (preis)` sie gar nicht
|
||
erst anlegt. */
|
||
.preis {
|
||
font-size: .72rem; font-weight: 600;
|
||
font-variant-numeric: tabular-nums;
|
||
color: var(--schrift-leise);
|
||
letter-spacing: 0; text-transform: none;
|
||
}
|
||
.preis--unter { display: block; margin-top: 1px; }
|
||
|
||
.geben__frei {
|
||
justify-self: start;
|
||
min-height: 34px; display: inline-flex; align-items: center;
|
||
font-size: .76rem; color: #9ff0c2;
|
||
text-decoration: underline; text-underline-offset: 3px;
|
||
}
|
||
|
||
/* Die eine Frage danach. Sie erscheint erst, wenn jemand einen
|
||
Betrag angetippt hat -- vorher waere sie eine Frage auf etwas,
|
||
das nicht passiert ist. */
|
||
.geben__nach { display: grid; gap: 7px; }
|
||
.geben__frage { margin: 0; font-size: .78rem; color: #e9e6f2; }
|
||
|
||
/* ==== WAS DIE LEUTE SELBST SCHREIBEN ===============================
|
||
|
||
Filipe: „der text der dazu erscheint sollen die leute selber
|
||
schreiben koennen ... es sollen personalisierte texte sein von den
|
||
leuten selbst."
|
||
|
||
Zwei kleine Felder, und beide sind freiwillig. Sie stehen im
|
||
gruenen Kasten und nicht in einem eigenen -- wer gerade gespendet
|
||
hat, soll nicht das Gefuehl haben, jetzt komme noch ein Formular. */
|
||
.geben__feld { display: grid; gap: 4px; }
|
||
.geben__feld > span {
|
||
display: flex; justify-content: space-between; align-items: baseline;
|
||
gap: 8px;
|
||
font-size: .72rem; font-weight: 700;
|
||
color: #9ff0c2; letter-spacing: .03em;
|
||
}
|
||
.geben__feld input, .geben__feld textarea {
|
||
min-height: 40px; padding: 9px 11px;
|
||
border-radius: 11px;
|
||
border: 1px solid rgba(125, 226, 168, .3);
|
||
background: rgba(0, 0, 0, .3);
|
||
color: var(--schrift); font: inherit; font-size: .84rem;
|
||
min-width: 0; width: 100%; box-sizing: border-box;
|
||
}
|
||
.geben__feld textarea { resize: vertical; line-height: 1.4; }
|
||
.geben__feld input:focus-visible, .geben__feld textarea:focus-visible {
|
||
outline: 2px solid rgba(125, 226, 168, .6); outline-offset: 1px;
|
||
}
|
||
/* Der Zaehler steht erst da, wenn es eng wird -- ein Zaehler, der
|
||
von Anfang an mitlaeuft, macht aus einem Gruss eine Aufgabe. */
|
||
/* .72rem und nicht .7rem: 11,52 px ist die Untergrenze des Hauses,
|
||
11,2 waere darunter. Die Zahl ist nicht Geschmack -- sie steht in
|
||
`pruef-css-klassen`, und genau dort ist diese Zeile aufgefallen. */
|
||
.geben__rest { font-size: .72rem; font-weight: 600; opacity: .7; }
|
||
.geben__rest[data-eng="ja"] { color: var(--gleich); opacity: 1; }
|
||
|
||
/* Der eigene Stand. Er steht nur da, wenn er nicht null ist. */
|
||
.geben__stand {
|
||
margin: 0;
|
||
display: flex; align-items: center; gap: .4em;
|
||
font-size: .78rem; color: #9ff0c2;
|
||
}
|
||
.geben__nach-knoepfe { display: flex; gap: 6px; }
|
||
.geben__melden, .geben__abbruch {
|
||
appearance: none; cursor: pointer;
|
||
flex: 1 1 auto; min-height: 40px; padding: 0 12px;
|
||
border-radius: 11px; font-size: .8rem; font-weight: 700;
|
||
}
|
||
.geben__melden {
|
||
border: 1px solid rgba(125, 226, 168, .5);
|
||
background: rgba(125, 226, 168, .18);
|
||
color: #9ff0c2;
|
||
}
|
||
.geben__abbruch {
|
||
flex: 0 1 auto;
|
||
border: 1px solid var(--rand);
|
||
background: none;
|
||
color: var(--schrift-leise);
|
||
}
|
||
.geben__danke { margin: 0; font-size: .78rem; color: #9ff0c2; }
|
||
|
||
/* ---- Die Spendenliste im Pult --------------------------------------- */
|
||
.spendenliste { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
|
||
.spendenzeile {
|
||
display: flex; align-items: center; gap: 10px;
|
||
padding: 8px 10px;
|
||
border-radius: 11px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .03);
|
||
}
|
||
.spendenliste--still .spendenzeile { background: none; border-color: transparent; }
|
||
.spendenzeile__betrag {
|
||
flex: none; min-width: 4.4rem;
|
||
font-size: .98rem; font-weight: 900;
|
||
font-variant-numeric: tabular-nums;
|
||
color: #9ff0c2;
|
||
}
|
||
.spendenzeile__mitte { flex: 1 1 6rem; min-width: 0; display: grid; gap: 4px; }
|
||
|
||
/* ==== DIE SCHRANKE VOR DEM STREAM ==================================
|
||
Name und Text sind hier FELDER und keine Beschriftung: Der Text
|
||
kommt seit dem 28.09. von dem, der gibt, und die Leitung sieht ihn
|
||
kurz bevor er im Livestream steht. Ohne die Moeglichkeit, ein Wort
|
||
zu aendern, bliebe nur „ganz ablehnen" -- und dann faellt wegen
|
||
eines Wortes eine echte Spende unter den Tisch. */
|
||
.spendenzeile__feld {
|
||
min-height: 34px; padding: 5px 9px;
|
||
border-radius: 9px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(0, 0, 0, .3);
|
||
color: var(--schrift); font: inherit; font-size: .82rem;
|
||
min-width: 0; width: 100%; box-sizing: border-box;
|
||
}
|
||
.spendenzeile__feld--gruss { font-size: .76rem; color: var(--schrift-leise); }
|
||
.spendenzeile__feld:focus-visible {
|
||
outline: 2px solid var(--rand-hell); outline-offset: 1px;
|
||
}
|
||
.spendenzeile__wer {
|
||
font-size: .84rem; color: var(--schrift);
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
}
|
||
.spendenzeile__gruss {
|
||
font-size: .74rem; color: var(--schrift-leise);
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
}
|
||
.spendenzeile__ja, .spendenzeile__nein, .spendenzeile__nochmal {
|
||
appearance: none; cursor: pointer; flex: none;
|
||
min-height: 36px; padding: 0 11px;
|
||
border-radius: 9px;
|
||
font-size: .76rem; font-weight: 700;
|
||
}
|
||
.spendenzeile__ja {
|
||
border: 1px solid rgba(125, 226, 168, .45);
|
||
background: rgba(125, 226, 168, .16);
|
||
color: #9ff0c2;
|
||
}
|
||
.spendenzeile__nein, .spendenzeile__nochmal {
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .04);
|
||
color: var(--schrift-leise);
|
||
}
|
||
.spendenliste__leer {
|
||
padding: 10px 2px;
|
||
font-size: .78rem; color: var(--schrift-leise);
|
||
}
|
||
|
||
/* ==== WER WIE VIELE DOGEN HAT ======================================
|
||
|
||
Filipe: „ich will dass die den leuten auch als punkte hinzugefuegt
|
||
werden."
|
||
|
||
NUR IM PULT. Oeffentlich waere das eine Rangliste darueber, wer wie
|
||
viel gibt -- und wer wenig geben kann, staende jeden Abend darin.
|
||
Sie ist absichtlich ruhig gestaltet: eine Auskunft, kein
|
||
Siegertreppchen. */
|
||
.dogenliste {
|
||
list-style: none; margin: 0; padding: 0;
|
||
display: grid; gap: 4px;
|
||
}
|
||
.dogenzeile {
|
||
display: flex; align-items: center; gap: 10px;
|
||
padding: 6px 10px;
|
||
border-radius: 9px;
|
||
background: rgba(255, 255, 255, .03);
|
||
}
|
||
.dogenzeile__wer {
|
||
flex: 1 1 auto; min-width: 0;
|
||
font-size: .82rem; color: var(--schrift);
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
}
|
||
.dogenzeile__wert {
|
||
flex: none;
|
||
font-size: .92rem; font-weight: 800;
|
||
color: #9ff0c2;
|
||
}
|
||
|
||
|
||
/* =====================================================================
|
||
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. */
|
||
/* DIE ZEILEN DES SAALS STEHEN GANZ OBEN, BEI `.saal` -- und nur
|
||
dort. Hier stand bis zum 28.09.2026 eine zweite Angabe
|
||
(`minmax(0, 1fr) auto`), aus der Zeit, als der Saal zwei Zeilen
|
||
hatte. Sie stand SPAETER in der Datei und gewann damit gegen die
|
||
dreizeilige oben: Die Regieleiste landete in der `1fr`-Zeile,
|
||
bekam null Pixel, und ihre Register ragten ueber das Video.
|
||
|
||
Gemessen war das `0px 491px 340px` -- und im Quelltext oben stand
|
||
die ganze Zeit die richtige Angabe. Zwei Regeln, die dieselbe
|
||
Frage beantworten, sind keine Sicherheit, sondern die Garantie,
|
||
dass eine davon irgendwann falsch ist. */
|
||
|
||
.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. */
|
||
/* 17rem SEIT DEM 28.09., VORHER 19. Die Register sind aus diesem
|
||
Teil heraus nach oben gewandert; sie waren hier rund 47 Pixel
|
||
hoch. Die Sendungs-Tafel misst 264 Pixel und passt damit
|
||
weiterhin ohne Rollen hinein — die 32 Pixel Unterschied gehen
|
||
an das Bild zurück. */
|
||
max-height: min(40dvh, 17rem);
|
||
overflow-y: auto;
|
||
}
|
||
/* EINE SPALTE, DIE BIS AUF NULL SCHRUMPFEN DARF.
|
||
|
||
`grid-template-columns` steht hier ausdruecklich, obwohl es nur
|
||
eine Spalte gibt. Der Grund: Die Vorgabe waere `auto`, und eine
|
||
`auto`-Spalte richtet sich nach dem unteilbarsten Inhalt -- also
|
||
genau das, was in der schmalen Regiespalte die waagerechte
|
||
Rollleiste erzeugt hat. `minmax(0, 1fr)` sagt stattdessen: nimm
|
||
die Breite, die da ist, und bring den Inhalt darin unter.
|
||
|
||
ACHTUNG BEIM LESEN: `overflow-y: auto` allein reicht, damit der
|
||
Browser AUCH waagerecht rollt. Steht eine Achse auf `auto` und
|
||
die andere auf `visible`, macht er aus der `visible` ebenfalls
|
||
`auto` -- es gibt in dieser Datei also gar kein `overflow-x`,
|
||
und die Rollleiste war trotzdem da. Deshalb ist die Reparatur
|
||
hier, beim Platz, und nicht bei einem `overflow-x: hidden`:
|
||
Letzteres haette den Text still abgeschnitten, statt ihn
|
||
umbrechen zu lassen. */
|
||
.pult[data-auf="ja"] .pult__innen { display: grid; grid-template-columns: minmax(0, 1fr); }
|
||
|
||
/* ---- Die Register -----------------------------------------------------
|
||
|
||
SIE BRECHEN UM. SEIT DEM 28.09.2026.
|
||
|
||
Vorher rollten sie waagerecht, mit einer Begründung, die für sich
|
||
genommen stimmte: Sieben Register in zwei Zeilen kosten oben rund
|
||
45 Pixel, und zwar dem Video, um das es geht. Waagerecht rollen
|
||
kostet null.
|
||
|
||
Filipe hat das entschieden, und seine Entscheidung ist die
|
||
richtige: „ich will niemals irgendwas nach links oder rechts
|
||
swippen müssen." Waagerecht rollen kostet eben NICHT null --
|
||
es kostet die Gewissheit, alles gesehen zu haben. Auf einem
|
||
412-Pixel-Handy standen von 605 Pixeln Registern 193 rechts
|
||
ausserhalb; dass es „Gestaltung" und „Spenden" überhaupt gibt,
|
||
erfuhr man nur, wenn man auf Verdacht wischte. Ein Register, das
|
||
man nicht sieht, gibt es nicht.
|
||
|
||
GEMESSEN: Mit Umbruch stehen auf 412 px zwei Zeilen (rund 45 px
|
||
mehr), auf 360 px drei. Das ist der Preis, und er ist richtig
|
||
bezahlt -- umgekehrt gab es dafür null Gewissheit.
|
||
|
||
`flex-wrap: wrap` ist dabei eine Regel, die MISST: Sie bricht
|
||
genau dann um, wenn der Platz nicht reicht, und bei einem
|
||
achten Register von selbst eine Zeile später. Eine feste
|
||
Schwelle („ab 500 px umbrechen") wäre beim nächsten Register
|
||
still falsch. */
|
||
.reiter {
|
||
position: relative;
|
||
display: flex; gap: 4px; flex-wrap: wrap;
|
||
padding: 5px 10px 6px;
|
||
min-width: 0;
|
||
}
|
||
.reiter__knopf {
|
||
appearance: none; cursor: pointer;
|
||
position: relative;
|
||
display: inline-flex; align-items: center; gap: 7px;
|
||
/* 44 PX UND NICHT MEHR 38. In der Schublade war das ein Reiter
|
||
unter vielen; oben am Rand ist es das Erste, wonach ein Daumen
|
||
greift. Die Hausgröße für Fingerziele ist 44. */
|
||
min-height: 44px; padding: 0 15px;
|
||
flex: none;
|
||
scroll-snap-align: center;
|
||
border: 0; border-radius: 11px;
|
||
background: none;
|
||
color: var(--schrift-leise);
|
||
font-size: .82rem; font-weight: 700;
|
||
white-space: nowrap;
|
||
transition: color .16s ease, background-color .16s ease;
|
||
}
|
||
.reiter__knopf:hover { color: var(--schrift); }
|
||
/* DIE FLAECHE MACHT DIE MARKE, DIE FARBE MACHT DER KNOPF.
|
||
Zwei Anzeigen für dieselbe Sache -- aber nur eine davon rechnet.
|
||
Vorher trugen beide eine Füllung, und die feste verdeckte die
|
||
gleitende. */
|
||
.reiter__knopf[aria-selected="true"] {
|
||
color: #fff;
|
||
letter-spacing: .01em;
|
||
}
|
||
|
||
/* ---- Die gleitende Marke ----------------------------------------------
|
||
Sie liegt IN der rollenden Leiste, nicht darüber — dadurch wandert
|
||
sie beim Rollen von selbst mit, ohne dass jemand nachrechnen muss.
|
||
Ihre Lage setzt das Skript aus dem gemessenen Rechteck des
|
||
gewählten Knopfes.
|
||
|
||
UND SIE IST NICHT DIE EINZIGE ANZEIGE. Die Pille darunter bleibt
|
||
gefüllt. Sollte die Marke je aus dem Tritt geraten — Schrift lädt
|
||
nach, jemand zieht das Fenster —, ist die Auswahl trotzdem zu
|
||
sehen. Eine Anzeige, die rechnet, braucht eine daneben, die es
|
||
nicht tut. */
|
||
.reiter__marke {
|
||
position: absolute;
|
||
left: 0; top: 0;
|
||
width: 0; height: 0;
|
||
z-index: 0;
|
||
border-radius: 11px;
|
||
/* Glas mit Lichtkante oben und Tiefe unten -- dieselbe Sprache
|
||
wie überall im Haus: Was obenauf liegt, bekommt oben Licht. */
|
||
background:
|
||
linear-gradient(180deg, rgba(255, 255, 255, .11), rgba(255, 255, 255, .045));
|
||
box-shadow:
|
||
inset 0 1px 0 rgba(255, 255, 255, .16),
|
||
inset 0 -1px 0 rgba(0, 0, 0, .3),
|
||
0 6px 16px -10px #000;
|
||
transform: translate(0, 0);
|
||
transition:
|
||
transform .3s cubic-bezier(.22, 1, .3, 1),
|
||
width .3s cubic-bezier(.22, 1, .3, 1);
|
||
pointer-events: none;
|
||
}
|
||
/* Der Streifen darunter führt zur Tafel, die gerade offen ist --
|
||
das ist die einzige Farbe in der ganzen Leiste. */
|
||
.reiter__marke::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 12px; right: 12px; bottom: -5px;
|
||
height: 2px;
|
||
border-radius: 2px;
|
||
background: linear-gradient(90deg,
|
||
transparent,
|
||
var(--an-hell) 25%, var(--an-hell) 75%,
|
||
transparent);
|
||
box-shadow: 0 0 10px -1px var(--an-hell);
|
||
}
|
||
/* IST DIE REGIE ZUGEKLAPPT, IST DIE TAFEL NICHT DA -- dann führt
|
||
der Streifen nirgendwohin und wird leise. Eine Auskunft, die
|
||
nichts kostet: Man sieht am Rand, ob unten etwas offen ist. */
|
||
.saal:has(.pult[data-auf="nein"]) .reiter__marke::after { opacity: .28; }
|
||
/* Solange nichts gemessen ist, gibt es sie nicht — eine Marke, die
|
||
bei null anfängt und dann springt, sieht nach Fehler aus. */
|
||
.reiter__marke[hidden] { display: none; }
|
||
.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; }
|
||
|
||
/* `min-width: 0` IST HIER KEINE ZIERDE.
|
||
|
||
Ein Gitterfeld hat von sich aus `min-width: auto` -- es besteht
|
||
also darauf, mindestens so breit zu sein wie sein unteilbarster
|
||
Inhalt. In der 359 Pixel breiten Regiespalte hiess das: die Tafel
|
||
„Gestaltung" bestand auf 572 Pixeln, und `.pult__innen` haengte
|
||
eine waagerechte Rollleiste an. Genau das stand auf Filipes
|
||
Bildschirmfoto vom 28.09.2026.
|
||
|
||
Mit `min-width: 0` darf sie schrumpfen, und alles darin bricht
|
||
um -- untereinander statt nebeneinander. */
|
||
.pult-tafel {
|
||
display: grid; grid-template-columns: minmax(0, 1fr);
|
||
gap: 12px; align-content: start; min-width: 0;
|
||
}
|
||
/* 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.
|
||
--------------------------------------------------------------------- */
|
||
/* =====================================================================
|
||
DER REGIEPLATZ (28.09.2026)
|
||
|
||
Filipe: „kann das nicht bissl aufgeteilt sein auf links und rechts
|
||
und eine barre unten in der mitte. kannst du das nicht hoch
|
||
professionell machen und hochwertig vom aussehen?"
|
||
|
||
---------------------------------------------------------------------
|
||
DIE TEILUNG FOLGT DEM, WAS WANN GEBRAUCHT WIRD
|
||
|
||
LINKS Was läuft. Das liest man, man tippt es nicht.
|
||
RECHTS Was eingetragen wird. Das tippt man VOR der Sendung.
|
||
UNTEN Der Transport. Den fasst man WÄHREND der Sendung an --
|
||
und er liegt deshalb immer an derselben Stelle, über
|
||
die ganze Breite.
|
||
|
||
Vorher stand alles in einem Stapel untereinander, und wer im Live
|
||
an den Play-Knopf wollte, musste an den Eingabefeldern
|
||
vorbeiscrollen. Scrollen ist mitten in einer Sendung ein Griff
|
||
daneben.
|
||
|
||
`minmax(0, 1fr)` UND NICHT `1fr`: Ein langer Videotitel würde die
|
||
Spalte sonst aufziehen, statt abgeschnitten zu werden -- und dann
|
||
läuft die rechte Seite aus dem Pult. Dieselbe Falle wie bei den
|
||
Saalzeilen am selben Tag.
|
||
===================================================================== */
|
||
.regieplatz {
|
||
display: grid;
|
||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||
/* DIE LINKE KACHEL GEHT UEBER BEIDE ZEILEN. Ohne das waere sie so
|
||
hoch wie ihr Inhalt, und daneben staenden zwei -- eine Seite,
|
||
die unten ausfranst. So schliessen beide auf derselben Linie ab. */
|
||
grid-template-areas:
|
||
"laeuft sendung"
|
||
"laeuft bereit";
|
||
gap: 12px;
|
||
align-items: stretch;
|
||
}
|
||
.regiekachel--laeuft { grid-area: laeuft; }
|
||
.regiekachel--sendung { grid-area: sendung; }
|
||
.regiekachel--bereit { grid-area: bereit; }
|
||
|
||
/* ==== EINE KACHEL ==================================================
|
||
|
||
Filipe: „wo rechts links und unten kacheln sind wo alles drin ist,
|
||
schoen verteilt."
|
||
|
||
Rahmen, Kopf, eigener Grund. Vorher standen hier zwei Spalten mit
|
||
einer Trennlinie dazwischen -- das ist eine Teilung, keine
|
||
Gliederung, und ohne Rahmen fehlt genau das, was eine Flaeche
|
||
aufgeraeumt aussehen laesst.
|
||
|
||
AUGENSCHONEND: kein Leuchten, kein harter Kontrast. Der Grund ist
|
||
wenige Prozent heller als die Umgebung; das reicht, damit das Auge
|
||
eine Flaeche sieht, und blendet niemanden, der abends sendet. */
|
||
.regiekachel {
|
||
display: grid; gap: 9px; align-content: start;
|
||
padding: 11px 13px 13px;
|
||
border-radius: 14px;
|
||
border: 1px solid var(--rand);
|
||
background: linear-gradient(180deg, rgba(255, 255, 255, .045), rgba(255, 255, 255, .015));
|
||
min-width: 0;
|
||
}
|
||
.regiekachel__kopf {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
gap: 8px; min-width: 0;
|
||
}
|
||
.regiekachel__ueber {
|
||
margin: 0;
|
||
/* .72rem und nicht weniger: 11,52 px ist die Untergrenze des
|
||
Hauses. Die Zahl ist nicht Geschmack -- sie steht in
|
||
`pruef-css-klassen`. */
|
||
font-size: .72rem; font-weight: 800;
|
||
letter-spacing: .14em; text-transform: uppercase;
|
||
color: var(--schrift-leise);
|
||
}
|
||
/* Zwei Felder nebeneinander, solange Platz ist -- und untereinander,
|
||
sobald keiner mehr da ist. Das entscheidet `wrap` und nicht eine
|
||
Zahl, die man beim naechsten Feld vergisst. */
|
||
.regiekachel__paar { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
|
||
.regiekachel__paar > .pult__feld { flex: 1 1 11rem; }
|
||
|
||
/* ==== DAS VORSCHAUBILD ============================================
|
||
Es ist der Grund, warum die linke Kachel nie leer aussieht. Steht
|
||
noch kein Video da, liegt darin der Satz, der sagt, was zu tun ist
|
||
-- ein leerer Kasten sagt nur, dass etwas fehlt. */
|
||
.laufbild {
|
||
position: relative;
|
||
aspect-ratio: 16 / 9;
|
||
border-radius: 11px;
|
||
overflow: hidden;
|
||
background: #07060d;
|
||
border: 1px solid var(--rand);
|
||
display: grid; place-items: center;
|
||
}
|
||
.laufbild img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||
.laufbild[data-bild="nein"] img { display: none; }
|
||
.laufbild__leer {
|
||
position: absolute;
|
||
padding: 0 16px;
|
||
text-align: center;
|
||
font-size: .78rem; line-height: 1.45;
|
||
color: var(--schrift-leise);
|
||
}
|
||
.laufbild[data-bild="ja"] .laufbild__leer { display: none; }
|
||
|
||
/* ---- Die Transportleiste --------------------------------------------
|
||
Aufgebaut wie jeder Videospieler, den man kennt: Schiene über die
|
||
ganze Breite, darunter eine Reihe mit dem Transport in der MITTE.
|
||
Eine Anordnung, die man schon kennt, muss man nicht lernen.
|
||
|
||
Sie ist die einzige Fläche im Pult mit eigenem Grund -- weil sie
|
||
die einzige ist, die im Live gebraucht wird. */
|
||
.transport {
|
||
display: grid; gap: 10px;
|
||
padding: 12px 14px 13px;
|
||
border-radius: 15px;
|
||
border: 1px solid var(--rand-hell);
|
||
/* ==== SIE KLEBT UNTEN ==========================================
|
||
|
||
GEMESSEN, NICHT VERMUTET: Beim ersten Bau lag die Leiste bei
|
||
y=986 in einem 900 Pixel hohen Fenster -- unter dem Falz. Wer im
|
||
Live an den Play-Knopf wollte, haette also scrollen muessen, und
|
||
genau davon sollte der Umbau wegfuehren. Die Rechnung ging auf
|
||
(links, rechts, Leiste darunter), und das Ergebnis war trotzdem
|
||
falsch.
|
||
|
||
`sticky` loest beides auf einmal: Sie steht unten -- wie Filipe
|
||
es wollte -- und bleibt dabei immer sichtbar. Sie ist die
|
||
LETZTE Zeile des Rasters, also verdeckt sie nichts: Unter ihr
|
||
kommt nichts mehr.
|
||
|
||
Der Grund muss dafuer DICHT sein. Eine halbdurchsichtige Leiste,
|
||
durch die Text scrollt, ist genau die Art Flaeche, auf der man
|
||
sich im Live verliest. */
|
||
/* Er ist seit dem 28.09. eine eigene Zeile UNTER dem Saal und
|
||
nicht mehr das letzte Kind einer rollenden Tafel -- damit
|
||
braucht er kein `sticky` mehr, er steht ohnehin immer unten.
|
||
Ein `sticky`, das nichts mehr klebt, ist eine Regel, die man
|
||
beim naechsten Umbau falsch versteht. */
|
||
z-index: 3;
|
||
background:
|
||
linear-gradient(180deg, rgba(23, 20, 34, .95), rgba(15, 13, 24, .98));
|
||
backdrop-filter: blur(12px) saturate(1.1);
|
||
-webkit-backdrop-filter: blur(12px) saturate(1.1);
|
||
box-shadow: 0 -14px 26px -22px #000, inset 0 1px 0 rgba(255, 255, 255, .06);
|
||
}
|
||
.transport__schiene { display: flex; align-items: center; gap: 12px; }
|
||
.transport__schiene .spur__schiene { flex: 1 1 auto; min-width: 0; }
|
||
.transport__reihe {
|
||
display: grid;
|
||
/* Drei gleich breite Teile -- nur so steht der Transport wirklich
|
||
in der Mitte und nicht dort, wo die Nachbarn gerade Platz
|
||
lassen. */
|
||
grid-template-columns: 1fr auto 1fr;
|
||
align-items: center;
|
||
gap: 10px;
|
||
}
|
||
/* SIE BRECHEN UM. Ohne das ragte die rechte Gruppe auf einem
|
||
390er Handy 76 Pixel ueber beide Kanten hinaus, und „Nächstes"
|
||
war nur mit Wischen zu erreichen -- genau das, was Filipe am
|
||
28.09.2026 abgestellt haben wollte. Die mittlere Gruppe hatte
|
||
`wrap` schon; die beiden aeusseren nicht. */
|
||
.transport__teil {
|
||
display: flex; align-items: center; gap: 8px;
|
||
flex-wrap: wrap; min-width: 0;
|
||
}
|
||
.transport__teil--mitte { justify-content: center; gap: 10px; }
|
||
.transport__teil--rechts { justify-content: flex-end; }
|
||
/* ==== JEDE GRUPPE HAT EINEN NAMEN =================================
|
||
Auf Filipes Bildschirmfoto standen drei kleine Knopfgruppen in
|
||
einem 1400 Pixel breiten Kasten, und dazwischen war Luft. Leere
|
||
zwischen Knoepfen liest sich als „hier fehlt noch etwas". Ein Wort
|
||
davor bindet die Gruppe zusammen und fuellt den Raum mit Auskunft
|
||
statt mit Abstand. */
|
||
/* Die Taste am Knopf -- klein, ruhig, und nie unter 11,5 px: Die
|
||
Untergrenze des Hauses gilt auch fuer eine Nebenauskunft, sonst
|
||
ist sie keine Auskunft. */
|
||
.transport__teil kbd,
|
||
.transport__wort kbd,
|
||
.sender-taste {
|
||
font-size: .72rem; font-weight: 700;
|
||
font-family: inherit;
|
||
padding: 1px 5px;
|
||
border-radius: 5px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .06);
|
||
color: var(--schrift-leise);
|
||
line-height: 1.5;
|
||
}
|
||
.sender-taste { margin-left: 6px; }
|
||
/* Sie steht UNTER dem runden Play-Knopf. `order` statt einer neuen
|
||
Zeile: Die drei Knoepfe bleiben damit in einer Reihe, und die
|
||
Taste haengt darunter, ohne die Mitte zu verschieben. */
|
||
.transport__taste {
|
||
flex-basis: 100%;
|
||
display: flex; justify-content: center;
|
||
margin-top: -2px;
|
||
}
|
||
.transport__teil--mitte { flex-wrap: wrap; }
|
||
|
||
.transport__wort {
|
||
display: inline-flex; align-items: center; gap: 5px;
|
||
flex: none;
|
||
font-size: .72rem; font-weight: 800;
|
||
letter-spacing: .12em; text-transform: uppercase;
|
||
color: var(--schrift-leise);
|
||
}
|
||
|
||
.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__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;
|
||
}
|
||
/* DER PLAY-KNOPF IST DER GROESSTE KNOPF DES HAUSES -- und das ist
|
||
kein Geschmack: Er ist der einzige, den man mitten in einer
|
||
Sendung blind treffen muss. Rund, damit er sich schon in der
|
||
Form von allen anderen unterscheidet. */
|
||
.spur__knopf--gross {
|
||
min-width: 58px; min-height: 58px;
|
||
border-radius: 50%;
|
||
background: rgba(255, 255, 255, .12);
|
||
border-color: var(--rand-hell);
|
||
}
|
||
.spur__knopf--gross:hover { background: rgba(255, 255, 255, .17); }
|
||
.spur__knopf--gross svg { width: 22px; height: 22px; fill: currentColor; }
|
||
.spur__knopf--weiter {
|
||
border-color: rgba(154, 183, 255, .34);
|
||
background: rgba(154, 183, 255, .12);
|
||
color: #cfe0ff;
|
||
}
|
||
/* Der Umschalter zwischen den beiden Videos. In Gold und nicht in
|
||
Blau: „Nächstes" geht vorwärts und ist endgültig, „Wechseln" geht
|
||
hin und her. Zwei Knöpfe nebeneinander, die gleich aussehen und
|
||
Verschiedenes tun, sind im Live ein Griff daneben. */
|
||
.spur__knopf--tausch {
|
||
border-color: rgba(224, 161, 58, .36);
|
||
background: rgba(224, 161, 58, .13);
|
||
color: #f0cf9a;
|
||
/* Er steht seit dem 28.09. in der linken Spalte und nicht mehr in
|
||
einer eigenen Reihe: Dort ist die Breite der Spalte die Grenze,
|
||
nicht eine Zahl, die man beim naechsten Umbau vergisst. */
|
||
max-width: 100%;
|
||
justify-content: flex-start;
|
||
overflow: hidden;
|
||
}
|
||
/* DER TITEL DARF KUERZER WERDEN. `text-overflow: ellipsis` wirkt
|
||
erst, wenn das Kuerzen ueberhaupt erlaubt ist: Als Flex-Kind
|
||
steht das `span` von sich aus auf `min-width: auto` und besteht
|
||
damit auf der vollen Textbreite. Gemessen: 368 Pixel Knopf in
|
||
einem 390 Pixel breiten Fenster. */
|
||
.spur__knopf--tausch span {
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
min-width: 0; flex: 0 1 auto;
|
||
}
|
||
.spur__knopf--tausch[hidden] { display: none; }
|
||
|
||
/* ---- Geschwindigkeit ----
|
||
Eine Reihe kleiner Schalter, kein Schieberegler: Es gibt sechs
|
||
erlaubte Werte, und ein Regler, der zwischen ihnen einrastet, wäre
|
||
eine Bedienung, die etwas vortäuscht, das sie nicht kann.
|
||
|
||
Sie steht LINKS in der Transportleiste und nicht neben dem
|
||
Play-Knopf: Sie wird selten angefasst, und im Live fasst man in
|
||
die Mitte. */
|
||
.tempo { display: flex; gap: 4px; flex-wrap: wrap; }
|
||
.tempo__knopf {
|
||
appearance: none; cursor: pointer;
|
||
min-height: 34px; min-width: 44px; padding: 0 9px;
|
||
border-radius: 9px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .04);
|
||
color: var(--schrift-leise);
|
||
font-size: .76rem; font-weight: 700;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.tempo__knopf[aria-pressed="true"] {
|
||
background: rgba(154, 183, 255, .14);
|
||
border-color: rgba(154, 183, 255, .38);
|
||
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; }
|
||
/* SIE BRICHT UM. Vorher stand sie auf der Vorgabe `nowrap`: Nummer,
|
||
Vorschaubild, Titel und vier Knoepfe in einer starren Reihe, 554
|
||
Pixel breit. In der 359 Pixel schmalen Regiespalte hiess das eine
|
||
waagerechte Rollleiste -- und wer die vier Knoepfe erreichen
|
||
wollte, musste zu ihnen hinwischen.
|
||
|
||
Mit `wrap` rutschen die Knoepfe in eine zweite Zeile, sobald es
|
||
eng wird, und stehen auf dem breiten Bildschirm weiterhin daneben.
|
||
Die Regel MISST also, statt eine Schwelle zu raten. */
|
||
.warte-zeile {
|
||
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
||
min-width: 0;
|
||
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 ------------------------------------------------------- */
|
||
/* ==== DIE STUFENLEITER =============================================
|
||
Eine Zeile je Stufe, alle Felder nebeneinander. Umbrechen statt
|
||
rollen: Am Handy wird aus der Zeile ein Block, und die Regie
|
||
bleibt bedienbar, ohne dass man seitwaerts schieben muss. */
|
||
.stufen { display: grid; gap: 9px; }
|
||
.stufe-zeile {
|
||
display: flex; flex-wrap: wrap; align-items: flex-end; gap: 9px;
|
||
padding: 11px 12px 12px;
|
||
border-radius: 13px;
|
||
background: rgba(255, 255, 255, .035);
|
||
border: 1px solid var(--rand);
|
||
}
|
||
.stufe-feld { display: grid; gap: 3px; min-width: 0; }
|
||
.stufe-feld > span {
|
||
font-size: .72rem; font-weight: 700;
|
||
letter-spacing: .06em; text-transform: uppercase;
|
||
color: var(--schrift-leise);
|
||
}
|
||
.stufe-feld input, .stufe-feld select {
|
||
appearance: none;
|
||
min-height: 44px; padding: 9px 11px;
|
||
border-radius: 10px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .05);
|
||
color: var(--schrift);
|
||
font: inherit; font-size: .84rem;
|
||
min-width: 0;
|
||
}
|
||
.stufe-feld input[type="color"] { width: 56px; padding: 4px; }
|
||
.stufe-ab, .stufe-dauer, .stufe-groesse { width: 5.5rem; }
|
||
.stufe-name { width: 10rem; }
|
||
.stufe-vorlage { width: 7.5rem; }
|
||
|
||
.stufe-bild { display: flex; align-items: center; gap: 7px; }
|
||
.stufe-bild img {
|
||
width: 44px; height: 44px;
|
||
object-fit: contain;
|
||
border-radius: 9px;
|
||
background: rgba(255, 255, 255, .05);
|
||
border: 1px solid var(--rand);
|
||
}
|
||
.stufe-tun {
|
||
appearance: none; cursor: pointer;
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
min-height: 44px; padding: 9px 13px;
|
||
border-radius: 10px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .05);
|
||
color: var(--schrift);
|
||
font: inherit; font-size: .8rem; font-weight: 700;
|
||
white-space: nowrap;
|
||
}
|
||
.stufe-tun:hover { background: rgba(255, 255, 255, .09); }
|
||
.stufe-tun--weg { color: var(--schrift-leise); font-weight: 500; }
|
||
.stufe-tun--weg:hover { color: var(--an-hell); background: rgba(216, 64, 74, .12); }
|
||
.stufe-tun--aus { opacity: .45; cursor: default; }
|
||
|
||
/* ==== DIE DREI MUENZSAETZE =========================================
|
||
|
||
Filipe: „alle drei varianten will ich drauf so dass ich sie
|
||
aussuchen kann wie ich will."
|
||
|
||
Jeder Satz zeigt seine DREI Muenzen nebeneinander, von links nach
|
||
rechts aufsteigend -- der Unterschied zwischen niedrig und hoch
|
||
ist hier die eigentliche Aussage, und den sieht man nur im
|
||
Vergleich.
|
||
|
||
AUGENSCHONEND: Der gewaehlte Satz wird nicht heller, sondern
|
||
bekommt einen ruhigen Rahmen und einen leichten Grund. Ein
|
||
leuchtender Rahmen neben neun glaenzenden Muenzen waere zu viel
|
||
auf einmal. */
|
||
.muenzwahl { display: grid; gap: 8px; }
|
||
.muenzsatz {
|
||
appearance: none; cursor: pointer; text-align: left;
|
||
/* UMBRUCH: Auf 320 Pixeln ragten die drei Muenzen plus ihr Text
|
||
8 Pixel hinaus und die Tafel rollte waagerecht -- genau das,
|
||
was am 28.09. abgestellt wurde. Der Text rutscht jetzt unter
|
||
die Muenzen, statt neben ihnen hinauszulaufen. */
|
||
display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
|
||
padding: 8px 12px;
|
||
border-radius: 13px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .03);
|
||
color: var(--schrift-leise);
|
||
}
|
||
.muenzsatz[aria-pressed="true"] {
|
||
border-color: rgba(154, 183, 255, .45);
|
||
background: rgba(154, 183, 255, .11);
|
||
color: var(--schrift);
|
||
}
|
||
.muenzsatz__reihe { display: flex; gap: 6px; flex: none; }
|
||
.muenzsatz__bild {
|
||
/* GROSS GENUG, UM ZU ENTSCHEIDEN. Bei 40 px sahen „Amethyst" und
|
||
„Neon" auf dem Bildschirmfoto praktisch gleich aus -- und genau
|
||
sie auseinanderzuhalten ist der Zweck dieser Liste. Eine
|
||
Auswahl, in der man den Unterschied nicht sieht, ist keine. */
|
||
width: 56px; height: 56px;
|
||
object-fit: contain;
|
||
filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .5));
|
||
}
|
||
/* Die mittlere und die hohe stehen etwas groesser -- so sieht man
|
||
die Rangfolge, noch bevor man die Bilder erkannt hat. */
|
||
.muenzsatz__bild:nth-child(2) { width: 64px; height: 64px; }
|
||
.muenzsatz__bild:nth-child(3) { width: 72px; height: 72px; }
|
||
.muenzsatz__text { display: grid; gap: 2px; min-width: 0; }
|
||
.muenzsatz__name { font-size: .86rem; font-weight: 800; }
|
||
/* NICHT NUR DIE FARBE SAGT, WAS GEWAEHLT IST. Neben neun glaenzenden
|
||
Muenzen geht ein ruhiger Rahmen unter, und wer Farben schlecht
|
||
unterscheidet, sieht ihn gar nicht. Ein Wort kann man nicht
|
||
uebersehen. Fuer Hilfsmittel steht daneben `aria-pressed`. */
|
||
.muenzsatz[aria-pressed="true"] .muenzsatz__name::after {
|
||
/* Mittelpunkt als Escape — Begründung oben bei „Bildschirm". */
|
||
content: " \00B7\0020gewählt";
|
||
color: #9ab7ff; font-weight: 700;
|
||
}
|
||
.muenzsatz__wort {
|
||
font-size: .72rem; color: var(--schrift-leise);
|
||
overflow: hidden; text-overflow: ellipsis;
|
||
}
|
||
.zeichenwahl__tun { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
|
||
|
||
/* „Noch nicht übernommen" in Gold: Es ist keine Störung, sondern
|
||
eine Erinnerung -- Rot gehört in diesem Haus dem Senden. */
|
||
#stufen-stand[data-offen="ja"] { color: var(--gleich); font-weight: 700; }
|
||
#stufen-stand[data-offen="nein"] { color: var(--schrift-leise); }
|
||
|
||
/* ==== GRÖSSE UND ECKE DER KAMERAFENSTER ============================
|
||
Zwei Gruppen nebeneinander, beide klein — sie stehen unter der
|
||
Anordnung und sind deren Feinjustierung, nicht ihresgleichen. */
|
||
.kamerawahl { display: flex; flex-wrap: wrap; gap: 14px 22px; align-items: flex-start; }
|
||
.kamerawahl__teil { display: grid; gap: 5px; }
|
||
.kamerawahl__wort {
|
||
font-size: .72rem; font-weight: 700;
|
||
letter-spacing: .06em; text-transform: uppercase;
|
||
color: var(--schrift-leise);
|
||
}
|
||
|
||
.kamgroesse { display: flex; gap: 4px; flex-wrap: wrap; }
|
||
.kamgroesse__knopf {
|
||
appearance: none; cursor: pointer;
|
||
min-height: 38px; min-width: 44px; padding: 0 9px;
|
||
border-radius: 9px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .04);
|
||
color: var(--schrift-leise);
|
||
font-size: .76rem; font-weight: 700;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.kamgroesse__knopf[aria-pressed="true"] {
|
||
background: rgba(154, 183, 255, .14);
|
||
border-color: rgba(154, 183, 255, .38);
|
||
color: #cfe0ff;
|
||
}
|
||
|
||
/* ---- Die vier Ecken --------------------------------------------------
|
||
Jeder Knopf ist ein kleines Abbild der Leinwand mit einem Feld in
|
||
der Ecke, die er meint. Ein Wort wäre länger zu lesen, als das
|
||
Bild zu erfassen ist — und vier Wörter nebeneinander passen am
|
||
Handy nicht in eine Zeile.
|
||
Der Name steht trotzdem da: als `aria-label` für Hilfsmittel und
|
||
als Hinweis unter dem Zeiger. */
|
||
.kamecke { display: flex; gap: 6px; }
|
||
.kamecke__knopf {
|
||
appearance: none; cursor: pointer;
|
||
position: relative;
|
||
width: 44px; height: 38px;
|
||
padding: 5px;
|
||
border-radius: 8px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .04);
|
||
}
|
||
.kamecke__feld {
|
||
position: absolute;
|
||
width: 12px; height: 9px;
|
||
border-radius: 2px;
|
||
background: var(--schrift-leise);
|
||
opacity: .5;
|
||
}
|
||
.kamecke__knopf[data-ecke="ol"] .kamecke__feld { top: 5px; left: 5px; }
|
||
.kamecke__knopf[data-ecke="or"] .kamecke__feld { top: 5px; right: 5px; }
|
||
.kamecke__knopf[data-ecke="ul"] .kamecke__feld { bottom: 5px; left: 5px; }
|
||
.kamecke__knopf[data-ecke="ur"] .kamecke__feld { bottom: 5px; right: 5px; }
|
||
.kamecke__knopf[aria-pressed="true"] {
|
||
border-color: rgba(154, 183, 255, .38);
|
||
background: rgba(154, 183, 255, .14);
|
||
}
|
||
.kamecke__knopf[aria-pressed="true"] .kamecke__feld {
|
||
background: #cfe0ff; opacity: 1;
|
||
}
|
||
/* Ein Knopf, der gerade nichts tun kann, sieht auch so aus — und
|
||
der Satz darunter sagt, warum. Gilt für beide Gruppen: die Ecke
|
||
wirkt nur bei „Video groß", die Größe überall außer bei „Nur
|
||
Video", wo es gar keine Kamerafenster gibt. */
|
||
.kamecke__knopf:disabled,
|
||
.kamgroesse__knopf:disabled { opacity: .38; cursor: default; }
|
||
|
||
/* Am Finger werden beide Gruppen auf Hausgröße gehoben.
|
||
`min-height`/`min-width` und nicht `height`/`width` — das ist
|
||
nicht Geschmack: `pruef-tippziele` leitet daraus ab, dass ein
|
||
Element gedeckt ist, und hat den Eckwähler zu Recht gemeldet,
|
||
solange dort nur eine feste Höhe stand. Eine feste Höhe sagt
|
||
„genau so groß"; die Regel will wissen „mindestens so groß". */
|
||
/* Der Teilen-Knopf in der Senderleiste: gedrueckt heisst hier
|
||
„teilt gerade" und nicht „ist aus" -- deshalb leuchtet er, statt
|
||
durchgestrichen zu sein. */
|
||
#s-teilen[aria-pressed="true"] {
|
||
border-color: rgba(125, 226, 168, .5);
|
||
background: rgba(125, 226, 168, .16);
|
||
color: #9ff0c2;
|
||
}
|
||
#s-teilen svg { fill: none; stroke: currentColor; stroke-width: 1.7; }
|
||
.sender-knopf[disabled] { opacity: .4; cursor: default; }
|
||
|
||
@media (pointer: coarse) {
|
||
.kamgroesse__knopf { min-height: 44px; }
|
||
.kamecke__knopf { min-height: 44px; min-width: 52px; height: 44px; width: 52px; }
|
||
/* Am Finger werden auch die Felder in der offenen Spendenliste auf
|
||
Hausgroesse gehoben -- sie werden mitten in einer Sendung
|
||
bedient, oft am Handy. */
|
||
.spendenzeile__feld { min-height: 44px; }
|
||
}
|
||
|
||
.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 ------------------------------------------------------- */
|
||
/* ==== DIE ALTE LEGENDE ============================================
|
||
Sie stand als eigener Absatz am Ende der Regie -- hinter ALLEN
|
||
Registern, also auch unter „Ton" und „Spenden", wo keines ihrer
|
||
Kuerzel etwas tut. Seit dem 28.09. steht jede Taste an dem Knopf,
|
||
den sie bedient. Die Regeln bleiben, weil `kuerzel` auch anderswo
|
||
im Haus vorkommt. */
|
||
.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; grid-template-columns: minmax(0, 1fr);
|
||
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;
|
||
}
|
||
/* ==== DER HAUPTKNOPF EINER ZEILE ===================================
|
||
`knopf-still--haupt` stand schon an „Übernehmen" bei den Stufen --
|
||
und war NIRGENDS gestaltet. Eine Klasse, die kein Stilblatt kennt,
|
||
ist stille Absicht ohne Wirkung: Sie sieht im Quelltext aus, als
|
||
sei etwas hervorgehoben, und auf dem Bildschirm ist es das nicht.
|
||
Gefunden beim Nachsehen, ob es sie gibt, bevor ich sie ein zweites
|
||
Mal benutze.
|
||
|
||
Dieselben Werte wie „Nächstes" in der Transportleiste: Ein Haus,
|
||
in dem die wichtige Handlung zweimal verschieden aussieht, hat
|
||
keine wichtige Handlung. */
|
||
.knopf-still--haupt {
|
||
border-color: rgba(154, 183, 255, .34);
|
||
background: rgba(154, 183, 255, .12);
|
||
color: #cfe0ff;
|
||
}
|
||
|
||
/* Ein Knopf, der gebraucht wird, aber nicht gesucht: leise Farbe,
|
||
und im Live grau. Rot waere er erst, wenn er etwas zerstoeren
|
||
koennte -- er leert nur den Schreibtisch. */
|
||
.knopf-still--leise {
|
||
border-color: var(--rand);
|
||
background: none;
|
||
color: var(--schrift-leise);
|
||
}
|
||
.knopf-still--leise:hover:not([disabled]) {
|
||
color: var(--an-hell);
|
||
border-color: rgba(216, 64, 74, .35);
|
||
background: rgba(216, 64, 74, .1);
|
||
}
|
||
.knopf-still--leise[disabled] { opacity: .4; cursor: default; }
|
||
.pult__zeile--ende { margin-top: 4px; align-items: center; }
|
||
|
||
.pult__feld select {
|
||
min-height: 44px; padding: 0 10px;
|
||
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__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) {
|
||
/* ==== DAS BILD VERSCHWINDET NICHT ===============================
|
||
Gemessen am 28.09.2026 auf 390x844: Bei offener Regie war das
|
||
Kino 0 Pixel hoch -- die Regie (511 px) hatte alles genommen,
|
||
weil die Kinozeile auf `minmax(0, 1fr)` steht und bis auf null
|
||
schrumpfen darf.
|
||
|
||
Mit einer Mindesthoehe bleibt das Bild stehen, und die Regie
|
||
rollt dafuer in sich. Senkrecht rollen ist in Ordnung; Filipes
|
||
Ansage vom 28.09. galt dem Wischen nach links und rechts. Ein
|
||
Video, das ganz weg ist, ist dagegen kein Video mehr. */
|
||
/* `minmax(0, auto)` FUER DIE REGIE, NICHT `auto`.
|
||
`auto` heisst fuer eine Rasterzeile „mindestens so hoch wie
|
||
der Inhalt" -- sie schrumpft also nicht, sie laeuft ueber.
|
||
Gemessen auf 320 und 390 px: Die Regie lag 51 Pixel ueber der
|
||
Transportleiste, „Vorbereiten" und der Klapp-Knopf waren von
|
||
der Positionsschiene verdeckt. Erst mit `minmax(0, auto)` darf
|
||
sie nachgeben, und dann wirkt auch ihr `overflow-y: auto`:
|
||
Sie rollt in sich, statt die Leiste darunter zuzudecken. */
|
||
/* ==== OFFEN: AM HANDY VERSCHWINDET DAS BILD ====================
|
||
Gemessen am 28.09.2026 auf 390x844 bei offener Regie:
|
||
Saal 775 = Leiste 101 + Kino 0 + Regie 511
|
||
Das Bild ist NULL Pixel hoch. Wer mitten in der Sendung etwas
|
||
einstellt, sieht nicht mehr, worueber er redet.
|
||
|
||
ICH HABE DAS HEUTE NICHT SAUBER GELOEST und schreibe lieber
|
||
auf, was ich probiert habe, als eine halbe Loesung
|
||
stehenzulassen:
|
||
|
||
- Kinozeile auf `minmax(24dvh, 1fr)`: Das Bild kam zurueck,
|
||
dafuer wurde die Regiezeile gekuerzt und ihr Kopf lag
|
||
ueber der Transportleiste -- „Vorbereiten" und „Beenden"
|
||
waren von der Positionsschiene verdeckt (gemessen auf 320
|
||
und 390 px). Ein verdeckter Knopf ist schlimmer als ein
|
||
kleines Bild: Man drueckt ihn und trifft etwas anderes.
|
||
- Hoechsthoehe fuer die Regie (52dvh) mit klebendem Kopf:
|
||
besser, 390 px war sauber -- 320 px blieb verdeckt.
|
||
- Tempo-Knoepfe schmaler, Wort weg: half nicht genug.
|
||
|
||
DIE WURZEL ist die Transportleiste: Seit sie umbricht (statt
|
||
seitlich zu rollen -- Filipes Ansage vom 28.09.), ist sie auf
|
||
320 px 220 Pixel hoch. Zusammen mit der Regieleiste (115) sind
|
||
das 335 von 453 Pixeln Saal; fuer Bild UND Regie bleiben 118.
|
||
|
||
DER RICHTIGE WEG ist, die Tempo-Gruppe am Fingergeraet hinter
|
||
einen Knopf zu klappen -- so wie die Schriftleiste im Chat
|
||
hinter „Aa". Das spart rund 90 Pixel und braucht ein paar
|
||
Zeilen Programm. Als eigener Schritt, nicht nebenbei. */
|
||
|
||
/* ==== AM HANDY WIRD AUS LINKS UND RECHTS EIN STAPEL ==========
|
||
Zwei Spalten auf 390 px waeren zwei Spalten mit je 180 px -- da
|
||
passt kein Videotitel hinein und kein Datumsfeld. Die
|
||
Transportleiste bleibt, wo sie ist: ganz unten, ueber die
|
||
ganze Breite. Sie ist das, was man im Live anfasst, und das
|
||
aendert sich mit der Bildschirmbreite nicht. */
|
||
.regieplatz {
|
||
grid-template-columns: minmax(0, 1fr);
|
||
grid-template-areas: "laeuft" "sendung" "bereit";
|
||
gap: 12px;
|
||
}
|
||
/* Die drei gleich breiten Teile der Leiste gehen auf; uebrig
|
||
bleibt: Transport in der Mitte, alles andere darunter. */
|
||
.transport__reihe {
|
||
grid-template-columns: minmax(0, 1fr);
|
||
justify-items: center;
|
||
gap: 12px;
|
||
}
|
||
.transport__teil--rechts { justify-content: center; }
|
||
|
||
/* AM SCHMALEN GERÄT UNTEREINANDER: erst das Bild, dann der Chat.
|
||
Die Angabe gehört an denselben Ort wie die breite — an den Raum,
|
||
nicht ans Kino. */
|
||
.raum {
|
||
grid-template-columns: 1fr;
|
||
/* `minmax(0, auto)` AM KINO WURDE AM 01.10.2026 PROBIERT UND
|
||
WIEDER VERWORFEN -- gemessen null Pixel Unterschied (Kino
|
||
vorher wie nachher 203 px auf 360). Der Raum ragt naemlich
|
||
nicht aus eigener Kraft ueber seine Zeile: Die Zeile hat auf
|
||
360 px noch 161 Pixel, und ein 16:9-Video auf 360 px Breite
|
||
will 203. Keine Angabe an DIESEN Zeilen aendert daran etwas.
|
||
Steht hier, damit es niemand ein zweites Mal probiert. */
|
||
grid-template-rows: auto minmax(0, 1fr);
|
||
}
|
||
#teil-zu, #teil-warte, #teil-live { grid-area: 1 / 1; }
|
||
.raum > .schiene { grid-area: 2 / 1; }
|
||
.kino {
|
||
grid-template-rows: auto 1fr;
|
||
}
|
||
.leinwand {
|
||
aspect-ratio: 16 / 9;
|
||
height: auto;
|
||
width: 100%;
|
||
/* UND NIE HOEHER ALS SEIN PLATZ (01.10.2026).
|
||
|
||
Gemessen auf 320x568 mit zugeklappter Regie: Der Raum hat
|
||
75 Pixel, die Leinwand war 180 hoch. Das Pult liegt darueber
|
||
(z-index 60), die Knoepfe bleiben also erreichbar -- deshalb
|
||
meldet auch keine Pruefung etwas. Zu sehen war vom Bild
|
||
trotzdem nur das obere Drittel.
|
||
|
||
`width: 100%` mit `aspect-ratio` heisst „volle Breite, Hoehe
|
||
ergibt sich" -- ob Platz ist, spielt keine Rolle. `max-height`
|
||
setzt dem eine Grenze.
|
||
|
||
WAS DANN WIRKLICH PASSIERT, nachgemessen: Der Kasten wird auf
|
||
320x75 gestaucht, die Breite bleibt. Das Verhaeltnis gilt also
|
||
nicht mehr -- aber der Spieler darin setzt das Bild mittig mit
|
||
Balken links und rechts, und damit ist es GANZ zu sehen statt
|
||
zu zwei Dritteln hinter dem Pult. Klein, aber vollstaendig.
|
||
|
||
(Ich hatte hier zuerst geschrieben, die Breite folge dem
|
||
Verhaeltnis. Tut sie nicht. Gemessen 320x75, nicht 133x75.)
|
||
|
||
Auf 360, 390 und 412 aendert das nichts: Dort ist der Kasten
|
||
hoeher, als 16:9 verlangt, und `max-height` greift nicht. */
|
||
max-height: 100%;
|
||
margin-inline: auto;
|
||
}
|
||
/* Damit `max-height: 100%` einen Bezug hat, darf die Kinozeile
|
||
nicht ueber ihren Platz hinauswachsen. */
|
||
.kino { min-height: 0; }
|
||
.schiene {
|
||
border-left: 0;
|
||
border-top: 1px solid var(--rand);
|
||
min-height: 0;
|
||
}
|
||
/* ==== AM HANDY NUR ZWEI ZAHLEN ANDERS ==========================
|
||
|
||
Hier stand bis zum 28.09. `.kamera { width: clamp(88px, 26vw,
|
||
140px) }` -- eine feste Breite am Fenster selbst. Seit die Regie
|
||
die Größe einstellen kann, war das die zweite Antwort auf
|
||
dieselbe Frage, und sie gewann: Filipes Einstellung hätte am
|
||
Telefon gar nichts bewirkt, und am Rechner wäre alles richtig
|
||
gewesen. Gefunden hat das die Prüfung, nicht das Auge.
|
||
|
||
Und `.kameras { right: 10px; bottom: 10px }` war seit den vier
|
||
Ecken wirkungslos: `.kino[data-ecke="…"] .kameras` ist stärker
|
||
und setzt `inset` vollständig, ganz gleich, in welcher Reihe die
|
||
Regel steht. Eine Regel, die aussieht, als täte sie etwas, ist
|
||
schlimmer als keine. */
|
||
.kino {
|
||
--kam-grund: clamp(88px, 26vw, 140px);
|
||
--kam-rand: 10px;
|
||
}
|
||
.kameras { flex-direction: row; }
|
||
|
||
/* ==== 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; }
|
||
/* 52dvh SEIT DEM 28.09., VORHER 62. Die Register sind nach oben
|
||
gewandert, und auf 844 Pixel Höhe blieben mit 62 nur 131 Pixel
|
||
für das Bild übrig -- ein Streifen, kein Video. Gemessen mit
|
||
52: 215 Pixel. Die Tafeln rollen ohnehin in sich; was hier
|
||
kleiner wird, ist die Höhe der Schublade, nicht ihr Inhalt. */
|
||
/* GEMESSEN UND NICHT GESCHAETZT. Vorher 62dvh -- damit blieben auf
|
||
844 Pixel Höhe 131 Pixel für das Bild übrig, ein Streifen. Mit
|
||
52dvh wurden es 75: schlechter, nicht besser. Der Grund stand
|
||
woanders — die Leiste des Pults bricht am Handy in vier Zeilen
|
||
um und ist dort rund 200 Pixel hoch, nicht 67. Ein Anteil der
|
||
Fensterhöhe kann davon nichts wissen.
|
||
Also eine feste Obergrenze daneben: 19rem sind 304 Pixel, und
|
||
200 + 304 lassen dem Video 217 — genug für ein 16:9-Bild auf
|
||
390 Pixel Breite (219). Die Tafeln rollen in sich; kleiner wird
|
||
die Schublade, nicht ihr Inhalt. */
|
||
.pult__innen { max-height: min(52dvh, 19rem); }
|
||
|
||
/* ==== 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 auf JEDER Breite waagerecht -- das steht
|
||
jetzt in der Grundregel. Am Handy wird nur enger gefasst. */
|
||
.reiter { padding: 4px 8px 5px; gap: 3px; }
|
||
.reiter__knopf { padding: 0 12px; font-size: .8rem; }
|
||
.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,
|
||
.reiter__marke,
|
||
.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.
|
||
===================================================================== */
|
||
/* DIE CHAT-LEISTE HIESS BIS ZUM 28.09.2026 `.stufen` -- GENAU WIE
|
||
DIE STUFENLEITER DER SPENDEN, 600 Zeilen weiter oben. Zwei Dinge,
|
||
ein Name, und die spaetere Regel gewinnt: Die Spenden-Stufenleiter
|
||
bekam dadurch `display: flex` und stellte ihre drei Stufen
|
||
NEBENEINANDER -- 572 Pixel in einer 327 Pixel schmalen Spalte, mit
|
||
waagerechter Rollleiste. Auf dem Bildschirmfoto sah das aus wie ein
|
||
Platzproblem; es war ein Namensstreit. Dritter Fall dieser Art nach
|
||
`.tafel` und `.stufe-knopf`. */
|
||
.chatstufen {
|
||
display: flex; gap: 3px;
|
||
margin-left: auto;
|
||
padding: 3px;
|
||
border-radius: 10px;
|
||
background: rgba(0, 0, 0, .35);
|
||
border: 1px solid var(--rand);
|
||
}
|
||
.chatstufe {
|
||
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;
|
||
}
|
||
.chatstufe[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; }
|
||
}
|
||
|
||
/* ---- Die Bühnenquellen ------------------------------------------------
|
||
Drei Adressen zum Kopieren. Der Schlüssel darin steht NICHT
|
||
ausgeschrieben da: Er ist ein Geheimnis, und dieser Bildschirm wird
|
||
gestreamt. Der Knopf legt die vollständige Adresse in die
|
||
Zwischenablage.
|
||
--------------------------------------------------------------------- */
|
||
.quellen { display: grid; gap: 7px; }
|
||
.quelle {
|
||
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
|
||
padding: 9px 11px;
|
||
border-radius: 12px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .03);
|
||
}
|
||
.quelle__text { flex: 1 1 12rem; min-width: 0; display: grid; gap: 1px; }
|
||
.quelle__name {
|
||
font-size: .84rem; font-weight: 800;
|
||
color: var(--schrift);
|
||
}
|
||
.quelle__was {
|
||
font-size: .74rem; color: var(--schrift-leise);
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
}
|
||
.quelle__kopie {
|
||
appearance: none; cursor: pointer; flex: none;
|
||
min-height: 38px; padding: 0 14px;
|
||
border-radius: 10px;
|
||
border: 1px solid rgba(154, 183, 255, .34);
|
||
background: rgba(154, 183, 255, .12);
|
||
color: #cfe0ff;
|
||
font-size: .78rem; font-weight: 700;
|
||
}
|
||
.quelle__kopie[data-fertig="ja"] {
|
||
border-color: rgba(125, 226, 168, .5);
|
||
background: rgba(125, 226, 168, .18);
|
||
color: #9ff0c2;
|
||
}
|
||
/* Nur der Notweg, wenn die Zwischenablage nicht geht. */
|
||
.quelle__feld {
|
||
flex: 1 1 100%;
|
||
min-height: 38px; padding: 0 10px;
|
||
border-radius: 10px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(0, 0, 0, .34);
|
||
color: var(--schrift);
|
||
font: inherit; font-size: .76rem;
|
||
font-family: ui-monospace, "Cascadia Mono", Menlo, monospace;
|
||
}
|
||
|
||
/* =====================================================================
|
||
DER BÜHNENMODUS (?nur=buehne)
|
||
|
||
Dieselbe Seite, nur ohne alles Bedienbare — für die Aufnahme als
|
||
Fenster in OBS oder TikTok Studio. Übrig bleibt, was in den Stream
|
||
gehört: das Video und die Kameras.
|
||
|
||
FÜR DEN FALL MIT GÄSTEN. Deren Kameras kommen über eine
|
||
Direktverbindung an, und die braucht eine angemeldete Seite — eine
|
||
Browser-Quelle in OBS kann das nicht, weil OBS die Anmeldung nicht
|
||
zuverlässig behält. Läuft nur das Video, ist `buehne.html` die
|
||
bessere Quelle: schärfer, frei in Größe und Lage.
|
||
===================================================================== */
|
||
body[data-nur="buehne"] .kopfleiste,
|
||
body[data-nur="buehne"] .schiene,
|
||
body[data-nur="buehne"] .regieleiste,
|
||
body[data-nur="buehne"] .pult,
|
||
body[data-nur="buehne"] .buehne-schild,
|
||
body[data-nur="buehne"] .senderleiste,
|
||
body[data-nur="buehne"] .ton-an,
|
||
body[data-nur="buehne"] .fehler,
|
||
body[data-nur="buehne"] .spendentafel {
|
||
display: none !important;
|
||
}
|
||
/* Der Saal füllt das ganze Fenster — ohne die 69 Pixel Kopfleiste,
|
||
die es hier nicht mehr gibt.
|
||
|
||
==== UND ER BEHÄLT SEINE DREI ZEILEN ==============================
|
||
|
||
Hier stand `grid-template-rows: minmax(0, 1fr)` — eine einzige
|
||
Zeile. Das war richtig, solange nichts festgenagelt war. Seit dem
|
||
28.09. sitzt `#teil-live` ausdrücklich auf Zeile 2, und die gab es
|
||
hier dann nicht mehr: Das Video landete in einer IMPLIZITEN Zeile,
|
||
die sich nach ihrem Inhalt bemisst — während die Leinwand ihre
|
||
Höhe aus der Zeile nimmt. Beide warten aufeinander, heraus kommt
|
||
null. Gemessen: Leinwand unsichtbar, Saal 720 von 720.
|
||
|
||
Die drei Zeilen der Grundregel stimmen hier von selbst: Leiste und
|
||
Pult sind `display: none` und belegen als `auto`-Zeile genau null
|
||
Pixel. Es bleibt also nur die Höhe zu setzen.
|
||
|
||
DAS IST HEUTE DER VIERTE FALL VON „ZWEI REGELN FÜR DIESELBE
|
||
FRAGE" (Tafeln, Saalzeilen, Kamerabreite, jetzt der
|
||
Bühnenmodus). Die Lehre ist jedes Mal dieselbe und jedes Mal
|
||
dieselbe Lösung: nicht die zweite Regel richtig stellen, sondern
|
||
sie abschaffen. */
|
||
body[data-nur="buehne"] .saal {
|
||
height: 100dvh;
|
||
}
|
||
/* In der Bühnenquelle gibt es keinen Chat — dann soll die rechte
|
||
Spalte auch keinen Platz belegen. */
|
||
body[data-nur="buehne"] .raum,
|
||
.obs-buehne .raum { grid-template-columns: 1fr; }
|
||
body[data-nur="buehne"] { background: #000; }
|
||
|
||
/* ==== KEINE TASTENKUERZEL AM FINGERGERAET =========================
|
||
Sie stehen an den Knoepfen, damit man sie beim Bedienen lernt --
|
||
am Rechner genau richtig. An einem Geraet ohne Tastatur sind sie
|
||
eine Beschriftung fuer etwas, das es nicht gibt, und sie kosten
|
||
Breite: Gemessen wuchs die Transportleiste auf einem 390er Handy
|
||
dadurch auf 373 Pixel und nahm der Regie den Platz, in dem „Auf
|
||
Sendung" steht.
|
||
|
||
Fuer Vorleseprogramme bleiben sie im Dokument -- versteckt wird
|
||
nur, was das Auge nicht braucht. */
|
||
@media (pointer: coarse) {
|
||
.transport__teil kbd,
|
||
.transport__wort kbd,
|
||
.transport__taste,
|
||
.sender-taste,
|
||
.spur__knopf kbd { display: none; }
|
||
|
||
/* VIERUNDVIERZIG AM DAUMEN, AUCH HIER (29.09.2026).
|
||
|
||
Die Grundregel von `.spur__knopf` steht auf `min-height: 40px`
|
||
-- am Rechner richtig, am Finger vier Pixel zu wenig. Gemessen:
|
||
`#v-zurueck` und `#v-vor` 48x40, `#v-naechstes` 83x40, auf
|
||
iPhone und Android, bei zwei Rollen.
|
||
|
||
WARUM DAS ERST HEUTE AUFFAELLT: Die Transportleiste war am
|
||
Handy bis gestern gar nicht erreichbar -- sie lag 162 Pixel
|
||
unter dem Fensterrand, und der Koerper hat `overflow: hidden`.
|
||
Was nicht sichtbar ist, wird nicht gemessen. Die Reparatur von
|
||
gestern hat den Mangel nicht verursacht, sondern aufgedeckt.
|
||
|
||
Die vier Pixel kosten die Reihe einmal 4 Pixel Hoehe. Die
|
||
Schublade hat 72 Prozent und traegt das. */
|
||
.spur__knopf { min-height: 44px; }
|
||
}
|
||
|
||
/* ==== DIE TEMPO-GRUPPE KLAPPT AM FINGERGERAET =====================
|
||
Der offene Punkt vom 28.09.2026: Am Handy blieb bei offener
|
||
Regie vom Bild null Pixel. Die Wurzel war die Transportleiste --
|
||
seit sie umbricht (Filipes Ansage: nichts nach links oder rechts
|
||
schieben), braucht sie auf 320 px Breite 220 Pixel. Der groesste
|
||
Posten darin sind die sechs Tempo-Knoepfe zu je 44 Pixeln.
|
||
|
||
Am Rechner aendert sich NICHTS: Dort gibt es den Klappknopf gar
|
||
nicht, und die Gruppe steht offen -- sie war Filipes Wunsch an
|
||
genau dieser Stelle. Nur wo mit dem Finger bedient wird und der
|
||
Platz fehlt, klappt sie hinter ihren eigenen Wert. */
|
||
.tempo__auf { display: none; }
|
||
|
||
@media (pointer: coarse) {
|
||
.tempo__auf {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
appearance: none; cursor: pointer;
|
||
min-height: 44px; min-width: 52px; padding: 0 10px;
|
||
border-radius: 10px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .05);
|
||
color: var(--schrift);
|
||
font: inherit; font-size: .78rem; font-weight: 800;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
/* AUFGEKLAPPT SIEHT MAN ES DEM KNOPF AN -- sonst drueckt man ihn
|
||
ein zweites Mal, weil man nicht weiss, ob der erste gewirkt hat. */
|
||
.tempo__auf[aria-expanded="true"] {
|
||
border-color: rgba(154, 183, 255, .4);
|
||
background: rgba(154, 183, 255, .14);
|
||
}
|
||
/* ==== DIE REGISTER KLAPPEN HINTER IHREN WERT (01.10.2026) ======
|
||
|
||
Acht Register brauchen am Handy zwei Zeilen — gemessen 100 px
|
||
auf 360x640 und 148 auf 320x568. Unten fehlten dieselben Pixel:
|
||
Die drei festen Leisten nahmen 410 von 571, ein 16:9-Video auf
|
||
360 px Breite will 203, und der Chatkopf lag auf dem Pult.
|
||
|
||
NICHT EINZEILIG ZUM WISCHEN: Filipes Ansage vom 28.09. galt dem
|
||
Wischen nach links und rechts, und mess-quer misst genau das.
|
||
|
||
Der Knopf traegt den Namen des Bereichs, in dem man steht. */
|
||
.reiter__auf {
|
||
display: inline-flex; align-items: center; gap: 7px;
|
||
min-height: 44px; padding: 0 14px;
|
||
border: 1px solid var(--rand-hell); border-radius: 12px;
|
||
background: rgba(255, 255, 255, .05);
|
||
color: var(--schrift); font: inherit; font-weight: 700;
|
||
font-size: .84rem; cursor: pointer;
|
||
}
|
||
/* Der Pfeil gehoert zum Knopf, nicht ins Gerüst: Ein Zeichen, das
|
||
nur zeigt, was `aria-expanded` schon sagt, braucht keinen
|
||
eigenen Knoten im Dokument. */
|
||
.reiter__auf::after {
|
||
content: ""; width: 7px; height: 7px;
|
||
border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
|
||
transform: rotate(45deg) translate(-2px, -2px);
|
||
transition: transform .18s ease;
|
||
}
|
||
.reiter__auf[aria-expanded="true"]::after {
|
||
transform: rotate(-135deg) translate(-2px, -2px);
|
||
}
|
||
.regieleiste[data-auf="zu"] .reiter { display: none; }
|
||
|
||
/* Das Wort „Tempo" faellt weg: Der Knopf daneben sagt bereits
|
||
„1×", und die Kuerzel darin gibt es an einem Geraet ohne
|
||
Tastatur ohnehin nicht.
|
||
|
||
UND „WEITER" AUS DEMSELBEN GRUND (01.10.2026). Gemessen auf
|
||
360x640 war die rechte Gruppe 122 Pixel hoch statt 44: Sie
|
||
bekommt in der dreispaltigen Reihe nur 89 Pixel Breite und
|
||
bricht dreimal um. „Weiter" ist dabei eine Beschriftung fuer
|
||
zwei Knoepfe, die ihre Aufgabe selbst draufstehen haben --
|
||
„Naechstes" und „Wechseln zu <Titel>". Am Rechner bleibt sie:
|
||
Dort ist Platz, und dort ordnet sie die Leiste. */
|
||
.transport__teil .transport__wort { display: none; }
|
||
#tempo-teil[data-auf="zu"] .tempo { display: none; }
|
||
}
|
||
|
||
/* ==== AM HANDY MUSS DER TRANSPORT ERREICHBAR BLEIBEN ==============
|
||
Gemessen am 29.09.2026 auf 390x844 bei offener Regie:
|
||
Saal 775 px, Zeilen 101 + 0 + 511 + 325 = 937
|
||
transport 681..1006 -- 162 Pixel UNTER dem Fensterrand
|
||
Der Koerper hat `overflow: hidden`; die Leiste war also nicht
|
||
abgeschnitten, sondern weg. Play, „Naechstes" und ±10 Sekunden
|
||
waren bei offener Regie nicht erreichbar, und das Kino hatte
|
||
null Pixel.
|
||
|
||
Drei Schnitte, keiner davon nimmt eine Funktion weg: */
|
||
@media (pointer: coarse) {
|
||
/* 1. DER KLAPP-KNOPF STAND ALLEIN IN EINER ZEILE -- 44 Pixel plus
|
||
Abstand fuer einen Pfeil. Er gehoert an den Rand der obersten
|
||
Zeile, neben die Lampe. `order` reicht dafuer: Die Leiste ist
|
||
ohnehin eine umbrechende Reihe. */
|
||
.pult__leiste { position: relative; padding-right: 64px; }
|
||
.pult__klapp {
|
||
position: absolute; top: 9px; right: 12px;
|
||
}
|
||
|
||
/* 2. DIE DREI GRUPPEN DER TRANSPORTREIHE NEBENEINANDER.
|
||
Untereinander kosteten sie 240 Pixel; nebeneinander sind es
|
||
rund 58. Moeglich wurde das, als die Tempo-Gruppe hinter
|
||
ihren eigenen Wert klappte -- vorher brauchte sie allein
|
||
zwei Zeilen. */
|
||
.transport__reihe {
|
||
/* DIE MITTE SCHRUMPFT NIE, DIE SEITEN SCHON.
|
||
Mit `auto 1fr auto` nahmen Tempo und „Wechseln zu <Titel>"
|
||
so viel, dass die mittlere Spalte schmaler wurde als der
|
||
runde Play-Knopf -- er ragte gemessen 21 Pixel ueber beide
|
||
Nachbarn. Auf dem Bildschirmfoto sieht das aus wie ein
|
||
Fehler, und wer danebentippt, trifft den falschen Knopf.
|
||
|
||
`min-content` in der Mitte heisst: so breit wie noetig, nie
|
||
weniger. `minmax(0, auto)` aussen heisst: nehmt euch, was
|
||
uebrig ist, und gebt nach, wenn es eng wird. */
|
||
/* `max-content` UND NICHT `min-content`: Mit dem Minimum war
|
||
die Spalte so breit wie ihr BREITESTER Knopf (der runde
|
||
Play-Knopf), und „−10" und „+10" brachen darunter um --
|
||
drei Knoepfe in drei Zeilen. Mit dem Maximum bleiben sie
|
||
nebeneinander, so wie man sie im Live sucht. Die beiden
|
||
Seiten geben dafuer nach; der Videotitel im Umschalter
|
||
kuerzt sich ohnehin. */
|
||
grid-template-columns: minmax(0, auto) max-content minmax(0, auto);
|
||
justify-items: stretch;
|
||
gap: 8px;
|
||
}
|
||
.transport__teil--rechts { justify-content: flex-end; }
|
||
|
||
/* 3. DER REGIE-INHALT NIMMT, WAS UEBRIG BLEIBT.
|
||
Eine feste Hoechsthoehe waere hier die dritte Zahl, die
|
||
dasselbe zu regeln versucht wie die Schublade darueber --
|
||
und zwei Regeln fuer eine Frage haben heute schon zweimal
|
||
gereicht, damit eine davon falsch gewinnt. Als Flex-Kind
|
||
bekommt der Inhalt den Rest und rollt darin. */
|
||
.saal:has(.pult[data-auf="ja"]) .pult__innen {
|
||
max-height: none;
|
||
flex: 1 1 auto;
|
||
min-height: 0;
|
||
}
|
||
|
||
/* 4. BEI OFFENER REGIE TRITT DIE CHATSCHIENE BEISEITE (01.10.2026).
|
||
|
||
Gemessen mit offener Regie: Das Pult nimmt auf 412x915
|
||
vierhundertvierundachtzig der 846 Pixel des Saals.
|
||
Nebeneinander stehen Regie und Bild erst ab 1100 Pixeln --
|
||
darunter stapelt sich alles, und fuer den Raum bleiben 125
|
||
von den 232, die Bild und Chat zusammen brauchen. Die
|
||
Differenz lag auf dem Pult: „Offen", „Team" und „Zu" aus dem
|
||
Chatkopf waren verdeckt, und wer sie antippte, traf
|
||
„Starten" oder „Beenden".
|
||
|
||
WARUM DIE SCHIENE WEICHT UND NICHT DAS BILD: Wer die Regie
|
||
aufmacht, stellt etwas ein — das Bild muss er dabei im Auge
|
||
behalten, den Chat nicht, und der ist einen Fingertipp
|
||
entfernt. Sie verschwindet auch nur, solange die Regie offen
|
||
ist; beim Zuklappen steht sie wieder da, mit allem darin. */
|
||
.saal:has(.pult[data-auf="ja"]) .schiene { display: none; }
|
||
}
|
||
|
||
/* ==== AM HANDY LEGT SICH DIE REGIE UEBER DAS BILD =================
|
||
GERECHNET, NICHT GERATEN. Auf 390x844 hat der Saal 775 Pixel.
|
||
Davon gehen weg: Regieleiste 101, Regie-Kopf 207, Regie-Inhalt
|
||
240, Transport 243 -- zusammen 791. Mehr als da ist. Selbst nach
|
||
drei Schnitten (Klapp-Knopf aus der eigenen Zeile, Transportreihe
|
||
nebeneinander, Inhalt kuerzer, zusammen 145 Pixel) bleiben fuer
|
||
das Bild rund 120 Pixel: ein Streifen, kein Bild.
|
||
|
||
Das ist keine Frage der Gestaltung mehr, sondern des Platzes.
|
||
Video, Regie und Transport passen auf einem Handy nicht
|
||
nebeneinander.
|
||
|
||
ALSO UEBEREINANDER. Das Video behaelt seine volle Hoehe und ist
|
||
sofort wieder da, sobald man die Regie zuklappt. Der Transport
|
||
bleibt sichtbar, weil die Schublade oberhalb von ihm endet --
|
||
seine Hoehe misst das Skript und schreibt sie in
|
||
`--transport-hoch`; eine Zahl waere beim naechsten Knopf still
|
||
falsch.
|
||
|
||
WARUM DAS NICHT DER ALTE FEHLER IST. Weiter oben steht, dass das
|
||
Pult frueher `position: fixed` war und „die untere Haelfte
|
||
verdeckte". Das stimmt -- fuer den RECHNER, wo Platz fuer beides
|
||
ist, und dort bleibt alles wie es ist. Am Handy ist die Wahl
|
||
nicht „nebeneinander oder uebereinander", sondern
|
||
„uebereinander oder gar nicht". */
|
||
/* ==== DIE 360-PIXEL-SPERRE IST WEG (02.10.2026) ====================
|
||
|
||
HIER STAND: „Erst ab 360 Pixeln. Auf 320x568 passen Register
|
||
(104), Regie-Kopf (210) und Transportleiste (158) zusammen nicht
|
||
in die 499 Pixel Saal — gemessen fehlten 17. Fuenf Versuche haben
|
||
den Befund verschoben und keinen geloest."
|
||
|
||
Filipe: „auf so apps wie youtube und so geht es doch auch auf dem
|
||
handy also perfektionier es endlich."
|
||
|
||
Er hat recht, und die Begruendung oben war ueberholt. Was bei
|
||
320 px wirklich geschah (gemessen, Regie offen):
|
||
|
||
Bild 0 px · Pult 1324 px IM FLUSS · Transportleiste endet
|
||
bei 1567 von 568 Pixeln Fenster
|
||
|
||
Die Regie stand im Raster statt darueber und schob alles hinaus.
|
||
Dass genau das ab 360 px schon geloest war, macht es nicht
|
||
besser: Es war dieselbe Seite, nur schmaler.
|
||
|
||
WARUM ES JETZT TRAEGT UND 2026-09 NICHT. Die Rechnung von damals
|
||
stimmt nicht mehr. Der Kopf der Regie war 210 px hoch, weil die
|
||
drei grossen Knoepfe und die Messwerte je zwei Zeilen brauchten.
|
||
Gemessen am 02.10.: 197 px — und mit der Straffung unten 147 px.
|
||
Der Platz, der 2026-09 fehlte, ist seitdem entstanden.
|
||
|
||
VIER VARIANTEN DURCHGEMESSEN, nicht geraten (320x568, offen):
|
||
|
||
heute Bild 0 · Kopf 197 · Schublade 1324
|
||
nur Sperre weg Bild 180 · Kopf 197 · Schublade 234 · Inhalt 36
|
||
+ Knoepfe enger Bild 180 · Kopf 147 · Schublade 234 · Inhalt 86
|
||
+ 86 % statt 72 Bild 180 · Kopf 147 · Schublade 280 · Inhalt 132
|
||
|
||
Die letzte ist es geworden. Drei Knoepfe zu 44 px bleiben in
|
||
jeder Variante erreichbar und keiner wird abgeschnitten — das
|
||
war die Bedingung, nicht die Hoffnung.
|
||
|
||
Der Rest steht im Block fuer schmale Geraete weiter unten. */
|
||
/* ERST AB 360 PIXELN.
|
||
|
||
Auf 320x568 bleiben zwischen den Registern und der
|
||
Transportleiste rund 190 Pixel, und der Kopf der Regie allein
|
||
braucht 210. Sechs Versuche haben dort nur bestimmt, WER
|
||
verdeckt wird -- „Vorbereiten" unter der Leiste, oder die
|
||
Schublade ueber „Gäste" und „Bild", oder beim rollenden
|
||
Container 22 Pixel Ueberlappung. Keiner hat es geloest.
|
||
|
||
Auf diesem Geraet (4 Zoll, 2016) bleibt es deshalb beim Stand
|
||
von vorher: Bei offener Regie ist die Transportleiste nicht
|
||
erreichbar. Das ist ein bekannter Mangel und keine Absicht --
|
||
aber einer, der ein eigenes Nachdenken braucht (etwa: die Regie
|
||
wird dort ein eigener Bildschirm statt einer Schublade), nicht
|
||
den siebten Versuch mit derselben Werkzeugkiste. */
|
||
@media (pointer: coarse) {
|
||
/* IM RASTER, NICHT DARUEBER GESCHWEBT.
|
||
|
||
Der erste Bau nahm `position: absolute` und rechnete die
|
||
Unterkante aus der gemessenen Transporthoehe. Das lief -- und
|
||
die Schublade lag dabei 17 Pixel ueber den Registern, weil
|
||
„von unten so hoch wie noetig" nichts darueber weiss, wo oben
|
||
etwas anderes steht.
|
||
|
||
Als Rasterfeld ueber die Zeilen 2 und 3, unten angedockt,
|
||
braucht es keine einzige gerechnete Zahl: Es beginnt nie ueber
|
||
der Regieleiste (die ist Zeile 1) und endet nie unter dem
|
||
Transport (der ist Zeile 4). Das Bild liegt darunter in
|
||
derselben Zeile 2 und behaelt seine volle Hoehe. */
|
||
.saal .pult {
|
||
/* UEBER ZEILE 2 UND 3, ABSOLUT DARIN.
|
||
|
||
Der Bezugsrahmen eines absolut gesetzten RASTERFELDES ist
|
||
sein Rasterbereich -- nicht der ganze Container. Das hat
|
||
zwei Versuche gekostet: Mit `grid-row: 3` (0 Pixel hoch)
|
||
wurde aus `max-height: 100%` eine Hoehe von einem Pixel, und
|
||
mit `top` UND `bottom` UND `height: fit-content` verwirft der
|
||
Browser das `bottom` -- die Regie ragte 101 Pixel in die
|
||
Transportleiste.
|
||
|
||
Ueber die Zeilen 2 und 3 gespannt stimmt beides von selbst:
|
||
Der Bereich beginnt unter der Regieleiste und endet ueber
|
||
dem Transport. `bottom: 0` dockt unten an. Keine gemessene
|
||
Zahl, keine Variable, nichts, das beim naechsten Knopf
|
||
veraltet.
|
||
|
||
72 PROZENT UND NICHT 100: Oben bleibt ein Streifen Bild
|
||
stehen. Wer mitten in der Sendung etwas einstellt, muss
|
||
sehen, worueber er redet -- eine Schublade, die alles
|
||
zudeckt, waere derselbe Zustand wie vorher, nur mit einem
|
||
anderen Grund. Gemessen sind das auf 390x844 rund 120 Pixel
|
||
Bild und 310 Pixel Regie; der Kopf mit den drei grossen
|
||
Knoepfen passt hinein, der Rest rollt. */
|
||
grid-row: 2 / 4;
|
||
position: absolute;
|
||
left: 0; right: 0; bottom: 0;
|
||
/* 72 PROZENT: Oben bleibt ein Streifen Bild stehen. Wer
|
||
mitten in der Sendung etwas einstellt, muss sehen, worueber
|
||
er redet -- eine Schublade, die alles zudeckt, waere
|
||
derselbe Zustand wie vorher, nur mit anderem Grund.
|
||
Gemessen auf 390x844: rund 120 Pixel Bild, 310 Pixel Regie. */
|
||
/* 72 PROZENT: Oben bleibt ein Streifen Bild stehen. Wer
|
||
mitten in der Sendung etwas einstellt, muss sehen, worueber
|
||
er redet. Gemessen auf 390x844: rund 133 Pixel Bild, 346
|
||
Pixel Regie -- der Kopf mit den drei grossen Knoepfen passt
|
||
hinein, der Rest rollt. */
|
||
max-height: 72%;
|
||
/* DER INHALT MUSS SICH DIE HOEHE TEILEN. Ohne diese drei
|
||
Zeilen hielt sich die Schublade an ihre 72 Prozent, ihr
|
||
INHALT aber nicht: Das Vorschaubild der Kachel „Was läuft"
|
||
lag im Bildschirmfoto quer ueber der Transportleiste.
|
||
Als Spalte bekommt der Kopf, was er braucht, und der Rest
|
||
rollt in dem, was uebrig bleibt. */
|
||
display: flex;
|
||
flex-direction: column;
|
||
/* DER KOPF GIBT NICHT NACH, ER ROLLT MIT.
|
||
Ohne `flex: none` ist er ein Flex-Kind mit `shrink: 1` --
|
||
das hilft aber nichts, weil sein `min-height: auto` ihn nicht
|
||
unter die Hoehe seines Inhalts laesst. Er ragte dann einfach
|
||
hinaus, und auf 320x568 lagen „Vorbereiten" und „Beenden"
|
||
unter der Transportleiste. Mit `flex: none` und einem
|
||
rollenden Container bleibt alles innerhalb der Schublade
|
||
erreichbar -- senkrechtes Rollen war nie das Problem,
|
||
Filipes Ansage galt dem Wischen nach links und rechts. */
|
||
overflow-y: auto;
|
||
overflow-x: hidden;
|
||
z-index: 60;
|
||
/* Ein Schatten nach oben -- sonst sieht die Schublade aus wie
|
||
ein abgeschnittenes Bild statt wie etwas, das darueberliegt. */
|
||
box-shadow: 0 -18px 40px -12px rgba(0, 0, 0, .75);
|
||
}
|
||
/* Die dritte Zeile faellt damit weg -- das Bild bekommt sie.
|
||
AUCH ZUGEKLAPPT: Bei 320x568 ist der Kopf der Regie allein
|
||
207 Pixel hoch (drei Knoepfe brauchen dort zwei Zeilen), und
|
||
zusammen mit den drei Zeilen Registern (148) und der
|
||
Transportleiste (243) sind das 598 von 499 Pixeln Saal.
|
||
Gemessen ragten „Vorbereiten" und „Beenden" dadurch in die
|
||
Transportleiste -- verdeckte Knoepfe, die man drueckt und
|
||
dabei etwas anderes trifft. Als Schublade legt sich der Kopf
|
||
ueber das Bild statt in die Leiste. */
|
||
.saal {
|
||
grid-template-rows: auto minmax(0, 1fr) 0 auto;
|
||
}
|
||
}
|
||
|
||
/* ==== DER KOPF DER REGIE AM FINGERGERAET ==========================
|
||
Gemessen auf 320x568: Der Kopf ist 207 Pixel hoch -- fuenf
|
||
Zeilen zu je rund 44 Pixeln. Zusammen mit drei Zeilen Registern
|
||
(148) und der Transportleiste (243) sind das 598 von 499 Pixeln
|
||
Saal, und „Vorbereiten" und „Beenden" lagen unter der Leiste.
|
||
|
||
Drei Straffungen, die auf jedem Fingergeraet gelten und keine
|
||
Funktion wegnehmen:
|
||
|
||
- Die Messwerte stehen in EINER Zeile statt umzubrechen.
|
||
„Sehen zu 3 · Mit Bild 3/12 · Gäste 1/2 · Upload –" liest
|
||
sich nebeneinander genauso gut, und untereinander kosten
|
||
sie 41 Pixel.
|
||
- Die Schrift der Zahlen ist kleiner. Sie sind Nebenauskunft,
|
||
nicht die Hauptsache -- 11,52 px ist die Hausgrenze, und
|
||
darueber bleibt es.
|
||
- Die drei grossen Knoepfe bekommen weniger Polsterung. Ihre
|
||
44 Pixel Hoehe bleiben (das ist die Daumengrenze), nur die
|
||
Breite gibt nach, damit sie in eine Zeile passen. */
|
||
@media (pointer: coarse) {
|
||
.pult__leiste { gap: 6px 10px; padding: 8px 12px; flex: none; }
|
||
.messwerte { gap: 2px 12px; flex-wrap: nowrap; overflow: visible; }
|
||
.messwerte__paar { display: flex; align-items: baseline; gap: 5px; }
|
||
.messwerte dt { font-size: .72rem; }
|
||
.messwerte dd { font-size: .8rem; }
|
||
.pult__tun { gap: 6px; }
|
||
.pult__tun .tun { padding: 0 10px; font-size: .78rem; }
|
||
}
|
||
|
||
/* Der Kopf bleibt stehen, waehrend der Inhalt rollt -- sonst
|
||
scrollt man „Auf Sendung" weg, den Knopf, um den es geht. */
|
||
@media (pointer: coarse) {
|
||
.saal .pult__leiste { position: sticky; top: 0; z-index: 2;
|
||
background: var(--saal-hoch); }
|
||
}
|
||
|
||
/* =====================================================================
|
||
DAS GANZ SCHMALE GERAET (02.10.2026)
|
||
|
||
Gilt unter 360 Pixeln -- in der Praxis das iPhone SE der ersten
|
||
Reihe (320x568, 2016). Oben steht, warum die Schublade dort
|
||
ueberhaupt erst seit heute greift.
|
||
|
||
ZWEI STELLSCHRAUBEN, BEIDE GEMESSEN:
|
||
|
||
1. DIE DREI GROSSEN KNOEPFE IN EINE ZEILE. Bei 320 px brauchten
|
||
„Vorbereiten", „Auf Sendung" und „Beenden" zwei Zeilen -- das
|
||
allein sind 50 Pixel Kopf (94 statt 44). Mit `nowrap` und
|
||
weniger Polsterung passen sie nebeneinander.
|
||
|
||
DIE 44 PIXEL HOEHE BLEIBEN. Das ist die Daumengrenze des
|
||
Hauses, und sie steht hier ausdruecklich nicht zur Debatte --
|
||
nur die BREITE gibt nach. Nachgemessen: kein Knopf wird
|
||
abgeschnitten (`scrollWidth <= clientWidth`), alle drei sind
|
||
im Fenster und liegen obenauf.
|
||
|
||
2. DIE SCHUBLADE DARF HOEHER WERDEN: 86 statt 72 Prozent. Die
|
||
72 Prozent sind fuer ein 844 Pixel hohes Fenster gerechnet;
|
||
auf 568 Pixeln bleiben davon 234 Pixel Schublade, und nach
|
||
Abzug des Kopfes 36 Pixel Inhalt -- ein Guckloch. Mit 86
|
||
Prozent sind es 132.
|
||
|
||
WARUM NICHT 100: Oben bleibt ein Streifen Bild stehen, aus
|
||
demselben Grund wie bei den 72 Prozent -- wer mitten in der
|
||
Sendung etwas einstellt, muss sehen, worueber er redet.
|
||
Gemessen bleiben 180 Pixel Bild.
|
||
|
||
DIE ZAHLEN AM STUECK (320x568, Regie offen):
|
||
|
||
vorher Bild 0 · Kopf 197 · Schublade 1324 im Fluss
|
||
nachher Bild 180 · Kopf 147 · Schublade 280 · Inhalt 132
|
||
===================================================================== */
|
||
@media (pointer: coarse) and (max-width: 359px) {
|
||
.pult__tun { flex-wrap: nowrap; }
|
||
.pult__tun .tun { padding: 0 6px; font-size: .72rem; min-width: 0; }
|
||
.saal .pult { max-height: 86%; }
|
||
}
|
||
|
||
/* =====================================================================
|
||
DER KAMERAHINWEIS WIRD WIEDER SICHTBAR (02.10.2026)
|
||
|
||
`#fehler` ist ein direktes Kind des Saals OHNE Platzangabe. Der
|
||
Saal hat vier Zeilen -- das Feld landete in einer fuenften, die es
|
||
im Raster gar nicht gibt. Ueber die Zeit abgetastet (390x844):
|
||
|
||
nach 500 ms Text 104 Zeichen · hidden=nein · 0 px
|
||
nach 5000 ms Text 104 Zeichen · hidden=nein · 0 px
|
||
nach 7000 ms Text 104 Zeichen · hidden=ja · 0 px
|
||
|
||
Es wird also angezeigt, sechs Sekunden lang (die Uhr steht in
|
||
reaktion.js) -- und ist dabei durchgehend NULL PIXEL hoch. Ein
|
||
`role="alert"`, den niemand sehen kann.
|
||
|
||
AUF 320 PIXELN HABE ICH DAS HEUTE SELBST VERURSACHT. Vorher
|
||
bekam die stillschweigende fuenfte Zeile dort 71 Pixel (die dem
|
||
Bild fehlten); seit die Regie aus dem Fluss ist, bleibt fuer sie
|
||
nichts uebrig. Der Hinweis war vorher sichtbar und zu teuer --
|
||
jetzt war er umsonst und unsichtbar. Beides ist falsch.
|
||
|
||
ERSTER VERSUCH, ZURUECKGENOMMEN: `grid-row: 2` ohne
|
||
`position: absolute`. Damit belegte das Feld die Zelle, der Raum
|
||
wich in eine stillschweigende zweite SPALTE aus, und das Bild fiel
|
||
auf 0 px (320) bzw. 2 px (360). Genau davor warnt der Kommentar
|
||
bei `.raum` -- dort war es eine zweite ZEILE, hier eine zweite
|
||
SPALTE, derselbe Fehler.
|
||
|
||
SO GEHT ES: dasselbe Muster wie beim Pult. `position: absolute`
|
||
nimmt das Feld aus dem Fluss -- es belegt keine Zelle mehr und
|
||
kann nichts verdraengen. `grid-row: 2` sagt dann nur noch, WORIN
|
||
es liegt (der Bezugsrahmen eines absolut gesetzten Rasterfeldes
|
||
ist sein Rasterbereich), und `align-self: end` setzt es an dessen
|
||
Unterkante. Keine gerechnete Zahl, die beim naechsten Umbau
|
||
veraltet. */
|
||
.saal > .fehler {
|
||
position: absolute;
|
||
grid-row: 2;
|
||
grid-column: 1;
|
||
align-self: end;
|
||
justify-self: stretch;
|
||
margin: 0 8px 8px;
|
||
z-index: 70;
|
||
}
|
||
|
||
|
||
/* =====================================================================
|
||
DAS REGISTER „WERBUNG" (29.09.2026)
|
||
|
||
Filipe: „ich will es so krass wie es nur geht."
|
||
|
||
Die Einblendung selbst steht in `werbung.css` — sie läuft auch in
|
||
der Bühnenquelle, und zwei Fassungen altern unterschiedlich. Hier
|
||
steht nur ihre BEDIENUNG, und die gibt es nur im Pult.
|
||
===================================================================== */
|
||
|
||
/* ---- Die Art und das Tempo ---------------------------------------- */
|
||
.bandart-reihe,
|
||
.bandtempo-reihe,
|
||
.bandbild-reihe,
|
||
.eckengroesse-reihe {
|
||
display: flex; flex-wrap: wrap; gap: 6px;
|
||
min-width: 0;
|
||
}
|
||
.bandart__knopf,
|
||
.bandtempo__knopf,
|
||
.bandbild__knopf,
|
||
.eckengroesse__knopf {
|
||
appearance: none; cursor: pointer;
|
||
min-height: 34px; padding: 0 12px;
|
||
border-radius: 9px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .05);
|
||
color: var(--schrift);
|
||
font-size: .82rem; font-weight: 700;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.bandart__knopf:hover,
|
||
.bandtempo__knopf:hover,
|
||
.bandbild__knopf:hover,
|
||
.eckengroesse__knopf:hover { background: rgba(255, 255, 255, .1); }
|
||
.bandart__knopf[aria-pressed="true"],
|
||
.bandtempo__knopf[aria-pressed="true"],
|
||
.bandbild__knopf[aria-pressed="true"],
|
||
.eckengroesse__knopf[aria-pressed="true"] {
|
||
border-color: var(--akzent);
|
||
background: color-mix(in srgb, var(--akzent) 22%, transparent);
|
||
color: #fff;
|
||
}
|
||
|
||
/* EIN FELD, DAS NICHTS BEWIRKEN KANN, SAGT ES. Das Tempo gilt nur,
|
||
wenn überhaupt etwas läuft. Es zu verstecken wäre schlechter:
|
||
Dann sucht man es und hält es für verschwunden. */
|
||
#bandtempo-feld[data-still="ja"] { opacity: .45; }
|
||
#bandtempo-feld[data-still="ja"] .bandtempo__knopf { pointer-events: none; }
|
||
|
||
/* ---- Die Liste der Botschaften ------------------------------------ */
|
||
.bandliste {
|
||
list-style: none; margin: 0 0 10px; padding: 0;
|
||
display: grid; gap: 6px;
|
||
min-width: 0;
|
||
}
|
||
.bandliste__leer {
|
||
font-size: .82rem; color: var(--text-leise);
|
||
padding: 8px 2px;
|
||
}
|
||
.bandzeile {
|
||
display: flex; align-items: center; gap: 10px;
|
||
padding: 7px 9px;
|
||
border-radius: 11px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .035);
|
||
min-width: 0;
|
||
}
|
||
/* WAS NICHT LÄUFT, SIEHT AUCH SO AUS. Eine abgeschaltete Botschaft
|
||
nur an einem Knopf zu erkennen hieße, in einer Liste von acht
|
||
Einträgen achtmal hinzusehen. */
|
||
.bandzeile[data-aktiv="nein"] { opacity: .5; }
|
||
.bandzeile[data-aktiv="nein"] .bandzeile__text { text-decoration: line-through; }
|
||
|
||
.bandzeile__an {
|
||
appearance: none; cursor: pointer;
|
||
flex: none;
|
||
width: 34px; height: 20px;
|
||
padding: 0;
|
||
border-radius: 999px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(255, 255, 255, .07);
|
||
position: relative;
|
||
transition: background .18s ease, border-color .18s ease;
|
||
}
|
||
.bandzeile__an::after {
|
||
content: "";
|
||
position: absolute;
|
||
top: 2px; left: 2px;
|
||
width: 14px; height: 14px;
|
||
border-radius: 50%;
|
||
background: var(--text-leise);
|
||
transition: transform .18s ease, background .18s ease;
|
||
}
|
||
.bandzeile__an[aria-pressed="true"] {
|
||
border-color: var(--akzent);
|
||
background: color-mix(in srgb, var(--akzent) 34%, transparent);
|
||
}
|
||
.bandzeile__an[aria-pressed="true"]::after {
|
||
transform: translateX(14px);
|
||
background: #fff;
|
||
}
|
||
|
||
.bandzeile__texte { flex: 1 1 auto; min-width: 0; display: grid; gap: 1px; }
|
||
.bandzeile__text {
|
||
font-size: .85rem; font-weight: 700;
|
||
color: var(--schrift);
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
}
|
||
.bandzeile__unter {
|
||
font-size: .74rem; color: var(--text-leise);
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
}
|
||
.bandzeile__bild {
|
||
flex: none;
|
||
width: 26px; height: 26px;
|
||
object-fit: contain;
|
||
filter: drop-shadow(0 0 1px rgba(255, 255, 255, .7));
|
||
}
|
||
.bandzeile__tun { flex: none; display: flex; gap: 3px; }
|
||
.bandzeile__schieb,
|
||
.bandzeile__weg {
|
||
appearance: none; cursor: pointer;
|
||
width: 26px; height: 26px;
|
||
display: grid; place-items: center;
|
||
border-radius: 7px;
|
||
border: 1px solid transparent;
|
||
background: none;
|
||
color: var(--text-leise);
|
||
font-size: .72rem; line-height: 1;
|
||
}
|
||
.bandzeile__schieb:hover,
|
||
.bandzeile__weg:hover {
|
||
background: rgba(255, 255, 255, .1);
|
||
color: var(--schrift);
|
||
}
|
||
.bandzeile__schieb[disabled] { opacity: .3; cursor: default; }
|
||
.bandzeile__schieb[disabled]:hover { background: none; color: var(--text-leise); }
|
||
/* Das Löschen trägt als einziges Farbe — es ist das einzige, das
|
||
sich nicht zurückholen lässt. */
|
||
.bandzeile__weg { color: #ff8f8f; }
|
||
.bandzeile__weg:hover { background: rgba(255, 107, 107, .18); }
|
||
|
||
/* ---- Wo das Bild steht -------------------------------------------- */
|
||
.eckenwahl {
|
||
display: grid; gap: 6px;
|
||
margin-bottom: 12px;
|
||
min-width: 0;
|
||
}
|
||
.eckenwahl__wort {
|
||
font-size: .78rem; font-weight: 700;
|
||
color: var(--text-leise);
|
||
text-transform: uppercase; letter-spacing: .06em;
|
||
}
|
||
.eckenwahl__gitter { display: flex; flex-wrap: wrap; gap: 5px; }
|
||
|
||
/* JEDER KNOPF IST EIN ABBILD DER LEINWAND. Ein Rechteck im
|
||
Seitenverhältnis des Bildes, und darin ein Feld genau dort, wo das
|
||
Logo landet. „Oben links" als Wort muss man lesen; das hier sieht
|
||
man.
|
||
|
||
Die Lage kommt aus `data-platz` — dasselbe Merkmal wie an der
|
||
Einblendung selbst. Zwei Schreibweisen für dieselbe Sache wären
|
||
die Stelle, an der eine von beiden irgendwann abweicht. */
|
||
.eckenwahl__knopf {
|
||
appearance: none; cursor: pointer;
|
||
position: relative;
|
||
width: 46px; height: 30px;
|
||
padding: 0;
|
||
border-radius: 6px;
|
||
border: 1px solid var(--rand);
|
||
background: rgba(0, 0, 0, .35);
|
||
}
|
||
.eckenwahl__knopf:hover { border-color: var(--rand-hell); }
|
||
.eckenwahl__knopf[aria-pressed="true"] {
|
||
border-color: var(--akzent);
|
||
background: color-mix(in srgb, var(--akzent) 18%, rgba(0, 0, 0, .35));
|
||
box-shadow: 0 0 0 1px color-mix(in srgb, var(--akzent) 45%, transparent);
|
||
}
|
||
.eckenwahl__punkt {
|
||
position: absolute;
|
||
width: 13px; height: 13px;
|
||
border-radius: 3px;
|
||
background: var(--text-leise);
|
||
}
|
||
.eckenwahl__knopf[aria-pressed="true"] .eckenwahl__punkt { background: #fff; }
|
||
.eckenwahl__knopf[data-platz="ol"] .eckenwahl__punkt { top: 4px; left: 4px; }
|
||
.eckenwahl__knopf[data-platz="om"] .eckenwahl__punkt { top: 4px; left: 50%; transform: translateX(-50%); }
|
||
.eckenwahl__knopf[data-platz="or"] .eckenwahl__punkt { top: 4px; right: 4px; }
|
||
.eckenwahl__knopf[data-platz="ul"] .eckenwahl__punkt { bottom: 4px; left: 4px; }
|
||
.eckenwahl__knopf[data-platz="um"] .eckenwahl__punkt { bottom: 4px; left: 50%; transform: translateX(-50%); }
|
||
.eckenwahl__knopf[data-platz="ur"] .eckenwahl__punkt { bottom: 4px; right: 4px; }
|
||
/* HIER STEHEN GERADE DIE KAMERAS (30.09.2026).
|
||
|
||
Ein gestrichelter Rahmen und kein Ausrufezeichen: Es ist eine
|
||
Auskunft, keine Fehlermeldung. Bernstein, weil es dieselbe Farbe
|
||
ist wie der Rabattcode im Band — „sieh her", nicht „falsch".
|
||
|
||
Gedämpft (40 %), damit es neben dem gedrückten Knopf nicht um
|
||
Aufmerksamkeit streitet: Was gewählt ist, muss lauter sein als
|
||
was zu bedenken ist. */
|
||
.eckenwahl__knopf[data-kameras="ja"] {
|
||
border-style: dashed;
|
||
border-color: color-mix(in srgb, #f0a52c 40%, var(--rand));
|
||
}
|
||
.eckenwahl__knopf[data-kameras="ja"] .eckenwahl__punkt {
|
||
box-shadow: 0 0 0 2px color-mix(in srgb, #f0a52c 30%, transparent);
|
||
}
|
||
|
||
.eckenwahl__aus {
|
||
position: absolute; inset: 0;
|
||
display: grid; place-items: center;
|
||
font-size: .72rem; font-weight: 700;
|
||
color: var(--text-leise);
|
||
}
|
||
.eckenwahl__knopf[aria-pressed="true"] .eckenwahl__aus { color: #fff; }
|
||
|
||
/* ---- Am Daumen ----------------------------------------------------- */
|
||
@media (pointer: coarse) {
|
||
/* HAUSREGEL: 44 px. Die Knöpfe der Liste sind klein, weil dort
|
||
acht Zeilen untereinander stehen — am Finger bekommen sie
|
||
trotzdem ihre Fläche, über ein unsichtbares Feld darum. */
|
||
.bandart__knopf,
|
||
.bandtempo__knopf,
|
||
.bandbild__knopf,
|
||
.eckengroesse__knopf { min-height: 44px; }
|
||
.bandzeile__schieb,
|
||
.bandzeile__weg { width: 34px; height: 34px; position: relative; }
|
||
.bandzeile__schieb::before,
|
||
.bandzeile__weg::before,
|
||
.bandzeile__an::before {
|
||
content: "";
|
||
position: absolute;
|
||
inset: 50% auto auto 50%;
|
||
width: 44px; height: 44px;
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
.bandzeile__an { width: 44px; height: 26px; }
|
||
.bandzeile__an::after { width: 20px; height: 20px; }
|
||
.bandzeile__an[aria-pressed="true"]::after { transform: translateX(18px); }
|
||
/* `min-*` UND NICHT `width`/`height`: Der Knopf ist ein Abbild
|
||
der Leinwand. Eine feste Zahl naegelt ihn fest; eine Untergrenze
|
||
laesst ihn mitwachsen, wenn die Zeile mehr Platz hat, und haelt
|
||
nur den Daumen frei. */
|
||
.eckenwahl__knopf { min-width: 58px; min-height: 44px; }
|
||
}
|