Files
DogFatherGitandClaude Opus 5 f62ade3573 Vertraulicher Meldeweg, klappbare Abschnitte, lila Stunden, Logos
Eine Nacht voller Auftraege von Filipe. Der Reihe nach:

1. VERTRAULICH MELDEN -- der groesste neue Teil.

"es soll auch eine kategorie also eine hauptkachel geben wo die
community leute sich anonym melden koennen wenn sie probleme haben ...
rechte hand und dogfather sollen zugriff auf diese anonyme nachrichten
haben. also anonym fuer die anderen."

WICHTIG, UND ES STEHT SO AUF DER SEITE: "anonym" heisst hier
VERTRAULICH. DogFather und die rechte Hand sehen den Namen -- so
bestellt und auch richtig, ohne Namen kann man niemandem helfen.
Anonym ist es gegenueber allen anderen: kein Modi, kein anderes
Mitglied. Wer glaubt, er schreibe unerkannt, schreibt anders und fuehlt
sich hinterher getaeuscht -- deshalb steht der Satz im Formular, bevor
jemand tippt.

Der strikte Wechsel (melden -> warten -> antworten -> warten) ist im
SERVER erzwungen, nicht nur im Knopf. Ein ausgegrauter Knopf ist keine
Regel. Geschlossen wird nur von der Leitung; abgeschlossene Faelle
werden nach 90 Tagen samt Nachrichten geloescht -- hier stehen die
empfindlichsten Texte des Hauses.

Modis sind ausdruecklich AUSSEN VOR: Sehr oft geht es in diesen
Meldungen um eine Moderationsentscheidung.

2. JEDE KATEGORIE LAESST SICH ZUKLAPPEN.

"man soll auf dieser seite jede kategorie auf und zu klappen koennen
mit einem button ... ueberall wo so eine liste entstehen kann."

Das Muster gab es auf der Startseite schon; es steht jetzt als
`abschnittKlappbar` in kopf.js und wird von den Brettern und dem
Zeitstrahl benutzt. Die Koepfe sind echte <button> (fuer die Tastatur),
der Zustand haelt in localStorage, und er haengt je Brett UND Art --
sonst waere "Regel zugeklappt" ueberall gleichzeitig zu.

3. DIE SPRUNGLEISTE SIEHT AUS WIE ETWAS ZUM ANFASSEN.

Vorher unterstrichene Woerter, die aussahen wie eine Fusszeile. Jetzt
Marken mit Rahmen in einem eigenen Block.

4. DIE STUNDEN SIND LILA.

UMGERECHNET, NICHT NEU GEWAEHLT: Jeder der fuenf Verlaufsstopps wurde
nach OKLCH zerlegt, der Farbton auf 303 Grad gedreht, zurueckgerechnet.
Helligkeit und Buntheit blieben gleich -- eine frei gegriffene Palette
waere heller oder bunter geworden, und die Uhr damit unruhiger.

5. DIE KARTEN "UNSERE SEITEN": babyblau und lila, mit schwebenden Logos.

Beide Logos wurden zu MASKEN gerechnet (tools/logo-maske.mjs): Die PNG
tragen nur Alpha, die Farbe kommt aus dem CSS. Dadurch passt dasselbe
Logo in jede Kachel, egal welchen Ton sie hat -- und VanVans 378-KB-
Logo wurde dabei zu 109 KB. Vier Stueck je Karte, verschieden gross,
zwei Bahnen, 26 bis 41 Sekunden Umlauf. Der erste Versuch war mit 5-9 %
Deckkraft praktisch unsichtbar; jetzt 10-16 %.

6. "ENTWICKLUNG" HEISST JETZT "EURE AUFGABEN".

Filipe hat recht: Die Kachel fuehrt seit dem 11.09. auf den Katalog --
eine Aufgabenliste. Der Name blieb stehen, weil beim Umhaengen des
Ziels niemand ihn angefasst hat. Der Name "Entwicklung" ist damit frei
fuer das, was er darunter versteht (Auswertung je Person mit Verlauf
und Text) -- das ist noch NICHT gebaut.

DREI PRUEFUNGEN, DIE ZUFAELLIG GRUEN WAREN, sind nebenbei aufgefallen:
- pruef-kachelraster wartete feste 500 ms auf eine gestaffelte
  Einblendung und mass vier Reihen, wo drei sind. Jetzt reducedMotion.
- pruef-start-ansicht scrollte 600 px und nahm an, danach liege keine
  Kachel mehr unter dem Zeiger.
- pruef-wege-nach-draussen zaehlte das Kachelraster ueber ALLE Gruppen
  statt je Gruppe.

GEMESSEN: pruef-hilfe (neu) 55/0, pruef-wege-nach-draussen 64/0,
pruef-jeder-hat-eine-seite 65/0, pruef-community-sicht 10/0,
pruef-bereiche-lesend, pruef-steckbrief, pruef-start-ansicht,
pruef-kachelraster alle gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-19 02:04:03 +02:00

135 lines
5.7 KiB
JavaScript

