Nichts wird mehr nach links oder rechts geschoben

Filipe, 28.09.2026: "ich will auch nicht dass man sachen nach links
und rechts schieben muss. perfektion das untereinander. ich will
niemals irgendwas nach links oder rechts swippen muessen." Dazu ein
Bildschirmfoto der Tafel "Gestaltung" mit waagerechter Rollleiste.

GEMESSEN, NICHT GERATEN

Ein grep nach `overflow-x` findet nur die absichtlichen Roller. Er
findet nicht die Stelle, an der ein Inhalt breiter ist als sein
Kasten und der Browser von sich aus eine Rollleiste anhaengt -- und
genau das war auf dem Bild zu sehen. `server/mess-quer.mjs` geht
deshalb im echten Browser jedes Element durch, auf fuenf
Bildschirmgroessen, in allen sieben Registern, bei offener und
zugeklappter Regie und in allen fuenf Anordnungen.

Erster Lauf: 78 Stellen. Davon waren 54 KEINE -- `overflow-x: hidden`
ist abgeschnittener Text, dort laesst sich nichts schieben. Die
Messung trennt das jetzt; wer es mitzaehlt, findet die echten nicht
mehr. Uebrig blieben vier Ursachen:

  1. DIE REGISTER rollten absichtlich waagerecht. Auf 412 px standen
     von 605 px Registern 193 rechts ausserhalb -- dass es
     "Gestaltung" und "Spenden" gibt, erfuhr man nur beim Wischen auf
     Verdacht. Sie brechen jetzt um. Das kostet oben rund 45 Pixel
     und bringt Gewissheit dafuer.

  2. `.stufen` STAND ZWEIMAL IN reaktion.css -- einmal fuer die
     Stufenleiter der Spenden (`display: grid`), 600 Zeilen spaeter
     fuer die Chat-Leiste Offen/Team/Zu (`display: flex`). Die
     spaetere gewinnt: Die Stufenleiter stellte ihre drei Stufen
     NEBENEINANDER, 572 Pixel in einer 327 Pixel schmalen Spalte.
     Das ist die Rollleiste auf Filipes Bild. Die Chat-Leiste heisst
     jetzt `.chatstufen` / `.chatstufe`.
     Dritter Fall dieser Art nach `.tafel` und `.stufe-knopf`.

  3. DIE TAFELN KONNTEN NICHT SCHRUMPFEN. Ein Gitterfeld hat von
     sich aus `min-width: auto` und besteht auf seinem unteilbarsten
     Inhalt. Mit `minmax(0, 1fr)` und `min-width: 0` bricht jetzt
     alles um, statt hinauszulaufen.

  4. DIE TRANSPORTLEISTE ragte am Handy 76 Pixel ueber beide Kanten
     ("Naechstes" war nur halb zu sehen). Zwei Gruende: `.transport__teil`
     hatte kein `flex-wrap` (die mittlere Gruppe schon -- zwei Regeln
     fuer dieselbe Sache, eine vergessen), und im Umschalter steht
     ein ganzer Videotitel, der als Flex-Kind auf seiner vollen
     Breite bestand.

NEBENBEFUND: EINE FESTE ZAHL VON GESTERN

Der Saal stand auf `height: calc(100dvh - 69px)` -- 69 war einmal
die gemessene Hoehe der Kopfleiste. Sie ist 73 geworden, und der
Saal endete damit 4 Pixel unter dem Fensterrand: Der Play-Knopf war
nur mit Scrollen zu erreichen. Die Antwort ist keine neue Zahl,
sondern eine Regel, die misst -- der Koerper ist jetzt eine Spalte,
die Kopfleiste nimmt, was sie braucht, der Saal bekommt den Rest.
(Dabei noch ein Spezifitaetsunfall: `.reaktion-seite` (0,1,0)
verliert gegen `body.start` (0,1,1) aus start.css.)

NEUE WACHEN

  - `mess-quer.mjs` mit Gegenprobe (ohne die Reparaturen findet sie
    47 px, mit ihnen nichts).
  - pruef-reaktion: kein absichtliches `overflow-x: auto` mehr; und
    zwei Grundregeln derselben Klasse mit verschiedenem `display`
    sind ein Namensstreit. Der bisherige Waechter verglich nur
    ZWISCHEN Stilvorlagen -- `.stufen` stand zweimal in DERSELBEN.
  - pruef-css-klassen: jede Klammer hat ihr Gegenstueck. Beim
    Umschreiben blieb heute das Ende einer Regel ohne ihren Anfang
    stehen; der Browser wirft die Zeile weg und schliesst dafuer den
    naechsten @media-Block zu frueh. Drei Befunde sahen daraufhin wie
    Programmfehler aus.

MESSUNG NACHGEZOGEN

`mess-reaktion` stammte noch aus der Zeit vor "Regie links" und
"drei Kacheln" und meldete drei Dinge, die keine Fehler waren --
gemessen gegen den Stand von HEAD: identisch rot. Sie misst ausserdem
seit heute mit FINGER statt Mauszeiger; ohne `hasTouch` greift keine
einzige Regel aus `@media (pointer: coarse)`, und dort stehen alle
44-Pixel-Beruehrziele des Hauses.

OFFEN UND AUFGESCHRIEBEN

