diff --git a/server/mess-quer.mjs b/server/mess-quer.mjs
index 1b3c2ddf..61f35d17 100644
--- a/server/mess-quer.mjs
+++ b/server/mess-quer.mjs
@@ -319,6 +319,23 @@ for (const [gname, breite, hoehe] of GERAETE) {
console.log(`\n=== ${gname} (${breite}x${hoehe}) ===`);
const host = await alsWer("admin", breite, hoehe);
await host.seite.goto(`${BASIS}/workspace/reaktion.html`, { waitUntil: "domcontentloaded" });
+ /* AUF DIE LEISTE WARTEN, NICHT AUF DIE REGISTER (01.10.2026).
+
+ Seit die Register am Fingergeraet hinter einem Knopf liegen, ist
+ `#reiter` dort unsichtbar -- `waitForSelector` wartet aber auf
+ SICHTBARKEIT und lief in die Zeitsperre ("33 x locator resolved
+ to hidden"). Gewartet wird jetzt auf die Leiste selbst; die
+ steht in jedem Fall. */
+ await host.seite.waitForSelector("#regieleiste", { timeout: 15000 });
+
+ /* UND DANN AUFKLAPPEN WIE EIN MENSCH. Diese Messung sucht
+ seitlichen Ueberlauf IN den Registern -- sie muss sie also
+ sehen. Der Knopf gibt es nur am Fingergeraet; am Rechner steht
+ die Leiste ohnehin offen, und `?.` faengt das ab. */
+ await host.seite.evaluate(() => {
+ const l = document.getElementById("regieleiste");
+ if (l && l.dataset.auf !== "auf") document.getElementById("reiter-auf")?.click();
+ });
await host.seite.waitForSelector("#reiter", { timeout: 15000 });
/* ZUERST ZUGEKLAPPT -- DAS IST DER HAEUFIGSTE ZUSTAND.
@@ -393,6 +410,13 @@ for (const [gname, breite, hoehe] of GERAETE) {
for (const reg of register) {
await host.seite.evaluate((r) => {
+ /* ERST AUFKLAPPEN, DANN WAEHLEN. Ein Klick auf ein Register
+ klappt die Leiste am Handy wieder zu -- das naechste waere
+ sonst nicht anklickbar. */
+ const leiste = document.getElementById("regieleiste");
+ if (leiste && leiste.dataset.auf !== "auf") {
+ document.getElementById("reiter-auf")?.click();
+ }
document.querySelector(`.reiter__knopf[data-tafel="${r}"]`)?.click();
}, reg);
await host.seite.waitForTimeout(250);
diff --git a/server/pruef-breiten.mjs b/server/pruef-breiten.mjs
index 1420c3b4..0bb12e0e 100644
--- a/server/pruef-breiten.mjs
+++ b/server/pruef-breiten.mjs
@@ -248,9 +248,36 @@ const messen = () => {
}
return false;
};
+ /* AUS DEM ROLLKASTEN GESCROLLT IST NICHT VERDECKT (01.10.2026).
+
+ Gemeldet war auf 1024, 1920 und 2560 Pixeln immer ein Feld aus
+ dem Pult „unter" einem Teil der Transportleiste -- und auf 1280
+ und 1440 nichts. Das Pult rollt in sich (`.pult__innen` hat eine
+ Hoechsthoehe); was unten herausgerollt ist, liegt rechnerisch
+ dort, wo die Leiste steht. `elementFromPoint` liefert dann die
+ Leiste.
+
+ Verdeckt ist es nicht -- es ist weggerollt, und man rollt zwei
+ Zentimeter und ist dran. Dieselbe Sorte Fehlalarm wie die
+ klebende Leiste und das dekorative SVG oben. */
+ const imRollkasten = (e, r) => {
+ for (let z = e.parentElement; z && z !== document.body; z = z.parentElement) {
+ const st = getComputedStyle(z);
+ if (!/auto|scroll|hidden/.test(st.overflowY + " " + st.overflowX)) continue;
+ const k = z.getBoundingClientRect();
+ /* Mehr als die Haelfte muss drin liegen -- ein Element, das
+ halb am Rand haengt, ist noch bedienbar. */
+ const hoch = Math.min(r.bottom, k.bottom) - Math.max(r.top, k.top);
+ const breit = Math.min(r.right, k.right) - Math.max(r.left, k.left);
+ if (hoch < r.height / 2 || breit < r.width / 2) return false;
+ }
+ return true;
+ };
+
for (const e of bedienbar.slice(0, 60)) {
const r = e.getBoundingClientRect();
if (r.bottom < 0 || r.top > window.innerHeight) continue; // ausserhalb des Fensters
+ if (!imRollkasten(e, r)) continue; // aus seinem Kasten gerollt
/* Fuenf Punkte statt einem: Mitte und die vier Viertelpunkte. */
const punkte = [[0.5, 0.5], [0.25, 0.3], [0.75, 0.3], [0.25, 0.7], [0.75, 0.7]];
let erreichbar = false;
@@ -297,7 +324,26 @@ let seitenGesamt = 0, elementeGesamt = 0;
const probleme = [];
for (const [breite, hoehe, wie] of BREITEN) {
- const kontext = await browser.newContext({ viewport: { width: breite, height: hoehe } });
+ /* MIT FINGER, WENN ES EIN FINGER WAERE (01.10.2026).
+
+ Hier stand nur die Fenstergroesse. Ohne `hasTouch` meldet der
+ Browser `pointer: fine`, und KEINE Regel aus
+ `@media (pointer: coarse)` greift -- dort stehen im ganzen Haus
+ die 44-Pixel-Beruehrziele, das Ausblenden der Tastenkuerzel und
+ seit heute die eingeklappte Reiterleiste. Auf 320, 390 und 430
+ Pixeln hat diese Pruefung also eine Seite vermessen, die es auf
+ keinem Telefon gibt, und daraus drei Befunde gemeldet.
+
+ Gefunden, weil ich einem dieser Befunde nachgegangen bin statt
+ ihm zu glauben: mess-quer misst dieselbe Seite auf 390x844 MIT
+ Finger und findet dort nichts.
+
+ 860 ist die Grenze des Hauses -- dieselbe wie in mess-reaktion,
+ mess-chat-optik und pruef-fingermass. */
+ const finger = breite <= 860;
+ const kontext = await browser.newContext({
+ viewport: { width: breite, height: hoehe },
+ hasTouch: finger, isMobile: finger });
const seite = await kontext.newPage();
const konsole = [];
seite.on("console", (m) => { if (m.type() === "error") konsole.push(m.text().slice(0, 70)); });
@@ -347,7 +393,9 @@ ok(elementeGesamt > 20000, `${elementeGesamt} Elemente vermessen`);
console.log(`\n=== Gegenprobe (muss anschlagen) ===`);
{
for (const testBreite of [320, 768, 1920]) {
- const kontext = await browser.newContext({ viewport: { width: testBreite, height: 900 } });
+ const kontext = await browser.newContext({
+ viewport: { width: testBreite, height: 900 },
+ hasTouch: testBreite <= 860, isMobile: testBreite <= 860 });
const seite = await kontext.newPage();
await seite.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" });
await seite.click('.rolle[data-rolle="admin"]');
diff --git a/server/pruef-fingermass.mjs b/server/pruef-fingermass.mjs
index 0c8f09c3..677117e6 100644
--- a/server/pruef-fingermass.mjs
+++ b/server/pruef-fingermass.mjs
@@ -106,7 +106,35 @@ export const fensterStellen = (text) => {
const rein = ohneKommentare(text);
for (const m of rein.matchAll(/newContext\s*\(\s*\{[\s\S]{0,400}?\}\s*\)/g)) {
const br = [...m[0].matchAll(/width\s*:\s*(\d{3,4})\b/g)].map((z) => Number(z[1]));
- if (!br.length) continue;
+ if (!br.length) {
+ /* ==== DER BLINDE FLECK DIESER WACHE (01.10.2026) ==========
+
+ Hier stand `continue` -- ein Fenster ohne Zahl galt als
+ nicht vorhanden. In pruef-breiten.mjs stand aber
+
+ newContext({ viewport: { width: breite, height: hoehe } })
+
+ und die Breite kam aus einer Schleife ueber neun
+ Geraete, darunter 320, 390 und 430 Pixel. Keine Zahl,
+ kein Treffer, „in Ordnung" -- und pruef-breiten meldete
+ daraufhin drei Befunde auf einer Seite, die es auf
+ keinem Telefon gibt.
+
+ Ohne Zahl laesst sich nicht sagen, ob das Fenster
+ schmal ist. Ob ein `hasTouch` danebensteht, sehr wohl --
+ und fehlt es, KANN das Fenster schmal sein und hat
+ keinen Finger. Das ist nicht „in Ordnung", sondern der
+ dritte Ausgang, und er bekommt eine eigene Zahl. */
+ /* NUR WENN EINE BREITE DASTEHT UND KEINE ZAHL IST. Ein
+ `newContext` ganz OHNE Breite ist das Standardfenster
+ (1280x720) -- kein Telefon. Ohne diese Einschraenkung
+ meldete die Wache 45 Faelle, darunter jedes
+ `newContext({ permissions: [...] })`. Eine Warnung, die
+ 45-mal kommt, nimmt die echte mit. */
+ const stehtBreite = /\bwidth\s*:/.test(m[0]);
+ if (stehtBreite && !/hasTouch/.test(m[0])) raus.push({ unklar: true });
+ continue;
+ }
raus.push({ schmal: br.some((x) => x <= SCHMAL), finger: /hasTouch/.test(m[0]) });
}
/* `setViewportSize` KANN `hasTouch` nicht nachtragen — es gehoert
@@ -153,7 +181,8 @@ if (dateien.length < 50) {
}
const funde = [];
-let blind = 0, mitFinger = 0, amTelefon = 0;
+const unklare = [];
+let blind = 0, mitFinger = 0, amTelefon = 0, unklar = 0;
for (const name of dateien) {
const text = readFileSync(join(ORDNER, name), "utf8");
const schmale = fensterStellen(text).filter((f) => f.schmal);
@@ -164,6 +193,15 @@ for (const name of dateien) {
if (b) { blind += b; funde.push(`${name} (${b})`); }
}
+/* Die unklaren getrennt -- sie koennen schmal sein, sie koennen es
+ auch nicht sein. Sie in die blinden einzurechnen waere geraten,
+ sie wegzulassen waere das, was heute den Fehler gedeckt hat. */
+for (const name of dateien) {
+ const u = fensterStellen(readFileSync(join(ORDNER, name), "utf8"))
+ .filter((f) => f.unklar).length;
+ if (u) { unklar += u; unklare.push(`${name} (${u})`); }
+}
+
console.log(` ${amTelefon} Dateien oeffnen ein Telefonformat, `
+ `${mitFinger} dieser Fenster haben einen Finger.`);
if (funde.length) console.log(" blinde Fenster mit Massband: " + funde.join(", "));
@@ -184,6 +222,44 @@ if (blind > GRUNDLINIE) {
ok(true, `${blind} blinde Fenster mit Massband — unveraendert zur Grundlinie ${GRUNDLINIE}`);
}
+/* ==== DIE DRITTE ZAHL (01.10.2026) ================================
+ Ein `newContext` ohne Zahl UND ohne `hasTouch`: Die Breite kommt
+ aus einer Variablen, und ob sie schmal ist, steht hier nicht. Das
+ ist kein Befund und kein Freispruch -- es ist die Frage, die
+ diese Wache nicht beantworten kann.
+
+ Sie bekommt eine eigene Grundlinie, damit sie weder
+ stillschweigend durchgeht noch die echte Zahl verfaelscht.
+
+ NEUNUNDDREISSIG, GEMESSEN AM 01.10.2026 -- und die Zahl ist
+ ernst. Stichprobe:
+
+ mess-chat-liste.mjs ["handy", 390, 860] ohne hasTouch
+ pruef-material.mjs ein Handy-Fall ohne hasTouch
+
+ Das sind Messungen, die bei Telefonbreiten eine Seite mit
+ MAUSZEIGER vermessen. Genau so hat pruef-breiten heute drei
+ Befunde gemeldet, die es auf keinem Telefon gibt.
+
+ WARUM SIE HIER ALS GRUNDLINIE STEHT UND NICHT ALS 39 FEHLER:
+ Eine Warnung, die bei jedem Lauf neununddreissigmal kommt, wird
+ weggeklickt und nimmt die echte mit. Die Zahl ist festgehalten,
+ sie darf nur SINKEN, und jede neue faellt sofort auf. Abgearbeitet
+ wird sie Datei fuer Datei -- jede einzeln, und jede mit einem
+ Lauf danach, denn bei pruef-breiten sind durch den Finger drei
+ Befunde verschwunden und haetten genauso gut drei neue
+ auftauchen koennen. */
+const UNKLAR_GRUNDLINIE = 39;
+if (unklare.length) console.log(" ohne Zahl und ohne Finger: " + unklare.join(", "));
+ok(unklar <= UNKLAR_GRUNDLINIE,
+ unklar <= UNKLAR_GRUNDLINIE
+ ? `${unklar} Fenster, deren Breite aus einer Variablen kommt und bei denen `
+ + `kein hasTouch danebensteht — Grundlinie ${UNKLAR_GRUNDLINIE}`
+ : `${unklar} Fenster mit Variable und ohne hasTouch (Grundlinie `
+ + `${UNKLAR_GRUNDLINIE}). Dort laesst sich nicht sagen, ob am Telefon gemessen `
+ + "wird — und genau so ist am 01.10. pruef-breiten durchgerutscht. "
+ + "Entweder hasTouch setzen oder die Breite als Zahl hinschreiben.");
+
console.log("\n=== 2. Gegenprobe: kann sie auch NICHT IN ORDNUNG sagen? ===");
const faelle = [
["der Fall vom 29.09. (schmal, misst, kein Finger)",
@@ -229,6 +305,34 @@ ok(daneben.length === 0,
daneben.length ? `Gegenprobe daneben bei: ${daneben.join(", ")}`
: `Gegenprobe: alle ${faelle.length} Faelle richtig eingeordnet`);
+/* ==== UND FUER DIE DRITTE ZAHL (01.10.2026) ======================
+ Sie meldet heute 0, und eine Zeile, die 0 meldet, sieht genauso
+ aus wie eine, die gar nichts finden kann. Genau das war sie bis
+ heute Mittag.
+
+ Eigene Tabelle, nicht in die obige hinein: Es ist eine andere
+ Frage, und ein Fall, der in beiden steht, wird irgendwann in
+ einer davon falsch gepflegt. */
+const unklarStellen = (text) => fensterStellen(text).filter((f) => f.unklar).length;
+const unklarFaelle = [
+ ["der Fall vom 01.10. (Breite aus einer Variablen, kein Finger)",
+ 'const c = await b.newContext({ viewport: { width: breite, height: hoehe } });', 1],
+ ["dieselbe Stelle MIT Finger",
+ 'const c = await b.newContext({ viewport: { width: breite, height: hoehe },\n'
+ + ' hasTouch: breite <= 860 });', 0],
+ ["eine Zahl ist keine Unklarheit — die beurteilt die Wache oben",
+ 'const c = await b.newContext({ viewport: { width: 390, height: 844 } });', 0],
+ ["ein Fenster ganz ohne Breite ist das Standardfenster, kein Telefon",
+ 'const c = await b.newContext({ permissions: ["notifications"] });', 0],
+];
+const unklarDaneben = unklarFaelle
+ .filter(([, text, soll]) => unklarStellen(text) !== soll)
+ .map(([n, text, soll]) => `${n} (${unklarStellen(text)} statt ${soll})`);
+ok(unklarDaneben.length === 0,
+ unklarDaneben.length
+ ? `Gegenprobe zur dritten Zahl daneben bei: ${unklarDaneben.join(", ")}`
+ : `Gegenprobe: alle ${unklarFaelle.length} Faelle der dritten Zahl richtig`);
+
console.log(`\n${ok_} Pruefungen, ${fehl} Fehler`);
console.log(fehl ? "NICHT IN ORDNUNG\n" : "ALLES IN ORDNUNG\n");
process.exit(fehl ? 1 : 0);
diff --git a/server/pruef-reaktion.mjs b/server/pruef-reaktion.mjs
index ffff5d79..7fe4c79b 100644
--- a/server/pruef-reaktion.mjs
+++ b/server/pruef-reaktion.mjs
@@ -1001,7 +1001,7 @@ melde("=== 12. Die Regie ===");
Uebrig bleibt genau das, was sich widersprechen KANN: zwei
Grundregeln, die beide sagen, WIE das Bauteil gebaut ist --
`grid` gegen `flex`, wie bei `.stufen`. */
- const positiv = (wert) => wert && wert !== "none" && !/^none/.test(wert);
+ const positiv = (wert) => wert && wert !== "none" && !/^none\b/.test(wert);
/* ZWEI EINSCHRAENKUNGEN MEHR, BEIDE AM 29.09.2026 NOETIG GEWORDEN.
diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html
index 5573de8b..3db8cc32 100644
--- a/workspace/anruf-probe.html
+++ b/workspace/anruf-probe.html
@@ -16,8 +16,8 @@
verdeckt. Gefunden hat es pruef-struktur.
Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. -->
-
-
+
+
-
+