/* =====================================================================
AUS EINEM LOGO EINE MASKE MACHEN (19.09.2026)
Filipe: „die kachel links soll dogfather logo als hintergrund haben
und rechts das logo von vanvan. die logos sollen auch richtig geil im
hintegrrund sein. die sollen paar mal sein in der kacheln und so wie
schweben, sich ganz leicht bewegen."
WARUM EINE MASKE UND NICHT DAS BILD SELBST:
Ein Logo als Hintergrundbild bringt seine eigenen Farben mit. Beide
hier sind schwarz auf weiss -- auf einer dunklen Kachel waere das
entweder ein weisser Kasten (VanVan, kein Alphakanal) oder ein
schwarzer Fleck, den man nicht sieht (DogFather). Umfaerben liesse
sich das nur mit Filtern, die man raten muss.
Eine Maske traegt gar keine Farbe. Sie sagt nur, WO etwas zu sehen
ist -- die Farbe kommt aus dem CSS. Damit laesst sich dasselbe Logo
in Babyblau, in Lila und morgen in Gruen zeichnen, ohne eine neue
Datei.
WIE DIE MASKE ENTSTEHT: Alpha = (1 - Helligkeit) x vorhandenes
Alpha. Wo das Logo schwarz ist, wird die Maske dicht; wo es weiss
oder durchsichtig ist, bleibt sie offen. Die Zeichnung bleibt
dadurch erhalten -- eine reine Silhouette waere ein Klecks.
UND KLEINER. Das Original von VanVan ist 387 KB. Fuer ein
Hintergrundmuster, das nie groesser als ein paar hundert Pixel
erscheint, ist das Verschwendung: Es wird auf 320 px gerechnet, und
uebrig bleiben wenige Kilobyte.
Aufrufen mit: node tools/logo-maske.mjs
===================================================================== */
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const HIER = dirname(fileURLToPath(import.meta.url));
const WURZEL = join(HIER, "..");
const ZIEL = join(WURZEL, "assets", "img", "marke");
/** Woraus wird was gemacht. Beide Quellen sind schwarz-weiss. */
const AUFTRAEGE = [
{ quelle: join(WURZEL, "assets/img/marke/logo-kopf-frei.png"),
ziel: join(ZIEL, "maske-dogi.png"), kante: 320,
was: "Der Huskykopf" },
{ quelle: join(WURZEL, "assets/img/marke/vanvan-logo-quelle.png"),
ziel: join(ZIEL, "maske-vanvan.png"), kante: 320,
was: "Van's DIY & Bastelbedarf" },
];
const fehlend = AUFTRAEGE.filter((a) => !existsSync(a.quelle));
if (fehlend.length) {
console.error("KANN NICHT ARBEITEN -- diese Vorlagen fehlen:");
for (const f of fehlend) console.error(" " + f.quelle);
console.error("");
console.error("Das VanVan-Logo liegt unter https://vans-diy-bastelbedarf.com/logo.png");
console.error("und gehoert VanVan. Es wird hier nur verkleinert und entfaerbt.");
process.exit(2);
}
const { chromium } = await import(
"file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs");
const browser = await chromium.launch();
const seite = await browser.newPage();
for (const auftrag of AUFTRAEGE) {
const roh = readFileSync(auftrag.quelle).toString("base64");
const ergebnis = await seite.evaluate(async ([daten, kante]) => {
const bild = new Image();
bild.src = "data:image/png;base64," + daten;
await bild.decode();
/* Quadratisch und mittig -- beide Logos sind schon nahezu
quadratisch, aber "nahezu" ist keine Zusicherung. */
const s = Math.max(bild.width, bild.height);
const gross = document.createElement("canvas");
gross.width = s; gross.height = s;
const gk = gross.getContext("2d");
gk.drawImage(bild, (s - bild.width) / 2, (s - bild.height) / 2);
const d = gk.getImageData(0, 0, s, s);
const p = d.data;
for (let i = 0; i < p.length; i += 4) {
/* Helligkeit nach Wahrnehmung, nicht als Mittelwert: Gruen
wiegt schwerer als Blau. Bei Schwarz-Weiss macht das keinen
Unterschied, bei einem spaeter farbigen Logo schon. */
const hell = (0.2126 * p[i] + 0.7152 * p[i + 1] + 0.0722 * p[i + 2]) / 255;
const alpha = p[i + 3] / 255;
const neu = Math.round((1 - hell) * alpha * 255);
p[i] = p[i + 1] = p[i + 2] = 255; // Farbe egal, die Maske traegt nur Alpha
p[i + 3] = neu;
}
gk.putImageData(d, 0, 0);
/* Verkleinern in EINEM Schritt mit hoher Glaettung. Mehrere
Halbierungen waeren schaerfer, aber hier ist ein weiches
Hintergrundmuster gewollt. */
const klein = document.createElement("canvas");
klein.width = kante; klein.height = kante;
const kk = klein.getContext("2d");
kk.imageSmoothingEnabled = true;
kk.imageSmoothingQuality = "high";
kk.drawImage(gross, 0, 0, kante, kante);
/* Wie viel ist ueberhaupt sichtbar? Eine Maske, die fast leer ist,
waere ein stiller Fehlschlag -- man sieht auf der Kachel nichts
und sucht im CSS. */
const kd = kk.getImageData(0, 0, kante, kante).data;
let sichtbar = 0;
for (let i = 3; i < kd.length; i += 4) if (kd[i] > 24) sichtbar++;
return {
png: klein.toDataURL("image/png").split(",")[1],
anteil: sichtbar / (kante * kante),
};
}, [roh, auftrag.kante]);
const bytes = Buffer.from(ergebnis.png, "base64");
if (!existsSync(ZIEL)) mkdirSync(ZIEL, { recursive: true });
writeFileSync(auftrag.ziel, bytes);
const vorher = readFileSync(auftrag.quelle).length;
const anteil = (ergebnis.anteil * 100).toFixed(1);
const warnung = ergebnis.anteil < 0.03 || ergebnis.anteil > 0.9
? " ACHTUNG: sieht nicht nach einem Logo aus" : "";
console.log(`${auftrag.was}:`);
console.log(` ${Math.round(vorher / 1024)} KB -> ${Math.round(bytes.length / 1024)} KB`
+ ` (${auftrag.kante} px, ${anteil} % gedeckt)${warnung}`);
}
await browser.close();
console.log("");
console.log("Fertig. Die Masken tragen keine Farbe -- die kommt aus dem CSS.");