Am Handy bleibt bei offener Regie vom Bild nichts (0 px). Der Mangel
besteht seit dem Umbau "Regie links"; drei Versuche, ihn heute zu
loesen, haben Knoepfe verdeckt -- und ein verdeckter Knopf ist
schlimmer als ein kleines Bild. Die Versuche und der richtige Weg
(Tempo-Gruppe hinter einen Knopf, wie "Aa" im Chat) stehen in
reaktion.css. `mess-reaktion` meldet ihn als dritten Ausgang: nicht
als Fehler und nicht als bestanden.

GEPRUEFT
  pruef-reaktion     384 / 0   (vorher 379)
  pruef-spenden      172 / 0
  pruef-buehne        36 / 0
  pruef-css-klassen, -tippziele, -struktur, -handy: ohne Befund
  mess-quer          EXIT 0 -- 28 Stellen, fuenf Groessen, nichts rollt
  mess-reaktion      EXIT 0, 1 benannter offener Punkt
  mess-buehne        EXIT 0
This commit is contained in:
2026-09-29 02:34:09 +02:00
parent 813d2e85a1
commit a9e0834cfb
50 changed files with 2669 additions and 1523 deletions
+204 -31
View File
@@ -33,7 +33,15 @@
mitten im Satz ist, noch die Verbindung zur Kamera.
===================================================================== */
.reaktion-seite {
/* `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);
@@ -48,10 +56,31 @@
background: var(--saal);
/* Kein Scrollen: Der Saal ist so hoch wie das Fenster. `dvh` und
nicht `vh` -- auf dem Handy wandert die Adressleiste, und `vh`
rechnet mit dem Zustand von vorhin. */
min-height: 100dvh;
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;
@@ -86,9 +115,12 @@
Eine Probe, die mehr ändert als das, wonach man sucht,
beantwortet eine andere Frage. */
grid-template-rows: auto minmax(0, 1fr) auto auto;
/* Die Kopfleiste ist 69 px hoch (gemessen, nicht geschätzt -- siehe
pruef-handy, das sie über alle Breiten abmisst). */
height: calc(100dvh - 69px);
/* 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;
}
@@ -1501,32 +1533,58 @@
max-height: min(40dvh, 17rem);
overflow-y: auto;
}
.pult[data-auf="ja"] .pult__innen { display: grid; }
/* 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 NICHT UM, SIE ROLLEN. Sieben Register in zwei Zeilen
kosten am oberen Rand rund 90 Pixel — und zwar dem Video, um das
es geht. Waagerecht rollen kostet null.
SIE BRECHEN UM. SEIT DEM 28.09.2026.
`scroll-snap` rastet das angefasste Register mittig ein; ohne das
bleibt auf dem Handy regelmäßig eines halb angeschnitten stehen,
und ein halber Knopf sieht aus wie ein Fehler. */
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: nowrap;
display: flex; gap: 4px; flex-wrap: wrap;
padding: 5px 10px 6px;
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x proximity;
scrollbar-width: none;
/* AN DEN RAENDERN VERLAEUFT SIE. Das ist die einzige Auskunft
darüber, dass rechts noch etwas kommt — eine Rollleiste zeigen
Mac und Handy von sich aus nicht an. */
mask-image: linear-gradient(90deg, transparent, #000 14px,
#000 calc(100% - 14px), transparent);
min-width: 0;
}
.reiter::-webkit-scrollbar { display: none; }
.reiter__knopf {
appearance: none; cursor: pointer;
position: relative;
@@ -1615,7 +1673,21 @@
}
.reiter__zahl[data-leer="ja"] { opacity: .45; }
.pult-tafel { display: grid; gap: 12px; align-content: start; }
/* `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
@@ -1787,7 +1859,15 @@
align-items: center;
gap: 10px;
}
.transport__teil { display: flex; align-items: center; gap: 8px; min-width: 0; }
/* 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 =================================
@@ -1910,8 +1990,14 @@
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; }
@@ -1976,8 +2062,18 @@
/* ---- 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;
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);
@@ -2428,7 +2524,10 @@
}
.pult__klein { margin: 0; font-size: .72rem; letter-spacing: .02em; text-transform: none; opacity: .85; }
.pult__zeile { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.pult__feld { display: grid; gap: 5px; flex: 1 1 14rem; min-width: 0; }
.pult__feld {
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;
@@ -2493,6 +2592,54 @@
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
@@ -2769,7 +2916,15 @@
/* ---- Die Chat-Stufe --------------------------------------------------
Drei Schalter im Kopf der Schiene. Man moderiert, wo man liest.
===================================================================== */
.stufen {
/* 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;
@@ -2777,7 +2932,7 @@
background: rgba(0, 0, 0, .35);
border: 1px solid var(--rand);
}
.stufe {
.chatstufe {
appearance: none; cursor: pointer;
min-height: 28px; padding: 0 9px;
border: 0; border-radius: 7px;
@@ -2785,7 +2940,7 @@
color: var(--schrift-leise);
font-size: .72rem; font-weight: 700;
}
.stufe[aria-pressed="true"] {
.chatstufe[aria-pressed="true"] {
background: rgba(255, 255, 255, .1);
color: var(--schrift);
}
@@ -2907,3 +3062,21 @@ body[data-nur="buehne"] .saal {
}
body[data-nur="buehne"] .kino { 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; }
}