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
+86
View File
@@ -12,6 +12,19 @@
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
/* NOTBREMSE (nachgeruestet 06.10.2026, nachdem genau das passiert ist).
Dieses Werkzeug startet einen Server und einen Browser. Beim Versuch,
die Farbkante unter dem Zeiger zu messen, blieb `page.hover()` haengen
-- und ein Stillstand sieht von aussen genauso aus wie "laeuft noch".
Schlimmer: Nach dem Abbrechen von aussen blieb der Server auf Port
4336 stehen und haette den naechsten Lauf blockiert.
Dieselbe Regel wie fuer die Pruefungen, und aus demselben Grund: Eine
Frist, die ueberschritten wird, ist ein FEHLER mit Meldung -- kein
Warten ohne Ende. */
import { notbremse } from "./helfer-notbremse.mjs";
notbremse(240_000, "bild-arten");
const ordner = mkdtempSync(join(tmpdir(), "ws-arten-"));
process.env.WORKSPACE_DB = join(ordner, "workspace.db");
@@ -104,6 +117,79 @@ for (const s of spalten) {
console.log(` ${String(s.stufe).padEnd(14)} ${String(s.titel).padEnd(8)} ${String(s.zahl).padStart(2)} `
+ `x=${String(s.x).padStart(4)} b=${String(s.breite).padStart(4)} Linie=${s.linie.padStart(5)} ${s.namen}`);
}
/* WAS KOMMT AN DER KARTE WIRKLICH AN? (06.10.2026)
`module.css` belegt `::before` (Kantenlicht) und `::after` (Raster,
Eckwinkel) JEDER Karte und wird NACH scouting.css geladen. Was
scouting.css auf dieselben Pseudoelemente legt, verliert damit --
ohne dass irgendwo ein Fehler erscheint. Diese Messung sagt, welcher
Ton tatsaechlich gilt und wie breit die farbige Kante wirklich ist. */
console.log("\n--- Was an der Karte wirklich ankommt ---");
const kante = await seite.$eval(".kk", (k) => {
const vor = getComputedStyle(k, "::before");
return {
ton: getComputedStyle(k).getPropertyValue("--ton").trim() || "(nicht gesetzt)",
stufenfarbe: getComputedStyle(k).getPropertyValue("--stufe-farbe").trim() || "(nicht gesetzt)",
vorBreite: vor.width, vorInhalt: vor.content,
grund: getComputedStyle(k).backgroundImage.slice(0, 60),
};
});
console.log(" --ton:", kante.ton, " --stufe-farbe:", kante.stufenfarbe);
console.log(" ::before Breite:", kante.vorBreite, " (3px = Kante von scouting.css, sonst ueberschrieben)");
console.log(" Grundbild:", kante.grund);
/* WIE BREIT IST DIE FARBKANTE WIRKLICH -- und kommt sie durch?
Gemessen wird nicht die Regel, sondern das Bild: die Farbe des
Bildpunktes zwei Pixel rechts von der linken Kartenkante, einmal in
Ruhe und einmal unter dem Zeiger. Eine Kante, die man nur im
Quelltext sieht, ist keine. */
const kantenMass = await seite.evaluate(() => {
const k = document.querySelector(".kk");
const s = getComputedStyle(k);
return { groesse: s.backgroundSize, lage: s.backgroundPosition, kante: s.getPropertyValue("--kante").trim() };
});
console.log(" background-size:", kantenMass.groesse, "| --kante:", kantenMass.kante || "(nicht gesetzt)");
/* MIT mouse.move AUF DIE MITTE DER KARTE, NICHT MIT page.hover().
`hover()` wartet darauf, dass das Ziel "bedienbar" ist -- sichtbar,
stabil, nicht verdeckt. Bei einer Karte, ueber der das Hintergrundbild
der Seite liegt, kann diese Pruefung dreissig Sekunden brauchen oder
nie fertig werden. Gemessen werden soll hier aber nicht die
Bedienbarkeit, sondern was der Zeiger an der Farbe aendert -- dafuer
genuegt es, den Zeiger hinzubewegen. */
{
const m = 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(m.x, m.y);
await seite.waitForTimeout(400);
}
const unterZeiger = await seite.evaluate(() =>
getComputedStyle(document.querySelector(".kk")).getPropertyValue("--kante").trim());
console.log(" --kante unter dem Zeiger:", unterZeiger || "(nicht gesetzt)");
/* Kommt die Haarlinie zwischen Kopf und Zahlen an? Ein ungueltiger
Farbwert laesst `border-image` lautlos ausfallen -- uebrig bleibt
Abstand ohne Linie, und das sieht im Quelltext richtig aus. */
const linie = await seite.$eval(".kk__info", (k) => {
const s2 = getComputedStyle(k);
return { quelle: s2.borderImageSource.slice(0, 48), breite: s2.borderTopWidth };
});
console.log(" Haarlinie in der Karte:", linie.breite, "|", linie.quelle);
/* Eine Nahaufnahme der linken Kante -- 90 px breit, damit man sie
ueberhaupt sehen kann. */
/* Eine Karte OHNE Faellig-Saum: Bei Tamy liegt der warme Innenring
ueber der Stufenkante, und dann misst man den Ring statt der Kante. */
const kasten = await seite.$eval(".kk:not([data-faellig])", (k) => {
const r = k.getBoundingClientRect();
/* `width`/`height` -- nicht `w`/`h`. Playwright meldet dann
"clip.width: expected float, got undefined"; gefunden hat es die
Notbremse, nicht das Auge. */
return { x: Math.round(r.x), y: Math.round(r.y), width: 90, height: Math.round(r.height) };
});
await seite.screenshot({ path: "server/bild-arten-kante.png", clip: kasten });
await seite.mouse.move(0, 0);
await seite.waitForTimeout(300);
const stufe1 = await seite.$('.stufe[data-stufe="neu"]');
await stufe1.screenshot({ path: "server/bild-arten-rechner.png" });
await seite.screenshot({ path: "server/bild-arten-rechner-ganz.png", fullPage: false });