Pipeline: die Stufenfarbe kommt endlich auf dem Bildschirm an

Filipe: "zuerst will ich dass du die kategorien und die kacheln viel
krasser geiler machst."

Beim Nachmessen stand fest, warum die Pipeline flach aussah: Drei
Regeln in scouting.css kamen gar nicht an, seit es den Baukasten
(module.css) gibt -- und module.css NENNT zwei davon im eigenen Text.

  --ton                  war an JEDER Karte #db4b66, dem Rot der Seite.
                         Daraus nimmt der Baukasten Kantenlicht, die
                         drei Eckwinkel und das Licht beim Zeigen. Sechs
                         Stufenfarben in der Datei, eine auf dem Schirm.
  .kk::before (3px)      gemessen 560px breit -- das ist das Kantenlicht
                         des Baukastens, das dasselbe Pseudoelement
                         belegt. Die farbige Pipeline-Kante gab es nicht.
  .kk { border } /:hover module.css setzt `border: 0`, gleich stark und
                         spaeter im Ladeweg.

Das Haus hatte die Lehre schon: aufgaben.css setzt `--ton` an fuenf
Spalten mit genau dieser Begruendung. Hierher uebertragen hat es nie
jemand.

WAS JETZT ANDERS IST
 * Jede Stufe traegt ihren Ton -- Eckwinkel, Kantenlicht und Hover
   laufen damit von kuehl (neu entdeckt) zu gruen (uebergeben).
 * Die Farbkante der Karte liegt im HINTERGRUND statt auf einem
   Pseudoelement (beide gehoeren dem Baukasten). 6px, weil das
   Kantenlicht 1,6px davon verdeckt -- bei 3px blieb nichts Sichtbares.
 * Etappennummern 01-05, abgeleitet aus WEITER statt daneben
   geschrieben. "Abgelehnt" bekommt keine: keine Etappe nach vorn.
 * Stufentitel in der eigenen Farbe (vorher einheitlich --akzent),
   mit Weiss aufgehellt -- 4,3:1 waeren bei fett-versal 12,5px zu wenig.
 * Faellig-Saum als inset-Schatten wie bei .kachel[data-warn], mit
   (0,3,0) gegen die Modulliste; vorher border-color und damit wirkungslos.
 * Karte: Plattform als Schild, Handle in gleichbreiter Schrift,
   Haarlinie zwischen "wer" und "lohnt sich", Reichweite deutlicher.

DAS MESSGERAET, DAS GEFEHLT HAT: module.css notiert "NICHT
MITREPARIERT, weil es kein Messgeraet dafuer gibt ... Hover laesst sich
nicht pruefen." Doch -- pruef-scouting-felder faehrt den Zeiger jetzt
auf die Karte und liest nach (6px -> 9px).

DREI FUNDE IN DEN EIGENEN WERKZEUGEN, alle von Hauswachen oder der
eigenen Messung:
 * bild-arten hatte keine Notbremse; page.hover() blieb haengen und
   liess beim Abbrechen einen Server auf Port 4336 zurueck. Jetzt
   notbremse(240s) und mouse.move statt hover().
 * color-mix(in srgb, var(--rand)) -- mit EINER Farbe ungueltig; der
   ganze Verlauf fiel aus, uebrig blieb Abstand ohne Linie.
 * Im Pruefausdruck steckte ein Backspace-Byte (0x08), das die
   Kommandozeile aus einer Zeichenfolge gemacht hatte. Sah im
   Quelltext richtig aus, traf nie. Jetzt startsWith.

