CRYONOVA Schritt 3: Feldfokus, Blickfaenge, Testkorrekturen
Der Feldfokus zeigt jetzt den Ion-Rand und den weichen Schein, den das
Design-System auf Seite 15 verlangt. Er fehlte, weil der allgemeine
Tastaturring seinen dunklen Innenring darueberlegte: Dessen Selektor hat
Spezifitaet 0,3,0, die Feldregel nur 0,2,1 -- und Spezifitaet schlaegt
Reihenfolge, egal wie weit unten die Regel steht. Eingabefelder sind
jetzt vom Innenring ausgenommen; sie brauchen ihn nicht, weil sie selbst
eine dunkle Flaeche sind. Der Aqua-Umriss bleibt fuer alle erhalten.
Die zwei Blickfang-Motive stehen jetzt auch wirklich auf einer Seite:
das Wappen auf "Ueber mich", direkt nach dem Absatz ueber die Herkunft
des Namens, der Monolith auf "Portfolio" zwischen Einleitung und den
echten Projekten. Beide als Zierbild ausgezeichnet -- ihre Aussage steht
schon im Text daneben. Auf dem Handy laedt automatisch die kleine
Fassung.
Vier Fehler steckten in der Pruefung selbst, nicht im Stilblatt:
- Sie griff das erste "input" der Anfrageseite. Das sind aber sechs
optisch versteckte Auswahl-Radios, kein Textfeld.
- Sie mass ohne Fensterfokus. Ein Browser wendet :focus nur an, wenn das
Fenster selbst den Fokus hat -- das DOM meldet trotzdem brav
matches(":focus") === true, die Farbe bleibt die alte.
- Sie mass mitten im Uebergang, bevor die Animation stand.
- Und sie zaehlte Schattenebenen an "),", einem Muster, das in keinem
Schattenwert je vorkommt. Geprueft wird jetzt die Anforderung selbst:
Ion-Farbe und ein Weichzeichner ueber 0.
Geprueft: 334 Pruefungen gruen (CRYONOVA 53, Blickfang 13, Abmelden 16,
Angebot 54, Abbruch 42, System 5, Automatik 55, Angebote 56, Kette 40).
Co-Authored-By: Claude Opus 5 <[email protected]>
@@ -2556,7 +2556,20 @@ a.wd-karte:active, .wd-karte--klickbar:active {
|
||||
.wd :is(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
|
||||
outline: 2px solid rgb(var(--wd-aqua-rgb));
|
||||
outline-offset: 2px;
|
||||
/* Der dunkle Innenring trennt das Aqua von hellen Flaechen. */
|
||||
}
|
||||
|
||||
/* Der dunkle Innenring trennt das Aqua von hellen Flaechen.
|
||||
|
||||
Eingabefelder sind hier BEWUSST ausgenommen: Sie sind selbst eine
|
||||
dunkle, vertiefte Flaeche, das Aqua hebt sich davon ohnehin ab. Ein
|
||||
Innenring waere nicht nur ueberfluessig, er ueberschreibt auch den
|
||||
Ion-Schein, den das System auf Seite 15 fuer den Feldfokus verlangt.
|
||||
|
||||
Warum die Ausnahme im Selektor stehen muss und nicht einfach weiter
|
||||
unten ueberschrieben wird: Diese Regel hat Spezifitaet 0,3,0
|
||||
(Klasse + :is + :focus-visible), die Feldregel nur 0,2,1 -- und
|
||||
Spezifitaet schlaegt Reihenfolge, egal wie weit unten sie steht. */
|
||||
.wd :is(a, button, summary, [tabindex]):focus-visible {
|
||||
box-shadow: 0 0 0 4px rgb(3 8 16 / .85);
|
||||
}
|
||||
|
||||
@@ -2641,3 +2654,188 @@ a.wd-karte:active, .wd-karte--klickbar:active {
|
||||
.wd-status--kritisch { background: rgb(var(--wd-fehler-rgb) / .13); color: var(--wd-fehler); border-color: rgb(var(--wd-fehler-rgb) / .35); }
|
||||
.wd-status--pausiert { background: rgb(var(--wd-chrome-rgb) / .12); color: var(--wd-chrome); border-color: rgb(var(--wd-chrome-rgb) / .30); }
|
||||
.wd-status--vip { background: rgb(var(--wd-gold-rgb) / .13); color: var(--wd-gold); border-color: rgb(var(--wd-gold-rgb) / .35); }
|
||||
|
||||
/* =====================================================================
|
||||
SIGNATURE-VERLAEUFE (Design-System Seite 18)
|
||||
|
||||
Vier Verlaeufe mit je einer klaren Aufgabe. Das System gibt dazu eine
|
||||
Dosierungsregel, die wichtiger ist als die Verlaeufe selbst:
|
||||
|
||||
"Maximal ein Signature-Verlauf pro sichtbarer Bildschirmhoehe.
|
||||
Keine Regenbogenflaechen. Kein Vollflaechen-Neon.
|
||||
Champagne niemals mit Violet mischen."
|
||||
|
||||
Das letzte Verbot ist keine Geschmacksfrage: Champagne steht fuer
|
||||
Treue und Bezahltes, Violet fuer Spezielles. Mischt man beides, kann
|
||||
niemand mehr ablesen, was eine Flaeche bedeutet -- und genau die
|
||||
Ablesbarkeit ist der Zweck eines Farbsystems.
|
||||
|
||||
Deshalb sind es HILFSKLASSEN und keine Vorgabe auf Kacheln: Ein
|
||||
Verlauf, der automatisch auf jeder Karte laege, waere sofort eine
|
||||
Regenbogenflaeche. Man setzt ihn bewusst an eine Stelle.
|
||||
===================================================================== */
|
||||
|
||||
/* CRYO FLOW -- primaere Energie. Baby zu Ion zu Aqua. */
|
||||
.wd-verlauf--cryo {
|
||||
background: linear-gradient(135deg,
|
||||
rgb(var(--wd-blau-rgb) / .95) 0%,
|
||||
rgb(var(--wd-ion-rgb) / .90) 50%,
|
||||
rgb(var(--wd-aqua-rgb) / .85) 100%);
|
||||
}
|
||||
|
||||
/* PRISM SHIFT -- Premium und Fokus. Ion zu Indigo. */
|
||||
.wd-verlauf--prisma {
|
||||
background: linear-gradient(135deg,
|
||||
rgb(var(--wd-ion-rgb) / .92) 0%,
|
||||
rgb(var(--wd-indigo-rgb) / .92) 100%);
|
||||
}
|
||||
|
||||
/* AURORA CUT -- Spezialmoment. Indigo zu Violet. */
|
||||
.wd-verlauf--aurora {
|
||||
background: linear-gradient(135deg,
|
||||
rgb(var(--wd-indigo-rgb) / .90) 0%,
|
||||
rgb(var(--wd-lila-rgb) / .90) 100%);
|
||||
}
|
||||
|
||||
/* LIQUID VALUE -- VIP und Treue. Champagne allein, mit einer dunklen
|
||||
Tiefe statt einer zweiten Akzentfarbe: Das System verbietet die
|
||||
Mischung mit Violet ausdruecklich. */
|
||||
.wd-verlauf--liquid {
|
||||
background: linear-gradient(135deg,
|
||||
rgb(var(--wd-gold-rgb) / .92) 0%,
|
||||
rgb(var(--wd-gold-rgb) / .55) 55%,
|
||||
rgb(var(--wd-dunkelblau-2)) 100%);
|
||||
}
|
||||
|
||||
/* Text auf einem Signature-Verlauf braucht immer dunkle Schrift --
|
||||
alle vier sind hell genug, dass helle Schrift darauf verschwindet. */
|
||||
.wd-verlauf--cryo, .wd-verlauf--prisma,
|
||||
.wd-verlauf--aurora, .wd-verlauf--liquid { color: var(--wd-schwarz); }
|
||||
|
||||
/* =====================================================================
|
||||
FORMULARE UND TABELLEN (Design-System Seite 15)
|
||||
|
||||
"Fokus: Eingabefeld erhaelt Ion-Blue-Rand und sanften Glow.
|
||||
Tabellenzeile erhaelt beim Hover ein sehr schwaches,
|
||||
positionsabhaengiges Licht."
|
||||
|
||||
Das Wort "sehr schwach" ist hier die eigentliche Anweisung. Eine
|
||||
Tabelle ist zum Lesen da: Wandert beim Ueberfahren ein kraeftiges
|
||||
Licht mit, springt der Blick staendig zur Maus statt zur Zahl, die
|
||||
man eigentlich sucht. Deshalb liegt die Deckkraft hier bei einem
|
||||
Bruchteil dessen, was eine Kachel bekommt.
|
||||
===================================================================== */
|
||||
|
||||
/* Der Fokus im Eingabefeld: Ion-Rand plus weicher Schein.
|
||||
Die Vertiefung bleibt erhalten -- sonst springt das Feld beim
|
||||
Anklicken optisch aus der Flaeche heraus. */
|
||||
.wd-feld input:focus, .wd-feld select:focus, .wd-feld textarea:focus,
|
||||
.wd-eingabe:focus {
|
||||
border-color: rgb(var(--wd-ion-rgb) / .85);
|
||||
box-shadow:
|
||||
var(--wd-tiefe),
|
||||
0 0 0 4px rgb(var(--wd-ion-rgb) / .16),
|
||||
0 0 18px -4px rgb(var(--wd-ion-rgb) / .45);
|
||||
}
|
||||
|
||||
/* Ein Feld mit Fehler traegt IMMER auch Text -- die Farbe allein
|
||||
waere fuer niemanden lesbar, der sie nicht unterscheiden kann. */
|
||||
.wd-feld--fehler input, .wd-feld--fehler select, .wd-feld--fehler textarea {
|
||||
border-color: rgb(var(--wd-fehler-rgb) / .7);
|
||||
}
|
||||
.wd-feld--fehler input:focus, .wd-feld--fehler select:focus,
|
||||
.wd-feld--fehler textarea:focus {
|
||||
box-shadow:
|
||||
var(--wd-tiefe),
|
||||
0 0 0 4px rgb(var(--wd-fehler-rgb) / .18);
|
||||
}
|
||||
|
||||
/* ---------- Tabellen ---------- */
|
||||
.wd-tabelle {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: .92rem;
|
||||
}
|
||||
.wd-tabelle th {
|
||||
text-align: left;
|
||||
font-size: .74rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: .06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--wd-text-soft);
|
||||
padding: .6rem .8rem;
|
||||
border-bottom: 1px solid rgb(var(--wd-blau-rgb) / .22);
|
||||
}
|
||||
.wd-tabelle td {
|
||||
padding: .7rem .8rem;
|
||||
border-bottom: 1px solid rgb(255 255 255 / .05);
|
||||
color: var(--wd-text-mid);
|
||||
}
|
||||
/* Zahlen in gleicher Ziffernbreite: Sonst stehen Betraege in einer
|
||||
Spalte nicht untereinander, und man vergleicht sie falsch. */
|
||||
.wd-tabelle td.wd-zahl, .wd-tabelle th.wd-zahl {
|
||||
text-align: right;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
.wd-tabelle tbody tr {
|
||||
--wd-lichtx: 50%;
|
||||
position: relative;
|
||||
transition: background-color .2s ease;
|
||||
}
|
||||
/* Das positionsabhaengige Licht der Zeile -- bewusst nur 7 %, ein
|
||||
Viertel dessen, was eine Kachel bekommt. Es soll die Zeile
|
||||
nachzeichnen, nicht den Blick fangen. */
|
||||
.wd-tabelle tbody tr:hover {
|
||||
background: linear-gradient(90deg,
|
||||
transparent 0%,
|
||||
rgb(var(--wd-blau-rgb) / .07) var(--wd-lichtx),
|
||||
transparent 100%);
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.wd-tabelle tbody tr:hover { background: rgb(var(--wd-blau-rgb) / .05); }
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
KACHEL-ANATOMIE (Design-System Seite 11)
|
||||
|
||||
Das System beschreibt sechs Bestandteile: Material (Obsidian Glass
|
||||
statt flacher Farbe), Kante (1 px Baby Blue, 24-36 % Deckkraft),
|
||||
Lumen, Inhalt ueber dem Licht, Tiefe (zarter Schatten plus innere
|
||||
Lichtkante) und Zustand.
|
||||
|
||||
Fuenf davon standen bereits. Was fehlte, ist die INNERE LICHTKANTE:
|
||||
eine haarfeine helle Linie an der Oberkante. Sie ist der Unterschied
|
||||
zwischen "dunkles Rechteck" und "Objekt aus Glas" -- Licht faellt von
|
||||
oben, also faengt die obere Kante es ein. Ohne sie wirkt jede Kachel
|
||||
flach, egal wie gut die Farben sind.
|
||||
===================================================================== */
|
||||
.wd-karte {
|
||||
/* BEIDE Hintergrundebenen, nicht nur eine.
|
||||
|
||||
Die Kachel baut ihre Kante ueber einen zweiten Verlauf auf der
|
||||
border-box -- der Rahmen selbst ist durchsichtig. Ein erster
|
||||
Versuch setzte hier nur die Flaeche (padding-box) und liess die
|
||||
Randebene damit ersatzlos wegfallen: Der Rand mass danach
|
||||
rgba(0,0,0,0), also gar nichts. Sichtbar war das kaum, messbar
|
||||
sofort -- und das System verlangt ausdruecklich eine Kante von
|
||||
1 px Baby Blue mit 24-36 % Deckkraft (Seite 11). */
|
||||
background:
|
||||
linear-gradient(180deg,
|
||||
rgb(var(--wd-glas-rgb) / .58),
|
||||
rgb(6 19 35 / .72)) padding-box,
|
||||
linear-gradient(140deg,
|
||||
rgb(var(--wd-blau-rgb) / .36),
|
||||
rgb(var(--wd-blau-rgb) / .10) 45%,
|
||||
rgb(var(--wd-lila-rgb) / .26)) border-box;
|
||||
/* Die innere Lichtkante: eine haarfeine helle Linie oben. Sie ist
|
||||
der Unterschied zwischen "dunkles Rechteck" und "Objekt aus
|
||||
Glas" -- Licht faellt von oben, also faengt die obere Kante es
|
||||
ein. Ohne sie wirkt jede Kachel flach, egal wie gut die Farben
|
||||
sind. */
|
||||
box-shadow:
|
||||
var(--wd-hoehe-1),
|
||||
inset 0 1px 0 rgb(var(--wd-blau-rgb) / .16);
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 304 KiB |
|
After Width: | Height: | Size: 960 KiB |
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 914 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 161 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1,76 @@
|
||||
/* Prueft, dass die beiden Blickfang-Motive wirklich ankommen: richtige
|
||||
Datei je Geraet, sichtbare Groesse, und keine 404 auf dem Weg. */
|
||||
import { chromium } from "playwright";
|
||||
import http from "http";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
const TYP = {
|
||||
".html": "text/html", ".css": "text/css", ".js": "text/javascript",
|
||||
".png": "image/png", ".svg": "image/svg+xml", ".webp": "image/webp",
|
||||
".json": "application/json", ".ico": "image/x-icon", ".jpg": "image/jpeg",
|
||||
};
|
||||
|
||||
const fehlt = [];
|
||||
const srv = http.createServer((q, r) => {
|
||||
const u = decodeURIComponent(q.url.split("?")[0]);
|
||||
const p = path.join(process.cwd(), u);
|
||||
if (fs.existsSync(p) && !p.endsWith("/")) {
|
||||
r.writeHead(200, { "content-type": TYP[path.extname(p)] || "text/plain" });
|
||||
return r.end(fs.readFileSync(p));
|
||||
}
|
||||
fehlt.push(u);
|
||||
r.writeHead(404);
|
||||
r.end("");
|
||||
});
|
||||
|
||||
let ok = 0, fehl = 0;
|
||||
const pruefe = (name, gut, info) => {
|
||||
if (gut) { ok++; console.log(" ok " + name + (info ? " -> " + info : "")); }
|
||||
else { fehl++; console.log(" FEHL " + name + (info ? " -> " + info : "")); }
|
||||
};
|
||||
|
||||
srv.listen(4402, async () => {
|
||||
const browser = await chromium.launch();
|
||||
|
||||
for (const [seite, kl] of [["ueber", "wappen"], ["portfolio", "monolith"]]) {
|
||||
for (const [gr, vp] of [["pc", { width: 1440, height: 950 }],
|
||||
["handy", { width: 390, height: 844 }]]) {
|
||||
const s = await browser.newPage({ viewport: vp });
|
||||
await s.goto(`http://127.0.0.1:4402/webdesign/${seite}.html`);
|
||||
await s.waitForTimeout(1400);
|
||||
|
||||
const el = s.locator(".wd-blickfang--" + kl);
|
||||
const r = await el.evaluate((e) => {
|
||||
const c = getComputedStyle(e);
|
||||
const b = e.getBoundingClientRect();
|
||||
const treffer = c.backgroundImage.match(/img\/([a-z0-9-]+\.webp)/i);
|
||||
return {
|
||||
datei: treffer ? treffer[1] : "(keins)",
|
||||
h: Math.round(b.height), w: Math.round(b.width),
|
||||
versteckt: e.getAttribute("aria-hidden"),
|
||||
};
|
||||
});
|
||||
|
||||
/* Auf dem Handy MUSS die kleine Fassung kommen -- sonst laedt ein
|
||||
Telefon ueber Mobilfunk die volle Datei fuer nichts. */
|
||||
const richtig = gr === "handy" ? r.datei.includes("-klein") : !r.datei.includes("-klein");
|
||||
pruefe(`${seite}/${gr}: richtige Bilddatei`, richtig, r.datei);
|
||||
pruefe(`${seite}/${gr}: sichtbar gross`, r.h > 80 && r.w > 200, `${r.w}x${r.h}`);
|
||||
pruefe(`${seite}/${gr}: als Zierbild ausgezeichnet`, r.versteckt === "true", r.versteckt);
|
||||
|
||||
await el.scrollIntoViewIfNeeded();
|
||||
await s.waitForTimeout(700);
|
||||
await s.screenshot({ path: `blickfang-${seite}-${gr}.png` });
|
||||
await s.close();
|
||||
}
|
||||
}
|
||||
|
||||
const verpasst = fehlt.filter((f) => /\.(webp|png|css|js|svg)$/.test(f));
|
||||
pruefe("keine fehlenden Dateien", verpasst.length === 0, verpasst.join(", ") || "keine");
|
||||
|
||||
console.log(`\n===== ${ok} bestanden, ${fehl} fehlgeschlagen =====`);
|
||||
await browser.close();
|
||||
srv.close();
|
||||
process.exit(fehl ? 1 : 0);
|
||||
});
|
||||
@@ -77,6 +77,14 @@ const hexZuRgb = (h) => [1, 3, 5].map((i) => parseInt(h.substr(i, 2), 16));
|
||||
|
||||
const browser = await chromium.launch();
|
||||
const seite = await browser.newPage({ viewport: { width: 1440, height: 950 } });
|
||||
|
||||
/* Ohne das misst jede :focus-Pruefung den Ruhezustand. Ein Browser
|
||||
wendet :focus nur an, wenn das FENSTER selbst den Fokus hat -- im
|
||||
Testlauf hat es den nie. Das DOM meldet trotzdem brav
|
||||
element.matches(":focus") === true, die Farbe bleibt aber die alte.
|
||||
Genau diese Kombination hat hier zwei Fehlalarme erzeugt. */
|
||||
const cdp = await seite.context().newCDPSession(seite);
|
||||
await cdp.send("Emulation.setFocusEmulationEnabled", { enabled: true });
|
||||
await seite.goto("http://127.0.0.1:4372/webdesign/index.html");
|
||||
await seite.waitForTimeout(500);
|
||||
|
||||
@@ -399,6 +407,116 @@ for (const b of bilder) {
|
||||
pruefe("alle Motive sind vorhanden und unter 300 KB",
|
||||
zuGross.length === 0, zuGross.join(", ") || "alle schlank");
|
||||
|
||||
console.log("\n=== 12. SIGNATURE-VERLAEUFE (Seite 18) ===");
|
||||
await seite.goto("http://127.0.0.1:4372/webdesign/index.html");
|
||||
await seite.waitForTimeout(400);
|
||||
|
||||
const verlaeufe = await seite.evaluate(() => {
|
||||
const alle = Array.from(document.styleSheets)
|
||||
.flatMap((b) => { try { return Array.from(b.cssRules); } catch { return []; } });
|
||||
const text = alle.map((r) => r.cssText).join("\n");
|
||||
const gefunden = ["cryo", "prisma", "aurora", "liquid"]
|
||||
.filter((n) => text.includes(".wd-verlauf--" + n));
|
||||
|
||||
/* Champagne NIEMALS mit Violet mischen (Seite 18). Das ist keine
|
||||
Geschmacksfrage: Champagne steht fuer Treue und Bezahltes, Violet
|
||||
fuer Spezielles. Gemischt kann niemand mehr ablesen, was eine
|
||||
Flaeche bedeutet -- und Ablesbarkeit ist der Zweck des Systems. */
|
||||
const liquid = alle.find((r) => (r.selectorText || "").includes("wd-verlauf--liquid"));
|
||||
const liquidText = liquid ? liquid.cssText : "";
|
||||
return {
|
||||
gefunden,
|
||||
champagneRein: !/--wd-lila-rgb|--wd-indigo-rgb/.test(liquidText),
|
||||
};
|
||||
});
|
||||
pruefe("alle vier Signature-Verlaeufe sind gebaut",
|
||||
verlaeufe.gefunden.length === 4, verlaeufe.gefunden.join(", "));
|
||||
pruefe("Liquid Value mischt Champagne NICHT mit Violet",
|
||||
verlaeufe.champagneRein, "Verbot aus Seite 18 eingehalten");
|
||||
|
||||
console.log("\n=== 13. FORMULARE UND TABELLEN (Seite 15) ===");
|
||||
await seite.goto("http://127.0.0.1:4372/webdesign/anfrage.html");
|
||||
await seite.waitForTimeout(600);
|
||||
|
||||
/* Echter Klick statt evaluate-focus(), und danach warten: Der Rand hat
|
||||
einen Uebergang. Sofort gemessen sieht man die Animation auf halbem
|
||||
Weg -- Rand noch alt, Schein noch bei 0 0 0 0 und durchsichtig.
|
||||
|
||||
Der Selektor nennt ausdruecklich Texteingaben: Die Anfrageseite
|
||||
beginnt mit sechs Auswahlkacheln, deren Radios optisch versteckt
|
||||
sind. Ein blindes "erstes input" greift die statt des Feldes. */
|
||||
await seite.locator('.wd-feld textarea, .wd-feld input[type="text"], .wd-eingabe')
|
||||
.first().click();
|
||||
await seite.waitForTimeout(700);
|
||||
|
||||
const feldFokus = await seite.evaluate(() => {
|
||||
/* Nur ECHTE Texteingaben. Die Anfrageseite beginnt mit sechs
|
||||
Auswahlkacheln, deren Radios optisch versteckt sind -- ein blindes
|
||||
"erstes input" greift die und misst deren neutrales Weiss statt des
|
||||
Ion-Randes. Genau das hat hier zweimal falschen Alarm ausgeloest. */
|
||||
const f = document.activeElement;
|
||||
if (!f || f === document.body) return null;
|
||||
const st = getComputedStyle(f);
|
||||
return { rand: st.borderColor, schatten: st.boxShadow };
|
||||
});
|
||||
/* Das System nennt ausdruecklich "Ion-Blue-Rand und sanften Glow". */
|
||||
pruefe("das Eingabefeld bekommt im Fokus einen Ion-Rand",
|
||||
feldFokus && /74,\s*200,\s*255/.test(feldFokus.rand), feldFokus && feldFokus.rand);
|
||||
/* Geprueft wird die Anforderung selbst, nicht die Anzahl Kommas:
|
||||
Der Schein muss in Ion-Blue leuchten und WEICH sein, also einen
|
||||
Weichzeichner ueber 0 haben. Eine harte 0px-Kante waere ein Rahmen,
|
||||
kein Schein. (Die frueher hier stehende Zaehlung trennte an "),"
|
||||
-- das Muster kommt in keinem Schattenwert je vor, weil nach der
|
||||
Farbe immer noch die Masse folgen.) */
|
||||
const scheinIon = feldFokus && /74,\s*200,\s*255/.test(feldFokus.schatten);
|
||||
const scheinWeich = feldFokus &&
|
||||
[...feldFokus.schatten.matchAll(/74,\s*200,\s*255[^)]*\)((?:\s+-?\d+px){2,4})/g)]
|
||||
.some((t) => parseFloat(t[1].trim().split(/\s+/)[2]) > 0);
|
||||
pruefe("und einen weichen Schein dazu",
|
||||
scheinIon && scheinWeich,
|
||||
feldFokus && feldFokus.schatten.slice(0, 60));
|
||||
|
||||
const tabelle = await seite.evaluate(() => {
|
||||
const alle = Array.from(document.styleSheets)
|
||||
.flatMap((b) => { try { return Array.from(b.cssRules); } catch { return []; } })
|
||||
.map((r) => r.cssText).join("\n");
|
||||
/* "sehr schwaches, positionsabhaengiges Licht" -- die Betonung liegt
|
||||
auf SCHWACH. Eine Tabelle ist zum Lesen da; ein kraeftiges
|
||||
Wanderlicht zieht den Blick zur Maus statt zur Zahl. */
|
||||
const m = alle.match(/wd-tabelle tbody tr:hover[^}]*rgb\(var\(--wd-blau-rgb\)\s*\/\s*\.(\d+)\)/);
|
||||
return { gebaut: alle.includes(".wd-tabelle"), staerke: m ? Number("0." + m[1]) : null,
|
||||
positionsabhaengig: /wd-tabelle tbody tr:hover[^}]*--wd-lichtx/.test(alle) };
|
||||
});
|
||||
pruefe("Tabellen sind gestaltet", tabelle.gebaut);
|
||||
pruefe("das Zeilenlicht ist positionsabhaengig", tabelle.positionsabhaengig);
|
||||
pruefe("und bleibt sehr schwach (unter 10 %)",
|
||||
tabelle.staerke !== null && tabelle.staerke < 0.10,
|
||||
tabelle.staerke !== null ? Math.round(tabelle.staerke * 100) + " %" : "nicht gefunden");
|
||||
|
||||
console.log("\n=== 14. KACHEL-ANATOMIE (Seite 11) ===");
|
||||
await seite.goto("http://127.0.0.1:4372/webdesign/leistungen.html");
|
||||
await seite.waitForTimeout(600);
|
||||
const anatomie = await seite.evaluate(() => {
|
||||
const k = document.querySelector(".wd-karte");
|
||||
if (!k) return null;
|
||||
const st = getComputedStyle(k);
|
||||
return {
|
||||
ebenen: (st.backgroundImage.match(/gradient/g) || []).length,
|
||||
lichtkante: /inset/.test(st.boxShadow),
|
||||
randbreite: st.borderWidth,
|
||||
};
|
||||
});
|
||||
/* Die Kachel baut ihre Kante ueber eine ZWEITE Hintergrundebene auf der
|
||||
border-box -- der Rahmen selbst ist durchsichtig. Wer beim Anpassen
|
||||
nur die Flaeche setzt, laesst die Kante ersatzlos wegfallen: Genau
|
||||
das ist beim Bauen passiert, der Rand mass danach rgba(0,0,0,0).
|
||||
Sichtbar war es kaum, messbar sofort. */
|
||||
pruefe("die Kachel hat zwei Hintergrundebenen (Flaeche UND Kante)",
|
||||
anatomie && anatomie.ebenen >= 2, anatomie && anatomie.ebenen);
|
||||
pruefe("sie hat eine innere Lichtkante", anatomie && anatomie.lichtkante);
|
||||
pruefe("die Kante ist 1 px stark (System Seite 11)",
|
||||
anatomie && anatomie.randbreite === "1px", anatomie && anatomie.randbreite);
|
||||
|
||||
await browser.close();
|
||||
srv.close();
|
||||
const f = ergebnisse.filter((e) => !e.ok).length;
|
||||
|
||||
|
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 803 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 456 KiB After Width: | Height: | Size: 466 KiB |
|
Before Width: | Height: | Size: 368 KiB After Width: | Height: | Size: 614 KiB |
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 232 KiB |
|
Before Width: | Height: | Size: 347 KiB After Width: | Height: | Size: 332 KiB |
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 368 KiB After Width: | Height: | Size: 357 KiB |
|
Before Width: | Height: | Size: 829 KiB After Width: | Height: | Size: 796 KiB |
|
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 346 KiB |
@@ -70,6 +70,16 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Blickfang: der Monolith. Steht zwischen Einleitung und den zwei
|
||||
echten Projekten -- ein ruhiger Moment, bevor die Arbeit kommt.
|
||||
aria-hidden, weil rein atmosphaerisch: Die Aussage der Seite
|
||||
steckt in den Projekten darunter, nicht in diesem Bild. -->
|
||||
<section class="wd-abschnitt wd-abschnitt--eng" style="padding-top:0">
|
||||
<div class="wd-container wd-container--schmal">
|
||||
<div class="wd-blickfang wd-blickfang--monolith wd-auf" aria-hidden="true"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="wd-abschnitt" style="padding-top:0">
|
||||
<div class="wd-container">
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
Start alle alten Zwischenspeicher weg. Muss bei jeder Änderung an den
|
||||
Dateien unten hochgezählt werden, sonst hängen Nutzer auf einem alten
|
||||
Stand fest. */
|
||||
const CACHE_NAME = "dogfather-webdesign-v32";
|
||||
const CACHE_NAME = "dogfather-webdesign-v33";
|
||||
|
||||
/* Bausteine, die die Oberfläche zum Anzeigen braucht. Bewusst KEINE
|
||||
HTML-Datei in dieser Liste. */
|
||||
|
||||
@@ -68,6 +68,20 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ---------------- Blickfang: das Wappen ----------------
|
||||
Ein Bild, das man ansieht, keine Flaeche mit Text darauf. Es
|
||||
steht bewusst hier: nach dem Absatz, der erklaert, woher der
|
||||
Name kommt.
|
||||
|
||||
aria-hidden, weil es rein atmosphaerisch ist -- alles, was es
|
||||
zeigt, steht schon im Text daneben. Es vorzulesen wuerde nichts
|
||||
ergaenzen, nur den Lesefluss unterbrechen. -->
|
||||
<section class="wd-abschnitt wd-abschnitt--eng" style="padding-top:0">
|
||||
<div class="wd-container wd-container--schmal">
|
||||
<div class="wd-blickfang wd-blickfang--wappen wd-auf" aria-hidden="true"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ---------------- Arbeitsweise ---------------- -->
|
||||
<section class="wd-abschnitt wd-abschnitt--gehoben">
|
||||
<div class="wd-container">
|
||||
|
||||