pruef-scouting-felder: 64 -> 72 Pruefungen, gruen. Gegenprobe gefahren
(einer Stufe den Ton genommen -> rot, mit #db4b66 als Beleg). Statt des
226-Sekunden-Hauslaufs pruef-handy misst die Datei jetzt selbst auf
320px: 97 Teile, keines ueber dem Rand, kein seitliches Schieben.
Dazu gruen: css-klassen, lesbarkeit, tippziele, fingermass,
haus-trennung, leerzustand, deutsche-texte, zeichen (der eine Rest dort
ist bereich.css und aelter).

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-10-07 00:04:49 +02:00
co-authored by Claude Opus 5
parent f18ab32f8c
commit ea4078740e
50 changed files with 1164 additions and 721 deletions
+117
View File
@@ -466,6 +466,95 @@ console.log("\n=== Die Seite selbst ===");
await seite.click("#neu-zu");
await seite.waitForTimeout(250);
/* ===== DIE OPTIK DER STUFE KOMMT WIRKLICH AN (06.10.2026) ========
module.css notiert selbst: „`.kk:hover` in scouting.css ... setzt
border-color -- und die Grundregel oben setzt `border: 0`, gleich
stark und spaeter im Ladeweg. Diese vier Regeln tun also vermutlich
nichts." Und: „NICHT MITREPARIERT, weil es kein Messgeraet dafuer
gibt ... Hover laesst sich nicht pruefen."
DOCH -- es laesst sich pruefen. Hier steht das Messgeraet.
ERST DEN ZEIGER WEGSETZEN. Beim ersten Anlauf meldete diese
Messung „die Kante ist 9px statt 6" und „unter dem Zeiger waechst
sie nicht (9 -> 9)" -- beides stimmte, und beides war kein Befund
am Programm: Der Klick auf „Bearbeiten" weiter oben hatte die Maus
auf der ersten Karte stehen lassen. Gemessen wurde also zweimal der
Zustand UNTER dem Zeiger. Eine Messung, die ihren Ausgangszustand
nicht herstellt, misst den Rest des Tests mit. */
await seite.mouse.move(2, 2);
await seite.waitForTimeout(300);
const optik = await seite.$$eval(".stufe", (gs) => gs.map((g) => {
const k = g.querySelector(".kk");
const s2 = k ? getComputedStyle(k) : null;
return {
stufe: g.dataset.stufe,
ton: getComputedStyle(g).getPropertyValue("--ton").trim(),
farbe: getComputedStyle(g).getPropertyValue("--stufe-farbe").trim(),
kante: s2 ? s2.getPropertyValue("--kante").trim() : null,
kantenbreite: s2 ? s2.backgroundSize.split(",")[0].trim() : null,
nr: g.querySelector(".stufe__nr")?.textContent.trim() || null,
};
}));
/* JEDE Stufe traegt IHREN Ton -- nicht den der Seite. Gezaehlt wird
in der Bedingung, nicht nur im Text: Ein `every()` auf einer leeren
Liste waere `true` und wuerde nichts beweisen. */
ok(optik.length >= 3 && optik.every((o) => o.ton && o.ton === o.farbe),
`jede der ${optik.length} Stufen traegt ihren eigenen Ton `
+ `(${optik.map((o) => o.stufe + "=" + o.ton).join(", ")})`);
/* Und die Toene sind verschieden -- sonst waere „jede traegt ihren
eigenen" auch dann wahr, wenn alle denselben haetten. */
ok(new Set(optik.map((o) => o.ton)).size === optik.length,
`und zwar jede eine andere (${new Set(optik.map((o) => o.ton)).size} Toene auf ${optik.length} Stufen)`);
/* `backgroundSize` liefert BEIDE Masse der ersten Ebene ("6px 100%").
Der erste Anlauf verglich mit "6px" und meldete rot, obwohl ueberall
6px standen -- ein Messfehler, der wie ein Befund aussah.
DER ZWEITE ANLAUF MELDETE DASSELBE, und die Ursache war eine
andere: Beim Schreiben ueber die Kommandozeile wurde aus der
Zeichenfolge fuer eine Wortgrenze ein echtes Steuerzeichen (0x08,
Backspace) mitten im Ausdruck. Ein Ausdruck mit einem Backspace
darin trifft natuerlich nie. Im Quelltext sah die Zeile voellig
richtig aus -- sichtbar wurde das Byte erst mit `cat -v`. Genau
davor warnt pruef-zeichen ("Serverdateien mit Steuerzeichen"), und
genau sie haette es gefunden.
Deshalb jetzt `startsWith` statt eines Ausdrucks: Daran gibt es
nichts, was beim Schreiben verstuemmelt werden koennte. */
ok(optik.length >= 3 && optik.every((o) => (o.kantenbreite || "").startsWith("6px")),
`die Farbkante der Karte ist 6px breit (${optik.map((o) => o.kantenbreite).join(", ")})`);
/* Die Etappennummer wird aus WEITER abgeleitet: 01 bis 05, und
„abgelehnt" bekommt keine. */
const nummern = Object.fromEntries(optik.map((o) => [o.stufe, o.nr]));
ok(nummern.neu === "01" && nummern.angesprochen === "02",
`die Stufen sind nummeriert (neu=${nummern.neu}, angesprochen=${nummern.angesprochen})`);
/* HOVER -- gemessen mit dem Zeiger, nicht geglaubt.
`mouse.move` und nicht `page.hover()`: Letzteres wartet auf
„bedienbar" und blieb beim ersten Anlauf haengen. Gemessen werden
soll hier die Farbe, nicht die Bedienbarkeit. */
const vorher = await seite.$eval(".kk", (k) => getComputedStyle(k).getPropertyValue("--kante").trim());
const mitte = await seite.$eval(".kk", (k) => {
const r = k.getBoundingClientRect();
return { x: Math.round(r.x + r.width / 2), y: Math.round(r.y + r.height / 2) };
});
await seite.mouse.move(mitte.x, mitte.y);
await seite.waitForTimeout(350);
const nachher = await seite.$eval(".kk", (k) => getComputedStyle(k).getPropertyValue("--kante").trim());
ok(vorher === "6px" && nachher === "9px",
`unter dem Zeiger waechst die Kante (${vorher} -> ${nachher})`);
await seite.mouse.move(0, 0);
await seite.waitForTimeout(200);
/* Die Haarlinie in der Karte. Ein ungueltiger Farbwert laesst
`border-image` lautlos ausfallen -- „none" heisst, sie fehlt. */
const haar = await seite.$eval(".kk__info",
(k) => getComputedStyle(k).borderImageSource);
ok(haar.includes("gradient"),
`die Haarlinie zwischen Kopf und Zahlen ist da (${haar.slice(0, 28)}…)`);
/* ===== GEGENPROBE: AUF DEM HANDY LIEGEN SIE UNTEREINANDER ========
Ohne diese Messung wuesste niemand, ob die Trennung ueberhaupt
@@ -500,6 +589,34 @@ console.log("\n=== Die Seite selbst ===");
ok(schmal.every((k) => k.breite >= 300),
`keine Spalte wird gequetscht (${schmal.map((k) => k.breite).join(" / ")} px)`);
/* ===== UND AUF DEM SCHMALSTEN GERAET, DAS ES GIBT (320 px) =======
Die Karte hat links 26px Polster bekommen (davor 21), dazu eine
6px-Kante. Was auf 390px passt, muss auf 320px nicht passen -- und
ein Element, das ueber den Rand steht, erzeugt seitliches Scrollen
auf der ganzen Seite.
GEMESSEN STATT DEN HAUSLAUF GESTARTET: `pruef-handy` prueft 186
Dinge auf vielen Seiten und braucht 226 Sekunden. Die Frage hier
ist eine einzige und in vier Sekunden beantwortet. */
const engKontext = await browser.newContext({
viewport: { width: 320, height: 720 }, hasTouch: true, isMobile: true,
});
await engKontext.addCookies(await ctx.cookies());
const eng = await engKontext.newPage();
await eng.goto(seite.url(), { waitUntil: "networkidle" });
await eng.waitForTimeout(900);
const ueber = await eng.$$eval(".stufe *", (ks) => ks
.filter((k) => k.getBoundingClientRect().right > window.innerWidth + 1)
.slice(0, 4)
.map((k) => `${k.className || k.tagName} bis ${Math.round(k.getBoundingClientRect().right)}px`));
const gemessen = await eng.$$eval(".stufe *", (ks) => ks.length);
ok(gemessen > 20 && ueber.length === 0,
`auf 320px steht keines der ${gemessen} Teile ueber den Rand (${ueber.join(", ") || "keins"})`);
const quer = await eng.evaluate(() =>
document.documentElement.scrollWidth - document.documentElement.clientWidth);
ok(quer <= 1, `und die Seite laesst sich nicht seitlich schieben (${quer} px)`);
await browser.close();
}