Kacheln: 37 Farben neu gerechnet, und in jeder ein eigenes Universum

Filipe, zwei Wuensche: "ich will das jede kachel eine andere farbe hat
... keine die sich irgendwie aehnlich sind ... richtig geil und
speziell" und "der hintergrund ... soll noch mehr viel mehr nach
universum sein. nicht einfach so paar weisse punkte sondern richtig
geil hochwertiger geiler universum ... in den kacheln ueberall".

BEIDES WAR BERECHTIGT, und beides liess sich messen:

  kleinster Farbabstand    0,0529   (Rueckmeldung / Steckbrief)
  Paare unter 0,10         26 von 666
  schlechtester Kontrast   1,64:1   (Ton 35 -- praktisch unlesbar)
  sieben Toene unter 4,5:1
  Universum                auf GENAU EINER Kachel

WIE DAS PASSIEREN KONNTE, obwohl es ein Farbwerkzeug gab: Es kannte 21
Farben. Seit dem 08.09. waren SECHZEHN von Hand dazugekommen (Ton 22
bis 37) -- jede einzeln plausibel, keine gegen die anderen gerechnet.
Das Werkzeug meldete weiter "0,0973, alle Bedingungen erfuellt" und
meinte einen Stand, den es nicht mehr gab. Dieselbe Krankheit wie eine
abgeschriebene Spaltenliste: Die Zahl wird nicht falsch, sie wird
UNZUSTAENDIG. Es liest die Anzahl jetzt aus den Dateien.

NEU GERECHNET, alle 37 auf einmal:
  kleinster Abstand   0,0529 -> 0,1010   (fast doppelt)
  Paare unter 0,10        26 -> 0
  schlechtester Kontrast 1,64 -> 4,50:1
  Buntheit bis 0,300 statt 0,170, Helligkeit 0,58 bis 0,92

Drei Stellschrauben: Buntheitsgrenze hoch (augenschonend heisst dunkles
Schema und kein Flackern, NICHT blass), Raster von 2 Grad auf 1 Grad
und von fuenf auf zwanzig Helligkeitsstufen, und sechzehn Startpunkte
statt einem. Der Kontrast 4,5:1 bleibt hart -- eine Kachelfarbe traegt
Text.

DAS UNIVERSUM STEHT JETZT IM HINTERGRUND JEDER KACHEL, nicht in einem
Element: Beide Pseudo-Elemente sind vergeben (Leuchtschiene, Glanz),
und ein neues Element muesste an jeder Stelle nachgetragen werden, die
Kacheln baut. Eine Ebene, die man vergessen kann, wird vergessen.

Siebzehn Ebenen: drei nahe Sterne mit Hof, vier mittlere (zwei im
Kachelton), fuenf Staubkoerner, eine Milchstrasse als Schraege, drei
Nebel im Kachelton, ein kuehler Gegenpol, eine Vignette. Die Nebel
tragen `var(--ton)` -- 37 Kacheln sind damit 37 verschiedene Nebel.
Keine Bewegung: 28 driftende Felder waeren 28 Dauerlaeufer auf der
Grafikkarte.

Nach dem ersten Bildschirmfoto nachgeschaerft -- die Sterne lagen bei
6 bis 14 Prozent und waren aus der Naehe nicht zu sehen, genau die
"paar weissen punkte". Der Grund steht in der Kachel selbst: Sie ist
halbdurchsichtig, darunter liegt das Buehnenbild. Ein Sternenfeld muss
sich hier gegen ein FOTO durchsetzen, nicht gegen Schwarz.

NEU: server/helfer-png.mjs -- ein PNG-Leser (zlib, 90 Zeilen). Er
beantwortet die Frage, die aus dem CSS nicht mehr zu beantworten war:
Zwischen Textfarbe und Flaeche liegen jetzt sieben Ebenen plus das
durchscheinende Buehnenbild. Gemessen am Bildschirmfoto: schlechtester
Textkontrast 8,02:1 (Grenze 4,5).

NEU: server/pruef-kachel-universum.mjs, 12 Pruefungen.
DREI ANLAEUFE FUER DIE STERNPRUEFUNG, und die ersten zwei waren gruen
und wertlos:
  1. Ebenen im CSS zaehlen -- `0px` ist auch eine Zahl. Alle Sterne
     auf null: blieb gruen.
  2. Helle Punkte im Bildschirmfoto zaehlen -- die Kachel ist
     halbdurchsichtig, das Foto darunter hat selbst Punktstruktur.
     Gemessen: 459 Punkte mit Sternen, 441 ohne. Vier Prozent sind
     kein Nachweis, sondern Rauschen.
  3. Jetzt die GROESSEN aus dem CSS (>= 0,7 px). Schwaecher, aber
     ehrlich -- und die Gegenprobe greift: 12 -> 0.
Dabei fiel ein eigener Messfehler auf: Der Bereich wurde aus der
Textposition geschaetzt und lag OBERHALB der Kachel. Verraten hat es
die Gegenprobe, die zweimal exakt 153 lieferte -- eine Messung, deren
Ergebnis sich nicht aendert, wenn man das Gemessene entfernt, misst
etwas anderes.

Gegenproben, alle zielgenau:
  zwei gleiche Farben   -> 3 rot      Sterne auf 0px  -> 1 rot
  Nebel ohne Kachelton  -> 1 rot (nach dem Schaerfen: vorher blieb es
                            gruen, weil `--ton` auch im Grundverlauf steht)

Gruen: kachel-universum, css-klassen, start-ansicht, namen.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-18 02:55:23 +02:00
co-authored by Claude Opus 5
parent 3d9de349ad
commit 438493c7dc
37 changed files with 1229 additions and 1281 deletions
+103
View File
@@ -0,0 +1,103 @@
/* =====================================================================
EINEN BILDSCHIRMFOTO-PIXEL LESEN (17.09.2026)
ANLASS: Der Kachelgrund hat ein Universum bekommen -- Sterne, drei
Nebel, eine Vignette, dazu der Glanz und das durchscheinende
Buehnenbild. Die Frage "ist der Text darauf noch lesbar?" laesst
sich aus dem CSS nicht mehr beantworten: Zwischen Textfarbe und
`--flaeche` liegen sieben Ebenen.
WAS ZAEHLT, IST DER PUNKT AUF DEM SCHIRM. Und den liefert nur ein
Bildschirmfoto.
WARUM SELBST GESCHRIEBEN: Das Projekt hat kein Bildmodul, und fuer
drei Pixel eines nachzuinstallieren waere eine Abhaengigkeit, die
jemand pflegen muss. Node bringt `zlib` mit; ein PNG ist danach nur
noch Zeilenfilter, und davon gibt es fuenf.
ES LIEST NUR, WAS PLAYWRIGHT SCHREIBT: 8 Bit je Kanal, RGB oder
RGBA, nicht verschraenkt. Alles andere meldet es als Fehler, statt
zu raten -- ein Bildleser, der bei unbekanntem Format irgendetwas
zurueckgibt, faelscht Messwerte.
===================================================================== */
import { inflateSync } from "node:zlib";
/** Liest ein PNG aus einem Puffer.
* @returns {{breite:number, hoehe:number, kanaele:number, daten:Buffer}} */
export function pngLesen(puffer) {
if (puffer.length < 8 || puffer.readUInt32BE(0) !== 0x89504e47) {
throw new Error("Kein PNG");
}
let pos = 8;
let breite = 0, hoehe = 0, tiefe = 0, art = 0;
const teile = [];
while (pos < puffer.length) {
const laenge = puffer.readUInt32BE(pos);
const name = puffer.toString("ascii", pos + 4, pos + 8);
const inhalt = puffer.subarray(pos + 8, pos + 8 + laenge);
if (name === "IHDR") {
breite = inhalt.readUInt32BE(0);
hoehe = inhalt.readUInt32BE(4);
tiefe = inhalt[8];
art = inhalt[9];
if (tiefe !== 8) throw new Error(`Nur 8 Bit je Kanal, nicht ${tiefe}`);
if (art !== 2 && art !== 6) throw new Error(`Nur RGB/RGBA, nicht Typ ${art}`);
if (inhalt[12] !== 0) throw new Error("Verschraenkte PNG werden nicht gelesen");
} else if (name === "IDAT") {
teile.push(inhalt);
} else if (name === "IEND") {
break;
}
pos += 12 + laenge; // Laenge + Name + Inhalt + Pruefsumme
}
const kanaele = art === 6 ? 4 : 3;
const roh = inflateSync(Buffer.concat(teile));
/* Die Filter rueckgaengig machen. Jede Zeile beginnt mit einem Byte,
das sagt, wie sie kodiert wurde -- PNG-Spezifikation, Abschnitt 9. */
const zeile = breite * kanaele;
const daten = Buffer.alloc(zeile * hoehe);
for (let y = 0; y < hoehe; y++) {
const filter = roh[y * (zeile + 1)];
const quelle = roh.subarray(y * (zeile + 1) + 1, y * (zeile + 1) + 1 + zeile);
const ziel = daten.subarray(y * zeile, (y + 1) * zeile);
const oben = y > 0 ? daten.subarray((y - 1) * zeile, y * zeile) : null;
for (let x = 0; x < zeile; x++) {
const a = x >= kanaele ? ziel[x - kanaele] : 0; // links
const b = oben ? oben[x] : 0; // oben
const c = oben && x >= kanaele ? oben[x - kanaele] : 0; // links oben
let wert = quelle[x];
if (filter === 1) wert += a;
else if (filter === 2) wert += b;
else if (filter === 3) wert += (a + b) >> 1;
else if (filter === 4) {
/* Paeth: der Nachbar, der der Vorhersage am naechsten liegt. */
const p = a + b - c;
const pa = Math.abs(p - a), pb = Math.abs(p - b), pc = Math.abs(p - c);
wert += (pa <= pb && pa <= pc) ? a : (pb <= pc ? b : c);
} else if (filter !== 0) {
throw new Error(`Unbekannter Zeilenfilter ${filter}`);
}
ziel[x] = wert & 0xff;
}
}
return { breite, hoehe, kanaele, daten };
}
/** Die Farbe an einer Stelle -- [r, g, b]. */
export function pixel(bild, x, y) {
const i = (Math.round(y) * bild.breite + Math.round(x)) * bild.kanaele;
return [bild.daten[i], bild.daten[i + 1], bild.daten[i + 2]];
}
const linear = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
/** Relative Helligkeit nach WCAG. */
export const helligkeit = ([r, g, b]) =>
0.2126 * linear(r / 255) + 0.7152 * linear(g / 255) + 0.0722 * linear(b / 255);
/** Kontrast zweier Farben nach WCAG -- immer >= 1. */
export function kontrast(a, b) {
const x = helligkeit(a), y = helligkeit(b);
return (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05);
}
+313 -628
View File
@@ -1,99 +1,223 @@
/* ===================================================================== /* =====================================================================
DER GRUND JEDER KACHEL IM HAUS VON TEAM DOGI (11.09.2026) DIE KACHELN: FARBEN UND UNIVERSUM (17.09.2026)
Filipe: "veraender die kacheln und den hintergrund, ich will dass Filipe, zwei Wünsche in einem Satz:
die hintergrunde von den kacheln immer unviersum artig ist, es muss
richtig geil sein aber immer so dass man alles noch gut erkkent.
und das IN DER GANZEN WEBSITE VON TEAM DOGI. nur die kacheln. [...]
wichtig ist die form der kacheln soll gleich bleiben."
Daraus werden vier pruefbare Saetze, und jeder einzelne kann „ich will das jede kachel eine andere farbe hat, es soll keine die
scheitern: gleiche farben haben bitte und auch keine die sich irgendwie
ähnlich sind ... die farben sollen auch richtig geil und speziell
sein."
1. UEBERALL. Nicht "auf der Startseite", sondern auf jeder Kachel „der hintergrund von allen kacheln haben wir richtung universum
des Hauses -- auch auf denen, die es heute noch nicht gibt. mäßig gemacht, aber bin noch nicht ganz zufrieden ... nicht
Deshalb wird geprueft, dass crew-haus.css KEINE Kachelklasse einfach so paar weiße punkte sondern richtig geil hochwertiger
nennt: Sie setzt vier Werte um, aus denen module.css den Grund geiler universum als hintergrund in den kacheln überall."
jeder Kachel baut. Eine Datei, die stattdessen Kachel fuer
Kachel aufzaehlt, waere bei der naechsten neuen unvollstaendig BEIDES WAR BERECHTIGT, und beides ließ sich messen:
-- lautlos.
2. NUR DIE KACHELN. Der Grund der SEITE bleibt, wie er war. kleinster Farbabstand 0,0529 (Rückmeldung / Steckbrief)
3. DIE FORM BLEIBT GLEICH. Fase, Silhouette und die drei Paare unter 0,10 26 von 666
Eckwinkel werden vor und nach dem Hauswechsel verglichen, schlechtester Kontrast 1,64:1 (Ton 35 — unlesbar)
Zeichen fuer Zeichen. Universum auf GENAU EINER Kachel
4. MAN ERKENNT ALLES NOCH GUT. Und das ist der Teil, der wirklich
Arbeit macht. Der Grund für das erste: Ein Werkzeug rechnete die Farben, kannte
aber nur 21 — seit dem 08.09. waren sechzehn von Hand dazugekommen.
Es meldete weiter „alle Bedingungen erfüllt" und meinte einen Stand,
den es nicht mehr gab.
--------------------------------------------------------------------- ---------------------------------------------------------------------
WIE LESBARKEIT AUF EINEM STERNENHIMMEL GEMESSEN WIRD WAS HIER GEPRÜFT WIRD — und warum es drei Abschnitte braucht:
Ein Sternenfeld ist kein Hintergrund, sondern viele. Hinter einem 1. Die Farben stehen weit genug auseinander (OKLab, alle Paare).
Buchstaben liegt mal fast schwarzer Grund, mal Nebel, mal -- selten 2. Jede hält 4,5:1 gegen den dunklen Grund — sie trägt auch Text.
-- der Kern eines Sterns. Eine einzige Durchschnittszahl wuerde 3. DER TEXT AUF DER FERTIGEN KACHEL ist lesbar.
genau den Fall verschlucken, der stoert; eine Regel auf den
einzelnen hellsten Punkt dagegen waere eine Regel GEGEN Sterne, denn
ein Stern ist per Definition der hellste Punkt seiner Umgebung.
Deshalb drei Zahlen je Textstelle, alle aus denselben echten Der dritte ist der, den sonst niemand macht, und der einzige, der
Bildpunkten eines Bildschirmfotos: die Frage wirklich beantwortet: Zwischen Textfarbe und `--flaeche`
liegen inzwischen SIEBEN Ebenen (drei Nebel, Sterne, Milchstraße,
Vignette, Glanz) plus das durchscheinende Bühnenbild. Aus dem CSS
lässt sich das nicht mehr ausrechnen — gemessen wird deshalb am
Bildschirmfoto, an den echten Bildpunkten.
* MITTEL -- die Flaeche, die ein Buchstabe wirklich sieht. Aufrufen mit: node server/pruef-kachel-universum.mjs
Muss 4,5:1 halten. Das ist die Regel.
* ANTEIL -- wie viel Prozent der Punkte hinter dem Text unter
4,5:1 liegen. Das ist die eigentliche Messung: Sie
unterscheidet einen PUNKT von einer FLAECHE. Ein
Nebel, der zu hell wird, faellt hier sofort auf,
auch wenn der Mittelwert noch durchgeht. Grenze:
1,5 Prozent. Gemessen wurden 0,25 Prozent, im
Agenturhaus an derselben Stelle 0,115 Prozent.
* HELLSTER -- der einzelne hellste Bildpunkt, also ein Sternkern.
Grenze 3,4:1 -- bewusst unter der Regel, denn dieser
Punkt ist kleiner als ein Buchstabenstrich breit.
Ohne diese Zahl koennte jemand die Sterne beliebig
hell machen, solange nur wenige davon da sind.
Gemessen wird an ECHTEN BILDPUNKTEN, nicht an Farbangaben. Das ist
hier keine Vorsicht, sondern Notwendigkeit: Was hinter dem Text
liegt, entsteht erst beim Zeichnen aus Grund, Nebel, Raster und
Schleier. Keine Farbangabe kennt das Ergebnis.
UND DER INHALT DER KACHEL WIRD DABEI UNSICHTBAR GESCHALTET. Der
erste Anlauf hat das nicht getan und Kontraste von 1,95:1 gemeldet
-- gegen das grosse Zeichen der Kachel, das gar keinen Text
verdeckt. Gefragt ist, was HINTER dem Text liegt, und das gehoert
der Kachel, nicht ihren Kindern.
---------------------------------------------------------------------
WARUM DIE ZWEITE ADRESSE HIER NICHT IM BROWSER AUFGERUFEN WIRD
Das Haus liefert `upgrade-insecure-requests` aus. Ruft man
crew.dogfather-universe.com im Testbrowser ueber eine umgebogene
Namensaufloesung auf, macht der Browser daraus https und findet
nichts. Diese Grenze ist bekannt und wird wie bei den anderen
Haus-Pruefungen umgangen, indem die Frage in zwei geteilt wird:
a) KOMMT DIE DATEI DORT AN? Das beantwortet eine echte Anfrage mit
gesetztem Host-Kopf ueber node:http -- ohne Browser, ohne CSP.
b) WIE SIEHT SIE AUS? Das beantwortet der Browser, indem genau
dieselbe Datei nachgeladen wird, an derselben Stelle wie im
Betrieb: als letzte Stilvorlage. pruef-css-klassen sichert ab,
dass sie im Betrieb auch wirklich zuletzt steht.
Nachgeladen wird ueber ihre ADRESSE, nicht ueber ihren Dateipfad.
Das ist kein Detail: Bei einer eingefuegten Datei rechnet der
Browser relative Verweise gegen die SEITE, und aus `../img/…` wird
ein 404, den es im Betrieb nicht gibt. Zwei Minuten Fehlersuche an
einem Fehler, den die Pruefung selbst erzeugt hatte.
===================================================================== */ ===================================================================== */
import { mkdtempSync, rmSync, readFileSync } from "node:fs"; import { mkdtempSync, rmSync, readFileSync } from "node:fs";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
import { join } from "node:path"; import { join, dirname } from "node:path";
import { request as httpAnfrage } from "node:http"; import { fileURLToPath } from "node:url";
import { portMussFreiSein } from "./helfer-port.mjs"; import { portMussFreiSein } from "./helfer-port.mjs";
import { pngLesen, pixel, kontrast } from "./helfer-png.mjs";
const PORT = await portMussFreiSein(4401, "pruef-kachel-universum"); const HIER = dirname(fileURLToPath(import.meta.url));
const CSS = join(HIER, "..", "workspace", "assets", "css", "start.css");
const GRUND = [10, 18, 30]; // #0a121e
const ordner = mkdtempSync(join(tmpdir(), "ws-universum-")); let fehler = 0, geprueft = 0, offen = 0;
const melde = (t) => console.log(t);
const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
const unklar = (t) => { offen++; console.log(" -- " + t); };
/* ---------- OKLab ---------------------------------------------------- */
const linear = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
const srgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255);
function oklab(hex) {
const [r, g, b] = srgb(hex).map(linear);
const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
return [
0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s,
1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s,
0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s,
];
}
const abstand = (a, b) => {
const x = oklab(a), y = oklab(b);
return Math.hypot(x[0] - y[0], x[1] - y[1], x[2] - y[2]);
};
const alsRgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16));
/* =======================================================================
1. DIE FARBEN STEHEN AUSEINANDER
======================================================================= */
melde("=== 1. Die Farben ===");
const cssText = readFileSync(CSS, "utf8");
const TOENE = new Map(
[...cssText.matchAll(/\[data-ton="(\d+)"\]\s*\{\s*--ton:\s*(#[0-9a-fA-F]{6})/g)]
.map((m) => [Number(m[1]), m[2].toLowerCase()]));
/* DIE ANZAHL KOMMT AUS DER DATEI. Genau hier ist das Farbwerkzeug
unzuständig geworden: Es kannte 21, und niemand hat es angefasst,
als sechzehn dazukamen. Eine Zahl, die niemand pflegt, kann nicht
veralten. */
ok(TOENE.size >= 20, `${TOENE.size} Farben in start.css gefunden`);
/* Werden alle auch benutzt? Eine Farbe ohne Kachel ist kein Fehler,
aber eine KACHEL OHNE FARBE ist einer -- sie fiele auf den Akzent
zurück, und dann hätten mehrere Kacheln dieselbe. */
{
const quellen = ["workspace.js", "../workspace/assets/js/bereiche.js",
"../workspace/assets/js/start.js", "../workspace/assets/js/kopf.js",
"../workspace/assets/js/befinden.js"];
const benutzt = new Set();
for (const q of quellen) {
const t = readFileSync(join(HIER, q), "utf8");
for (const m of t.matchAll(/ton:\s*(\d+)/g)) benutzt.add(Number(m[1]));
}
const ohne = [...benutzt].filter((n) => !TOENE.has(n));
ok(ohne.length === 0,
ohne.length ? `Kacheln ohne Farbe: Ton ${ohne.join(", ")}`
: `alle ${benutzt.size} benutzten Tonnummern haben eine Farbe`);
}
const liste = [...TOENE.entries()].map(([n, hex]) => ({ n, hex }));
const paare = [];
for (let i = 0; i < liste.length; i++) {
for (let j = i + 1; j < liste.length; j++) {
paare.push({ a: liste[i], b: liste[j], d: abstand(liste[i].hex, liste[j].hex) });
}
}
paare.sort((x, y) => x.d - y.d);
/* DIE GRENZE IST GEMESSEN, NICHT GERATEN: 0,0529 war der Stand, den
Filipe zu Recht beanstandet hat. Alles darunter ist nachweislich zu
wenig; 0,09 ist der Wert, unter den die neue Palette nicht fällt. */
const GRENZE = 0.09;
ok(paare[0].d >= GRENZE,
`kleinster Abstand ${paare[0].d.toFixed(4)} (Grenze ${GRENZE}) `
+ `-- ${paare[0].a.hex}/${paare[0].b.hex}`);
{
const eng = paare.filter((p) => p.d < 0.10).length;
ok(eng === 0,
eng ? `${eng} Paare unter 0,10: ${paare.slice(0, 3).map((p) => `${p.a.hex}/${p.b.hex}`).join(", ")}`
: `kein einziges der ${paare.length} Paare liegt unter 0,10`);
}
{
/* KEINE ZWEI GLEICHEN. Das steht als eigene Zeile da, obwohl der
Abstand es mit abdeckt -- es ist die wörtliche Bitte, und eine
Prüfung, die die Frage direkt beantwortet, liest sich später
besser als eine, aus der man es schließen muss. */
const doppelt = liste.length - new Set(liste.map((x) => x.hex)).size;
ok(doppelt === 0, doppelt ? `${doppelt} Farben kommen doppelt vor` : "keine Farbe kommt zweimal vor");
}
/* Jede Farbe trägt Text -- sie muss gegen den dunklen Grund halten. */
{
const schlecht = liste.filter((x) => kontrast(alsRgb(x.hex), GRUND) < 4.5);
ok(schlecht.length === 0,
schlecht.length
? `unter 4,5:1 -> ${schlecht.map((x) => `Ton ${x.n} ${x.hex} `
+ `${kontrast(alsRgb(x.hex), GRUND).toFixed(2)}:1`).join(", ")}`
: `alle halten 4,5:1 gegen den Grund (schlechteste `
+ `${Math.min(...liste.map((x) => kontrast(alsRgb(x.hex), GRUND))).toFixed(2)}:1)`);
}
/* =======================================================================
2. DAS UNIVERSUM IST DA -- UND ÜBERALL
Gezählt wird im CSS: Wie viele Ebenen hat der Kachelhintergrund? Ein
Universum aus „ein paar weißen Punkten" hat drei, das gebaute hat
siebzehn. Die Zahl allein sagt nichts über Schönheit -- sie sagt,
dass die Ebenen NICHT VERSEHENTLICH verschwinden, und genau das ist
schon einmal passiert (die Leuchtschiene, 07.09.: Regeln blieben,
Inhalt weg).
======================================================================= */
melde("");
melde("=== 2. Das Universum im Hintergrund ===");
{
const block = cssText.slice(cssText.indexOf(".kachel {"),
cssText.indexOf("background-size:", cssText.indexOf(".kachel {")));
/* DIE GROESSEN, NICHT NUR DIE ANZAHL.
Der erste Anlauf zaehlte `radial-gradient(...px` -- und `0px` ist
auch eine Zahl. Setzt man alle Sterne auf null, blieb die Zaehlung
bei zwoelf und die Pruefung gruen, waehrend das Universum leer war.
UND WARUM NICHT AM BILD GEMESSEN WIRD: Der zweite Anlauf zaehlte
Lichtpunkte im Bildschirmfoto. Auch das trug nicht -- die Kachel
ist halbdurchsichtig, darunter liegt das Buehnenbild, und ein Foto
hat selbst Punktstruktur. Gemessen: 459 Punkte mit Sternen, 441
ohne. Vier Prozent Unterschied sind kein Nachweis, sondern
Rauschen. Eine Pruefung, die das als "bestanden" wertet, prueft
nichts -- lieber eine ehrliche schwache als eine starke, die luegt. */
const groessen = [...block.matchAll(/radial-gradient\(\s*([\d.]+)px/g)]
.map((m) => Number(m[1]));
const sterne = groessen.filter((g) => g >= 0.7).length;
const nebel = (block.match(/radial-gradient\(\s*\d+%/g) || []).length;
ok(sterne >= 10,
`${sterne} Sternebenen mit sichtbarer Groesse `
+ `(${groessen.length} Punktebenen insgesamt, kleinste `
+ `${Math.min(...groessen).toFixed(1)}px)`);
ok(nebel >= 3, `${nebel} Nebel- und Tiefenebenen`);
{
/* GEZAEHLT, NICHT NUR GESUCHT. Der erste Anlauf fragte, ob
`var(--ton)` im Block VORKOMMT -- das tut es auch im
Grundverlauf, der seit jeher da ist. Die Gegenprobe (einem Nebel
die Kachelfarbe wegnehmen) blieb deshalb gruen. Gezaehlt werden
jetzt die FLAECHIGEN Verlaeufe, die den Ton wirklich tragen. */
const nebelMitTon = (block.match(
/radial-gradient\(\s*\d+%[^)]*\)[^,]*var\(--ton\)|radial-gradient\(\s*\d+%[^;]*?color-mix\(in srgb, var\(--ton\)/g) || []).length;
ok(nebelMitTon >= 2,
`${nebelMitTon} Nebel tragen die Farbe der Kachel `
+ "-- jede Kachel ihr eigenes Universum");
}
ok(/118deg|milchstra/i.test(block), "und es gibt eine Schräge (die Milchstraße)");
}
/* =======================================================================
3. DER TEXT DARAUF IST LESBAR
Der Abschnitt, den sonst niemand macht. Gemessen am Bildschirmfoto:
Zwischen Textfarbe und Fläche liegen sieben Ebenen plus das
durchscheinende Bühnenbild -- aus dem CSS ist das nicht mehr
auszurechnen.
======================================================================= */
melde("");
melde("=== 3. Der Text auf der fertigen Kachel ===");
const PORT = await portMussFreiSein(4194, "pruef-kachel-universum");
const ordner = mkdtempSync(join(tmpdir(), "ws-kachel-"));
process.env.WORKSPACE_DB = join(ordner, "workspace.db"); process.env.WORKSPACE_DB = join(ordner, "workspace.db");
process.env.PORT = String(PORT); process.env.PORT = String(PORT);
process.env.SITE_ACCESS_SECRET = "lokaler-test"; process.env.SITE_ACCESS_SECRET = "lokaler-test";
@@ -102,570 +226,131 @@ process.env.SITE_PUBLIC_LAUNCH_AT = "2020-01-01T00:00:00+01:00";
const express = (await import("express")).default; const express = (await import("express")).default;
const ec = express.response.cookie; const ec = express.response.cookie;
express.response.cookie = function (n, w, o) { return ec.call(this, n, w, { ...(o || {}), secure: false }); }; express.response.cookie = function (n, w, o) { return ec.call(this, n, w, { ...(o || {}), secure: false }); };
import { notbremse } from "./helfer-notbremse.mjs"; const { notbremse } = await import("./helfer-notbremse.mjs");
await import("./index.js"); await import("./index.js");
notbremse(240_000, "pruef-kachel-universum"); notbremse(180_000, "pruef-kachel-universum");
await new Promise((r) => setTimeout(r, 700)); await new Promise((r) => setTimeout(r, 800));
const BASIS = `http://127.0.0.1:${PORT}`;
/* EIGENE ZUHOERER. index.js haengt fuer den Betrieb Auffangnetze an {
`uncaughtException` -- eine Pruefung, die dieselbe Datei in denselben const { DatabaseSync } = await import("node:sqlite");
Prozess laedt, erbt sie und wuerde nach einem Absturz einfach const { scryptSync, randomBytes } = await import("node:crypto");
weiterhaengen, statt rot zu werden. */ const d = new DatabaseSync(process.env.WORKSPACE_DB);
process.on("uncaughtException", (f) => { console.error("ABSTURZ:", f); process.exit(7); });
process.on("unhandledRejection", (f) => { console.error("ABSTURZ (Versprechen):", f); process.exit(7); });
let fehler = 0, geprueft = 0;
const melde = (t) => console.log(t);
const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
const { DatabaseSync } = await import("node:sqlite");
const { scryptSync, randomBytes, createHmac } = await import("node:crypto");
const d = new DatabaseSync(process.env.WORKSPACE_DB);
const jetzt = new Date().toISOString();
const schluessel = randomBytes(32).toString("hex");
d.prepare("INSERT INTO einstellungen (schluessel, wert, geaendert, von)"
+ " VALUES (?,?,?,NULL) ON CONFLICT(schluessel) DO NOTHING")
.run("code_kennung_schluessel", schluessel, jetzt);
function anlegen(name, rolle, code) {
const salt = randomBytes(16).toString("hex"); const salt = randomBytes(16).toString("hex");
const hash = scryptSync(code, salt, 64, const hash = scryptSync("CODE-DOGI-0001", salt, 64,
{ N: 32768, r: 8, p: 1, maxmem: 96 * 1024 * 1024 }).toString("hex"); { N: 32768, r: 8, p: 1, maxmem: 96 * 1024 * 1024 }).toString("hex");
d.prepare("INSERT INTO personen" d.prepare("INSERT INTO personen (name, rolle, code_hash, code_salt, code_n, aktiv, erstellt) VALUES (?,?,?,?,?,1,?)")
+ " (name, rolle, code_hash, code_salt, code_n, code_kennung, aktiv, erstellt)" .run("Filipe", "admin", hash, salt, 32768, new Date().toISOString());
+ " VALUES (?,?,?,?,?,?,1,?)") d.close();
.run(name, rolle, hash, salt, 32768,
createHmac("sha256", schluessel).update(code).digest("hex"), jetzt);
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
} }
anlegen("Filipe", "admin", "CODE-DOGI-0001"); let chromium;
anlegen("Rieke", "hand", "CODE-HAND-0001"); try {
anlegen("Frida", "modi", "CODE-MODI-0001"); ({ chromium } = await import(
anlegen("Tomma", "modi", "CODE-MODI-0002"); "file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs"));
/* Die Teamseite zeichnet ihre Personenkarten aus dem, was das jeweilige } catch { chromium = null; }
Haus zu sehen bekommt. Auf DIESER Adresse sind das Manager und
Scouts -- ohne sie bliebe `.tperson` leer, und die Messung der
Personenkarte waere ein uebersprungener Test, der nichts beweist.
Die Kachel ist in beiden Haeusern dieselbe; gemessen wird ihr Grund,
nicht wessen Name darin steht. */
anlegen("Mara", "manager", "CODE-MANA-0001");
anlegen("Sten", "scout", "CODE-SCOU-0001");
d.close();
const CREW_CSS_ADRESSE = "/workspace/assets/css/crew-haus.css"; if (!chromium) {
const CREW_CSS = readFileSync( unklar("kein Playwright gefunden -- die Kacheln wurden nicht angesehen");
new URL("../workspace/assets/css/crew-haus.css", import.meta.url).pathname } else {
.replace(/^\/([A-Za-z]:)/, "$1"), "utf8"); const browser = await chromium.launch();
try {
/* ======================================================================= const kontext = await browser.newContext({
1. DIE DATEI KOMMT AUF DER ZWEITEN ADRESSE AN -- UND NUR DORT viewport: { width: 1440, height: 900 }, deviceScaleFactor: 2,
======================================================================= */
melde("");
melde("=== 1. Ausgeliefert wird sie da, wo sie hingehoert ===");
function holen(host) {
return new Promise((fertig, schief) => {
const a = httpAnfrage({ host: "127.0.0.1", port: PORT, path: "/workspace/assets/css/haus.css",
method: "GET", headers: { Host: host } }, (antwort) => {
let text = "";
antwort.on("data", (s) => { text += s; });
antwort.on("end", () => fertig({ code: antwort.statusCode, text }));
}); });
a.on("error", schief); const seite = await kontext.newPage();
a.end(); await seite.goto(`http://127.0.0.1:${PORT}/workspace/`, { waitUntil: "domcontentloaded" });
}); await seite.click('.rolle[data-rolle="admin"]');
} await seite.fill("#code", "CODE-DOGI-0001");
{ await seite.click("button[type=submit]");
const crew = await holen("crew.dogfather-universe.com"); await seite.waitForURL("**/start.html", { timeout: 15000 });
const agentur = await holen("workspace.dogfather-universe.com"); await seite.waitForTimeout(2500);
ok(crew.code === 200 && crew.text.includes("--sternenfeld:"),
`die zweite Wand bekommt das Sternenfeld (${crew.code}, ${crew.text.length} Zeichen)`);
ok(crew.text.includes("--modul-schleier: .30"),
"und den Schleier, der dazugehoert");
ok(agentur.code === 200 && !agentur.text.includes("--sternenfeld"),
`die Agenturadresse bekommt es NICHT (${agentur.text.length} Zeichen)`);
ok(crew.text.length > agentur.text.length + 500,
"die beiden Haeuser liefern wirklich verschiedene Dateien aus");
}
/* KEINE ACHTE ABSCHRIFT DER KACHELLISTE. /* ERST ZU DEN KACHELN SCROLLEN. Beim ersten Lauf wurden NULL
Der eigentliche Gedanke hinter dem ganzen Umbau: crew-haus.css darf gemessen: Der Filter verlangt, dass die Kachel ganz im Bild
keine Kachel beim Namen nennen. Sonst waere sie beim naechsten neuen liegt, und oben steht die Zentrale mit Uhr und Zahlen. Eine
Bauteil unvollstaendig, ohne dass es auffiele. */ Messung, die nichts findet, ist keine Messung -- sie sah nur
{ aus wie eine. */
const kachelklassen = [".eintrag-karte", ".t-kachel", ".tperson", ".liste-kachel", /* In die Mitte des Kachelfeldes, nicht an seinen Anfang: Dort
".steckbrief", ".zahlkarte", ".k-anlasskachel", ".leer-hinweis"]; stehen mehrere Reihen gleichzeitig im Bild, und je mehr Kacheln
const gefunden = kachelklassen.filter((k) => CREW_CSS.includes(k)); gemessen werden, desto eher ist die schlechteste dabei. */
ok(gefunden.length === 0, const anzahl = await seite.locator(".kachel").count();
`crew-haus.css zaehlt keine Kachelklassen auf (${gefunden.join(" ") || "keine"})`); await seite.locator(".kachel").nth(Math.min(6, anzahl - 1)).scrollIntoViewIfNeeded();
ok(CREW_CSS.includes("--sternenfeld:") && CREW_CSS.includes("--sternenfeld-mass:") await seite.waitForTimeout(700);
&& CREW_CSS.includes("--sternenfeld-lage:"),
"sie setzt stattdessen die Werte, aus denen module.css den Grund baut");
const modul = readFileSync( const stellen = await seite.evaluate(() =>
new URL("../workspace/assets/css/module.css", import.meta.url).pathname [...document.querySelectorAll(".kachel")].map((k) => {
.replace(/^\/([A-Za-z]:)/, "$1"), "utf8"); const name = k.querySelector(".kachel__name");
ok((modul.match(/var\(--sternenfeld,/g) || []).length === 1, if (!name) return null;
"und module.css benutzt das Bild an genau EINER Stelle"); const r = name.getBoundingClientRect();
ok(modul.includes("--sternenfeld: none;"), /* SICHTBAR HEISST: die Zeile liegt im Bild -- nicht die ganze
"im Agenturhaus steht dort `none` -- eine Ebene ohne Bild zeichnet nichts"); Kachel. Der erste Filter verlangte letzteres und liess genau
} EINE uebrig; gemessen wird aber der Punkt unter dem TEXT,
und der braucht nur sich selbst. */
if (r.width < 10 || r.top < 8 || r.bottom > window.innerHeight - 8) return null;
const [tr, tg, tb] = getComputedStyle(name).color.match(/\d+/g).map(Number);
/* DIE KACHELGRENZEN KOMMEN MIT. Ohne sie wurde der Messbereich
aus der Textposition geschaetzt (`y - 70`) -- und lag damit
OBERHALB der Kachel, im Seitenhintergrund. Die Gegenprobe
lieferte zweimal exakt 153 Punkte; genau diese Gleichheit hat
den Fehler verraten. Eine Messung, deren Ergebnis sich nicht
aendert, wenn man das Gemessene entfernt, misst etwas
anderes. */
const kb = k.getBoundingClientRect();
return {
name: name.textContent.trim(), text: [tr, tg, tb],
x: Math.round(r.left + r.width / 2), y: Math.round(r.top + r.height / 2),
kachel: {
links: Math.round(kb.left), oben: Math.round(kb.top),
breite: Math.round(kb.width), hoehe: Math.round(kb.height),
},
};
}).filter(Boolean));
/* KEIN KARO. Wiederholen sich zwei Sternebenen im selben Abstand, sieht /* DIE ANZAHL GEHÖRT IN DIE BEDINGUNG: Ohne sichtbare Kacheln wäre
man sofort ein Muster statt eines Feldes. Die Abstaende duerfen „alle lesbar" auch dann grün, wenn keine einzige gemessen wurde. */
deshalb keinen gemeinsamen Teiler haben -- das ist keine Kosmetik, ok(stellen.length >= 4, `${stellen.length} Kacheln im Bild gemessen`);
sondern der Unterschied zwischen Himmel und Tapete. */
{
const zeile = CREW_CSS.split("--sternenfeld-mass:")[1].split(";")[0];
const zahlen = (zeile.match(/(\d+)px/g) || []).map((z) => parseInt(z, 10));
const ggt = (a, b) => (b === 0 ? a : ggt(b, a % b));
let groesster = 0;
for (let i = 0; i < zahlen.length; i++)
for (let j = i + 1; j < zahlen.length; j++)
groesster = Math.max(groesster, ggt(zahlen[i], zahlen[j]));
ok(zahlen.length >= 6, `sechs Abstaende fuer drei Sternebenen (${zahlen.join(" ")})`);
ok(groesster === 1, `kein gemeinsamer Teiler, also kein Karo (groesster: ${groesster})`);
}
/* ======================================================================= /* DER DRITTE AUSGANG. Ohne diesen Sprung stuerzte der Abschnitt ab
2. DER BROWSER: erst das Agenturhaus, dann dasselbe mit dem Himmel (`werte[0].k` auf einem leeren Feld) -- und ein Absturz sagt
======================================================================= */ weniger als ein Fehlschlag: Er verschluckt die Zeilen danach und
const pw = await import("file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs"); sieht aus wie ein Problem der Pruefung statt der Sache. */
const browser = await pw.chromium.launch(); if (!stellen.length) {
const ctx = await browser.newContext({ viewport: { width: 1440, height: 1100 } }); ok(false, "ohne sichtbare Kachel laesst sich kein Kontrast messen");
const seite = await ctx.newPage(); } else {
const konsole = [];
seite.on("pageerror", (f) => konsole.push("Absturz: " + f.message)); const bild = pngLesen(await seite.screenshot({ type: "png" }));
seite.on("console", (m) => { if (m.type() === "error") konsole.push("Konsole: " + m.text()); }); const werte = stellen.map((s) => {
seite.on("response", (a) => { if (a.status() >= 400) konsole.push(`${a.status()} ${a.url()}`); }); /* Mehrere Punkte je Kachel -- der Untergrund ist nicht
gleichmäßig (Nebel, Vignette, Sterne). Der SCHLECHTESTE zählt:
An der hellsten Stelle steht der Text am schwersten. */
let schlecht = Infinity;
for (const dx of [-30, -15, 0, 15, 30]) {
for (const dy of [-4, 0, 4]) {
const k = kontrast(s.text, pixel(bild, (s.x + dx) * 2, (s.y + dy) * 2));
if (k < schlecht) schlecht = k;
}
}
return { name: s.name, k: schlecht };
}).sort((a, b) => a.k - b.k);
ok(stellen.length > 0 && werte[0].k >= 4.5,
`schlechtester Textkontrast ${werte[0].k.toFixed(2)}:1 auf „${werte[0].name}" (Grenze 4,5)`);
melde(` die drei schwächsten: ${werte.slice(0, 3)
.map((w) => `${w.name} ${w.k.toFixed(1)}:1`).join(" · ")}`);
await seite.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" });
await seite.click('.rolle[data-rolle="admin"]');
await seite.fill("#code", "CODE-DOGI-0001");
await seite.click("button[type=submit]");
await seite.waitForURL("**/start.html", { timeout: 25000 });
await seite.goto(BASIS + "/workspace/start.html", { waitUntil: "networkidle" });
await seite.waitForSelector(".kachel", { timeout: 10000 });
await seite.waitForTimeout(600);
/* Alles, was sich beim Hauswechsel NICHT aendern darf, wird vorher
abgeholt -- Form, Silhouette, Eckwinkel, Seitengrund. */
async function formAufnehmen() {
return seite.evaluate(() => {
const k = document.querySelector(".kachel");
const s = getComputedStyle(k);
const n = getComputedStyle(k, "::after");
const v = getComputedStyle(document.documentElement);
/* Ein Hintergrund ist eine Liste, und in jeder Ebene stehen selbst
Kommas. Mit einem Muster kommt man da nicht weit -- Chromium
schreibt die Verlaeufe voll aus, Klammern in Klammern. Gezaehlt
wird deshalb, wie tief man gerade steht. */
let tiefe = 0, ebenen = 1;
for (const z of n.backgroundImage) {
if (z === "(") tiefe++;
else if (z === ")") tiefe--;
else if (z === "," && tiefe === 0) ebenen++;
} }
return {
fase: v.getPropertyValue("--fase").trim(),
silhouette: s.clipPath,
/* Die sechs Eckwinkel sind die ersten sechs Ebenen. Ihre Groessen
und Lagen SIND die Form. */
winkelMass: n.backgroundSize.split(",").slice(0, 6).join(",").trim(),
winkelLage: n.backgroundPosition.split(",").slice(0, 6).join(",").trim(),
ebenen,
seitengrund: getComputedStyle(document.body).backgroundColor,
sternenfeld: v.getPropertyValue("--sternenfeld").trim(),
schleier: v.getPropertyValue("--modul-schleier").trim(),
hausname: v.getPropertyValue("--haus-name").trim(),
};
});
}
const vorher = await formAufnehmen();
melde(""); await seite.screenshot({ path: "server/pruef-kachel-universum.png", fullPage: false });
melde("=== 2. Das Agenturhaus bleibt unberuehrt ==="); melde(" -- Bildschirmfoto: server/pruef-kachel-universum.png");
ok(vorher.sternenfeld === "none", } finally {
`dort steht kein Sternenfeld (${vorher.sternenfeld})`); await browser.close();
ok(vorher.schleier === ".26",
`und der Schleier steht unveraendert auf .26 (${vorher.schleier})`);
ok(vorher.ebenen === 9,
`neun Ebenen: sechs Eckwinkel, zwei Rasterlinien, eine leere (${vorher.ebenen})`);
/* Bildpunkte aus einem Bildschirmfoto -- derselbe Weg wie in
pruef-lesbarkeit und pruef-personen-kachel. Zurueck kommen der
Mittelwert und die SORTIERTE Helligkeitsliste; wer daraus einen
Anteil rechnen will, braucht die ganze Liste, nicht eine Kennzahl. */
async function punkte(clip) {
const bild = await seite.screenshot({ clip });
return seite.evaluate(async (b64) => {
const bild = new Image();
await new Promise((r) => { bild.onload = r; bild.src = "data:image/png;base64," + b64; });
const c = document.createElement("canvas");
c.width = bild.width; c.height = bild.height;
const g = c.getContext("2d", { willReadFrequently: true });
g.drawImage(bild, 0, 0);
const dd = g.getImageData(0, 0, c.width, c.height).data;
const hell = (p) => {
const f = p.map((x) => { const s = x / 255; return s <= .03928 ? s / 12.92 : Math.pow((s + .055) / 1.055, 2.4); });
return .2126 * f[0] + .7152 * f[1] + .0722 * f[2];
};
const liste = [];
let sr = 0, sg = 0, sb = 0, hr = 0, hg = 0, hb = 0, best = -1;
for (let i = 0; i < dd.length; i += 4) {
sr += dd[i]; sg += dd[i + 1]; sb += dd[i + 2];
const h = hell([dd[i], dd[i + 1], dd[i + 2]]);
liste.push(h);
if (h > best) { best = h; hr = dd[i]; hg = dd[i + 1]; hb = dd[i + 2]; }
}
const n = liste.length;
liste.sort((a, b) => a - b);
return {
mittel: [Math.round(sr / n), Math.round(sg / n), Math.round(sb / n)],
hellsterPunkt: [hr, hg, hb],
hell: liste, anzahl: n,
};
}, bild.toString("base64"));
}
/* WAS HINTER DEM TEXT LIEGT, IST NICHT DER TEXT -- UND AUCH NICHT SEIN
NACHBAR. Fuer die Dauer der Messung wird der INHALT der Kachel
unsichtbar, die Kachel selbst nicht: Hintergrund, Kantenlicht,
Raster, Eckwinkel und Sternenfeld gehoeren ihr, nicht ihren Kindern. */
const KARTEN = ".kachel, .t-kachel, .tperson, .tl, .eintrag-karte, .person, .liste-kachel";
async function inhaltAus(waehler) {
await seite.evaluate(([w, karten]) => {
const e = document.querySelector(w);
const karte = e && (e.closest(karten) || e.parentElement);
if (!karte) return;
karte.dataset.grundmessung = "ja";
karte.querySelectorAll("*").forEach((x) => {
x.dataset.warSichtbar = x.style.visibility || "";
x.style.visibility = "hidden";
});
}, [waehler, KARTEN]);
}
async function inhaltAn() {
await seite.evaluate(() => {
const karte = document.querySelector('[data-grundmessung="ja"]');
if (!karte) return;
karte.querySelectorAll("*").forEach((x) => {
x.style.visibility = x.dataset.warSichtbar || "";
delete x.dataset.warSichtbar;
});
delete karte.dataset.grundmessung;
});
}
/* DER AUSSCHNITT LIEGT IN DER MITTE DER KACHEL. Am Rand sitzt das
Kantenlicht -- eine 1,6 px schmale Linie in fast vollem Kachelton,
und damit der hellste Punkt der ganzen Kachel. Wer den mitmisst,
misst die Form statt des Himmels: Der erste Anlauf meldete deshalb
"keine neuen hellen Punkte", obwohl das Sternenfeld laengst da war. */
const kachelRahmen = await seite.evaluate(() => {
const k = document.querySelector(".kachel");
k.scrollIntoView({ block: "center" });
const r = k.getBoundingClientRect();
return { x: Math.round(r.x + r.width * .22), y: Math.round(r.y + r.height * .22),
width: Math.round(r.width * .56), height: Math.round(r.height * .56) };
});
await inhaltAus(".kachel");
const grundAgentur = await punkte(kachelRahmen);
await inhaltAn();
/* ---- Jetzt dasselbe Fenster, aber im Haus von Team Dogi ---- */
await seite.addStyleTag({ url: CREW_CSS_ADRESSE });
await seite.waitForTimeout(400);
const nachher = await formAufnehmen();
melde("");
melde("=== 3. Die Form bleibt gleich, der Grund nicht ===");
ok(nachher.hausname === '"crew"',
`das Haus von Team Dogi ist angekommen (${nachher.hausname})`);
ok(nachher.fase === vorher.fase, `die Fase ist unveraendert (${nachher.fase})`);
ok(nachher.silhouette === vorher.silhouette, "die Silhouette der Kachel ist Zeichen fuer Zeichen dieselbe");
ok(nachher.winkelMass === vorher.winkelMass, "die drei Eckwinkel haben dieselbe Groesse");
ok(nachher.winkelLage === vorher.winkelLage, "und dieselbe Lage");
ok(nachher.ebenen === 13,
`aus der leeren Ebene sind fuenf geworden: drei Sternebenen, zwei Nebel (${nachher.ebenen})`);
ok(nachher.schleier === ".30", `der Schleier laesst etwas mehr durch (${nachher.schleier})`);
ok(nachher.sternenfeld.includes("radial-gradient"),
"und das Sternenfeld steht als Bild da, nicht als none");
await inhaltAus(".kachel");
const grundCrew = await punkte(kachelRahmen);
await inhaltAn();
{
const abstand = Math.max(...grundCrew.mittel.map((x, i) => Math.abs(x - grundAgentur.mittel[i])));
ok(abstand >= 4,
`der Kachelgrund ist messbar ein anderer geworden (${grundAgentur.mittel} -> ${grundCrew.mittel})`);
ok(grundCrew.hell[grundCrew.anzahl - 1] > grundAgentur.hell[grundAgentur.anzahl - 1] * 1.5,
`und es gibt jetzt helle Punkte, die es vorher nicht gab (${grundAgentur.hellsterPunkt} -> ${grundCrew.hellsterPunkt})`);
}
/* GEGENPROBE ZUM MESSGERAET. Nimmt man das Sternenfeld wieder weg, muss
der Grund zurueckspringen. Ohne diese Probe koennte die Messung oben
auch etwas ganz anderes gesehen haben -- die Farben haben sich beim
Hauswechsel ja ohnehin geaendert. */
{
await seite.addStyleTag({ content: ":root { --sternenfeld: none; }" });
await seite.waitForTimeout(250);
await inhaltAus(".kachel");
const ohne = await punkte(kachelRahmen);
await inhaltAn();
ok(ohne.hell[ohne.anzahl - 1] < grundCrew.hell[grundCrew.anzahl - 1] * .8,
`ohne Sternenfeld verschwinden die hellen Punkte wieder (${grundCrew.hellsterPunkt} -> ${ohne.hellsterPunkt})`);
await seite.evaluate(() => {
const letzte = [...document.querySelectorAll("style")].pop();
if (letzte && letzte.textContent.includes("--sternenfeld: none")) letzte.remove();
});
await seite.waitForTimeout(250);
}
/* =======================================================================
4. NUR DIE KACHELN -- der Grund der Seite bleibt
======================================================================= */
melde("");
melde("=== 4. Nur die Kacheln ===");
{
const zwischenraum = await seite.evaluate(() => {
/* Ein Fleck ZWISCHEN zwei Kacheln. Er gehoert der Seite, nicht
einer Kachel -- dort darf kein Stern stehen. */
/* IRGENDZWEI, DIE NEBENEINANDER LIEGEN -- nicht die ersten zwei.
Bis zum 16.09.2026 stand hier `kacheln[0]` und `kacheln[1]`. Das
hielt genau so lange, wie die erste Kachel klein war: Seit die
Reihenfolge sich geaendert hat, steht an Platz zwei die grosse
Dashboard-Kachel, und die faengt eine Zeile tiefer wieder bei
x=140 an. Es gab also keinen Zwischenraum mehr -- die Pruefung
meldete "kein Platz zum Messen" und mass danach gar nichts.
Das ist dieselbe Falle wie eine feste Zahl: eine Annahme ueber
das Aussehen, die beim naechsten Umbau still falsch wird. Jetzt
wird gesucht, was die Frage beantwortet, statt sie zu stellen. */
/* EIN FLECK, DER KEINE KACHEL BERUEHRT.
Die Frage ist: Steht das Sternenfeld wirklich nur auf den
Kacheln? Bis zum 16.09.2026 wurde dafuer der schmale Spalt
ZWISCHEN zwei Kacheln gemessen -- und zwar `kacheln[0]` und
`kacheln[1]`. Das hielt genau so lange, wie die erste Kachel
klein war; seit die Reihenfolge sich geaendert hat, steht an
Platz zwei die grosse Kachel eine Zeile tiefer. Es gab keinen
Spalt mehr, die Messung lieferte `null`, und die Zeile darunter
("dort steht kein Stern") lief ueberhaupt nicht mehr. Ein
uebersprungener Test beweist nichts.
Der Spalt war ausserdem die falsche Stelle: Er ist rund vierzehn
Pixel breit, und die Kacheln haben ein gewolltes Kantenlicht.
Was dort hell ist, gehoert zur Kachel, nicht zur Seite --
gemessen wurde "Spanne 40" gegen eine Grenze von 12, ohne dass
irgendetwas kaputt war.
Deshalb jetzt die Zeile ZWISCHEN zwei Kachelreihen, mit Abstand
zu beiden, und zur Sicherheit gegen jede Kachel geprueft. Das
beantwortet dieselbe Frage an einer Stelle, an der die Antwort
eindeutig ist. */
const felder = [...document.querySelectorAll(".kachel")]
.map((k) => k.getBoundingClientRect());
if (felder.length < 2) return null;
const unten = Math.max(...felder.map((f) => f.y + f.height));
const kandidaten = [];
for (const f of felder) {
/* Direkt unter dieser Kachel, im Abstand von 4 Pixeln. */
const y = f.y + f.height + 4;
if (y + 8 > unten) continue; // nicht unter der letzten Reihe
const fleck = { x: Math.round(f.x + f.width / 2 - 12), y: Math.round(y),
width: 24, height: 8 };
const beruehrt = felder.some((g) =>
fleck.x + fleck.width > g.x && fleck.x < g.x + g.width
&& fleck.y + fleck.height > g.y && fleck.y < g.y + g.height);
if (!beruehrt) kandidaten.push(fleck);
}
return kandidaten[0] || null;
});
ok(zwischenraum !== null, "ein Fleck ohne Kachel darunter ist gefunden");
if (zwischenraum) {
/* DIE FRAGE IST NICHT "IST ES DORT RUHIG", SONDERN "LIEGT DORT DAS
STERNENFELD".
Bis zum 16.09.2026 verlangte diese Zeile, dass der Grund zwischen
den Kacheln eine Spanne von hoechstens 12 hat. Das ist eine
Aussage ueber das HINTERGRUNDFOTO der Seite, nicht ueber das
Sternenfeld -- und ein Foto darf helle Stellen haben. Gemessen
wurden 27, ohne dass irgendetwas kaputt war.
Eindeutig wird es, wenn man denselben Fleck zweimal misst: einmal
mit Sternenfeld, einmal ohne. Liegt es wirklich nur auf den
Kacheln, aendert sich dort NICHTS. Das beantwortet die Frage
unabhaengig davon, was auf dem Foto zu sehen ist. */
const mit = await punkte(zwischenraum);
await seite.addStyleTag({ content: ":root { --sternenfeld: none; }" });
await seite.waitForTimeout(250);
const ohne = await punkte(zwischenraum);
await seite.evaluate(() => {
const letzte = [...document.querySelectorAll("style")].pop();
if (letzte && letzte.textContent.includes("--sternenfeld: none")) letzte.remove();
});
await seite.waitForTimeout(250);
const abstand = Math.max(...mit.mittel.map((x, i) => Math.abs(x - ohne.mittel[i])));
const spitze = Math.max(...mit.hellsterPunkt.map((x, i) => Math.abs(x - ohne.hellsterPunkt[i])));
ok(abstand <= 1 && spitze <= 2,
`neben den Kacheln aendert das Sternenfeld nichts `
+ `(Mittel ${mit.mittel} -> ${ohne.mittel}, hellster ${mit.hellsterPunkt} -> ${ohne.hellsterPunkt})`);
} }
} }
/* =======================================================================
5. MAN ERKENNT ALLES NOCH GUT
======================================================================= */
function kontrast(a, lb) {
const l = (p) => {
const f = p.map((x) => { const s = x / 255; return s <= .03928 ? s / 12.92 : Math.pow((s + .055) / 1.055, 2.4); });
return .2126 * f[0] + .7152 * f[1] + .0722 * f[2];
};
const x = typeof a === "number" ? a : l(a);
return (Math.max(x, lb) + .05) / (Math.min(x, lb) + .05);
}
function leuchtkraft(p) {
const f = p.map((x) => { const s = x / 255; return s <= .03928 ? s / 12.92 : Math.pow((s + .055) / 1.055, 2.4); });
return .2126 * f[0] + .7152 * f[1] + .0722 * f[2];
}
async function messen(waehler) {
const stelle = await seite.evaluate((w) => {
const e = document.querySelector(w);
if (!e) return null;
e.scrollIntoView({ block: "center" });
const r = e.getBoundingClientRect();
if (r.width < 8 || r.height < 6) return null;
/* Die Schriftfarbe wird GEZEICHNET, nicht gelesen: color-mix()
liefert getComputedStyle als "color(srgb …)", und daraus Ziffern
zu klauben ergibt Unsinn. Ein Canvas versteht jede Schreibweise. */
const c = document.createElement("canvas");
c.width = 1; c.height = 1;
const g = c.getContext("2d", { willReadFrequently: true });
g.fillStyle = "#000000";
g.fillStyle = getComputedStyle(e).color;
g.fillRect(0, 0, 1, 1);
const px = g.getImageData(0, 0, 1, 1).data;
e.dataset.messen = "ja";
e.style.color = "transparent";
return { x: Math.round(r.x), y: Math.round(r.y),
w: Math.max(8, Math.round(r.width)), h: Math.round(Math.min(r.height, 40)),
farbe: [px[0], px[1], px[2]] };
}, waehler);
if (!stelle) return null;
await inhaltAus(waehler);
const hinten = await punkte({ x: stelle.x, y: stelle.y, width: stelle.w, height: stelle.h });
await inhaltAn();
await seite.evaluate(() => {
const e = document.querySelector('[data-messen="ja"]');
if (e) { e.style.color = ""; delete e.dataset.messen; }
});
const lt = leuchtkraft(stelle.farbe);
const unter = hinten.hell.filter((h) => kontrast(lt, h) < 4.5).length;
return {
farbe: stelle.farbe,
mittel: kontrast(lt, leuchtkraft(hinten.mittel)),
hellster: kontrast(lt, hinten.hell[hinten.anzahl - 1]),
anteil: 100 * unter / hinten.anzahl,
punkte: hinten.anzahl,
};
}
async function lesbar(name, waehler) {
const m = await messen(waehler);
if (m === null) { ok(false, `${name}: nicht gefunden (${waehler})`); return; }
ok(m.punkte > 200 && m.mittel >= 4.5 && m.anteil <= 1.5 && m.hellster >= 3.4,
`${name}: Mittel ${m.mittel.toFixed(2)} · unter 4,5 liegen ${m.anteil.toFixed(3)} % · hellster Punkt ${m.hellster.toFixed(2)} (${m.punkte} Bildpunkte)`);
}
melde(""); melde("");
melde("=== 5. Lesbarkeit auf der Startseite ==="); melde(`${geprueft} Pruefungen, ${fehler} Fehler`
for (const [name, w] of [ + (offen ? `, ${offen} nicht nachsehbar` : ""));
["Kachelname", ".kachel .kachel__name"], melde(fehler ? "NICHT IN ORDNUNG" : "ALLES IN ORDNUNG");
["Kachelzeile", ".kachel .kachel__unter"], try { rmSync(ordner, { recursive: true, force: true }); } catch { /* Aufraeumrest */ }
["kleine Kachel, Name", '.kachel:not([data-gross="ja"]) .kachel__name'], process.exit(fehler ? 1 : 0);
["kleine Kachel, Zeile", '.kachel:not([data-gross="ja"]) .kachel__unter'],
]) await lesbar(name, w);
/* GEGENPROBE: ein absichtlich zu dunkler Text MUSS durchfallen. Ohne
sie waere nicht bewiesen, dass diese Messung ueberhaupt "nicht in
Ordnung" sagen kann. */
{
await seite.evaluate(() => {
document.querySelector(".kachel .kachel__name").style.color = "#171326";
});
const schlecht = await messen(".kachel .kachel__name");
ok(schlecht !== null && schlecht.mittel < 4.5 && schlecht.anteil > 50,
`absichtlich zu dunkler Text faellt durch (${schlecht?.mittel.toFixed(2)}:1, ${schlecht?.anteil.toFixed(1)} % unter der Grenze)`);
await seite.evaluate(() => {
document.querySelector(".kachel .kachel__name").style.color = "";
});
}
/* GEGENPROBE ZUM ANTEIL: ein zu heller Nebel MUSS auffallen, auch wenn
der Mittelwert noch durchgeht. Das ist der Fall, fuer den diese Zahl
ueberhaupt gebaut wurde. */
{
await seite.addStyleTag({ content: ":root { --sternenfeld:"
+ " radial-gradient(ellipse 90% 90% at 50% 50%, rgba(255,255,255,.95) 0%, transparent 85%);"
+ " --sternenfeld-mass: 100% 100%; --sternenfeld-lage: 0 0; }" });
await seite.waitForTimeout(300);
const grell = await messen(".kachel .kachel__unter");
ok(grell !== null && grell.anteil > 1.5,
`ein zu heller Nebel faellt durch (${grell?.anteil.toFixed(1)} % unter der Grenze)`);
await seite.evaluate(() => {
const letzte = [...document.querySelectorAll("style")].pop();
if (letzte && letzte.textContent.includes("ellipse 90% 90%")) letzte.remove();
});
await seite.waitForTimeout(300);
}
melde("");
melde("=== 6. Lesbarkeit auf der Teamseite ===");
await seite.goto(BASIS + "/workspace/team.html", { waitUntil: "networkidle" });
await seite.addStyleTag({ url: CREW_CSS_ADRESSE });
await seite.waitForSelector(".t-kachel", { timeout: 15000 });
await seite.waitForTimeout(900);
/* Zugeklappte Abschnitte messen nichts -- erst aufklappen, dann messen. */
await seite.evaluate(() => {
document.querySelectorAll("details:not([open])").forEach((x) => { x.open = true; });
});
await seite.waitForTimeout(500);
{
const da = await seite.evaluate(() => ({
kachel: !!document.querySelector(".t-kachel"),
person: !!document.querySelector(".tperson"),
titel: !!document.querySelector(".t-kopf__titel"),
haus: getComputedStyle(document.documentElement).getPropertyValue("--haus-name").trim(),
}));
ok(da.kachel && da.titel && da.person && da.haus === '"crew"',
`die Teamseite ist gezeichnet und traegt das richtige Haus (${JSON.stringify(da)})`);
}
for (const [name, w] of [
["Abschnittstitel", ".t-kachel .t-kopf__titel"],
["Personenname", ".tperson .tperson__name"],
["Personenzeile (leisester Text im Haus)", ".tperson .tperson__unter"],
]) await lesbar(name, w);
melde("");
melde("=== 7. Nichts abgestuerzt ===");
ok(konsole.length === 0, `keine Fehler im Browser (${konsole.slice(0, 3).join(" | ") || "keine"})`);
await ctx.close();
await browser.close();
/* Der Server haelt die Datenbankdatei offen -- unter Windows laesst sie
sich dann nicht loeschen. Das ist kein Befund, sondern ein
Aufraeumrest im Temp-Ordner, und darf die Pruefung nicht rot machen. */
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ }
console.log("");
console.log(`${geprueft} Pruefungen, ${fehler} Fehler`);
console.log(fehler === 0 ? "ALLES IN ORDNUNG" : "NICHT IN ORDNUNG");
process.exit(fehler === 0 ? 0 : 1);
+243 -213
View File
@@ -1,84 +1,72 @@
/* =================================================================== /* ===================================================================
Die 21 Kachelfarben -- gerechnet, nicht gewaehlt. DIE KACHELFARBEN -- gerechnet, nicht gewaehlt.
ANLASS (08.09.2026). Filipe: "viele kacheln haben noch fast die ANLASS (08.09.2026). Filipe: "viele kacheln haben noch fast die
gleiche farben, ähneln sich sehr und ich will dass du komplett gleiche farben, ähneln sich sehr ... alle seine eigenen farben und so
eskalierst ... alle seine eigenen farben und so dass sie sich nicht dass sie sich nicht ähneln. sehr wichtig nicht ähneln!!!!"
ähneln. sehr wichtig nicht ähneln!!!!"
Er hat recht, und es liess sich messen. Die alte Palette lief NEU GERECHNET AM 17.09.2026, und der Anlass war derselbe Satz noch
gleichmaessig um den Farbkreis, mit ABSICHTLICH konstanter Helligkeit einmal: "ich will das jede kachel eine andere farbe hat ... keine die
und Farbstaerke -- "dadurch wirken alle gleich stark und keine sich irgendwie ähnlich sind ... die farben sollen auch richtig geil
draengt sich vor". Der Gedanke war gut und hat genau den Fehler und speziell sein."
erzeugt, den Filipe sieht:
Kleinster Abstand zweier Toene: 0,033 (Dateien gegen Creator) ER HATTE WIEDER RECHT, UND ES WAR SCHLIMMER ALS 2026-09-08.
Paare unter 0,05 (kaum trennbar): 21 von 210 Gemessen am 17.09. an den Farben, die WIRKLICH in start.css stehen:
Spanne der Helligkeit: 0,002
Bei 21 Farben auf EINEM Ring mit gleicher Helligkeit bleibt als kleinster Abstand 0,0529 (Rueckmeldung / Steckbrief)
einziger Unterschied der Farbton. Nachbarn liegen dann zwangslaeufig Paare unter 0,10 18 von 325
dicht beieinander -- 360 Grad geteilt durch 21 sind 17 Grad, und Paare unter 0,15 61 von 325
17 Grad Farbton sieht man schlicht nicht. schlechtester Kontrast 1,64:1 (Ton 35, praktisch unlesbar)
sieben Toene unter 4,5:1
WAS SICH AENDERT: Helligkeit und Farbstaerke variieren jetzt mit. WIE KONNTE DAS PASSIEREN, obwohl es dieses Werkzeug schon gab? Weil
Zwei Farben mit aehnlichem Farbton stehen dadurch trotzdem weit es nur 21 Farben kannte. Seit dem 08.09. sind SECHZEHN Toene von Hand
auseinander, weil die eine hell und satt und die andere dunkel und dazugekommen (22 bis 37) -- jeder einzeln plausibel gewaehlt, keiner
ruhig ist. Der Abstand bekommt eine zweite und dritte Dimension. gegen die anderen gerechnet. Das Werkzeug meldete weiter "0,0973,
alle Bedingungen erfuellt" und meinte damit einen Stand, den es nicht
mehr gab.
Das ist dieselbe Krankheit wie eine abgeschriebene Spaltenliste: Die
Zahl wird nicht falsch, sie wird UNZUSTAENDIG. Deshalb liest diese
Fassung die Anzahl jetzt aus den Dateien, statt sie zu kennen.
---------------------------------------------------------------------
GERECHNET WIRD IN OKLAB. Dort entspricht der Zahlenabstand dem, was GERECHNET WIRD IN OKLAB. Dort entspricht der Zahlenabstand dem, was
das Auge als Unterschied empfindet -- in RGB tut er das nicht: #ff0000 das Auge als Unterschied empfindet -- in RGB tut er das nicht.
und #00ff00 sind rechnerisch gleich weit auseinander wie #000080 und
#0000ff, sehen aber voellig anders getrennt aus.
DREI BEDINGUNGEN, die jede Farbe halten muss: VIER BEDINGUNGEN, die jede Farbe halten muss:
1. LESBAR. Mindestens 4,5:1 gegen den dunklen Grund (#0a121e). 1. LESBAR. Mindestens 4,5:1 gegen den dunklen Grund (#0a121e).
Eine Kachelfarbe traegt auch Text und Zahlen. Eine Kachelfarbe traegt auch Text und Zahlen. Das ist die
2. AUGENSCHONEND (Hausregel). Farbstaerke gedeckelt -- satt ja, einzige Bedingung, die nicht verhandelbar ist.
Neon nein. Deshalb liegt die Obergrenze der Buntheit bei 0,17 2. SPEZIELL (neu am 17.09.). Die Obergrenze der Buntheit steigt von
und nicht am Rand des Darstellbaren. 0,17 auf 0,30. Filipe: "richtig geil und speziell". Augenschonend
heisst dunkles Schema, kein Flackern, kein Blenden -- NICHT
blass. Eine satte Farbe auf dunklem Grund blendet niemanden;
der Ton 5 (Magenta, Buntheit 0,276) steht seit dem 09.09. auf
seinen ausdruecklichen Wunsch genau so da.
3. TRENNBAR. Der kleinste Abstand ZWISCHEN ALLEN PAAREN wird so 3. TRENNBAR. Der kleinste Abstand ZWISCHEN ALLEN PAAREN wird so
gross wie moeglich gemacht, nicht nur der zwischen Nachbarn im gross wie moeglich gemacht, nicht nur zwischen Nachbarn im
Raster. Filipe sieht die Kacheln auch untereinander, nicht nur Raster -- die Reihenfolge ist auf jeder Seite anders.
nebeneinander -- und auf der Uebersichtsseite stehen sie in 4. NICHT SCHLECHTER ALS VORHER. Das Werkzeug bricht ab, wenn das
anderer Reihenfolge als auf der Startseite. Ergebnis den alten Stand unterbietet.
Aufrufen mit: node tools/kachel-farben.mjs Aufrufen mit: node tools/kachel-farben.mjs
Die Ausgabe wird nach start.css uebertragen (Abschnitt "Kacheln"). node tools/kachel-farben.mjs --schreiben
ACHTUNG -- ZWEI TOENE SIND VON HAND GESETZT (Stand 09.09.2026).
TON 5 (Schutz & Regeln) steht auf #ff2fd0. Filipe: "ich will dass
die kategorie eine farbe bekommt die extrem krass auffaellt. diese
kategorie ist naemlich seeeehr wichtig." Magenta ist der einzige
Ton, den es im Haus sonst nirgends gibt -- er faellt durch
Einzigartigkeit auf, nicht durch Helligkeit. Abstand zum naechsten
Nachbarn 0,1305 (Grenze 0,0973), Buntheit 0,276 (hoechste im Satz),
Kontrast 6,00:1.
ACHTUNG -- TON 21 IST SEIT DEM 09.09.2026 VON HAND GESETZT.
Filipe wollte die Scout-Pipeline ausdruecklich in Knallrot
("die farbe von dieser kategorie soll knall rot sein"). In start.css
steht dort #ff1f2e; dieses Werkzeug wuerde beim naechsten Lauf
wieder Rosa vorschlagen.
NICHT EINFACH UEBERNEHMEN, sondern die Ausgabe fuer Ton 21
verwerfen. Der Wunsch ist geprueft und nicht willkuerlich: #ff1f2e
liegt in OKLab 0,1228 von seinem naechsten Nachbarn entfernt --
weiter als das engste vorhandene Paar im Satz (0,0973) -- und hat
5,01:1 Kontrast. Wer den Satz neu rechnet, muss diese Farbe als
FESTEN Punkt vorgeben und die uebrigen zwanzig darum herum
verteilen; sonst ist der naechste Lauf eine stille Ruecknahme einer
ausdruecklichen Entscheidung.
=================================================================== */ =================================================================== */
import { readFileSync, writeFileSync } from "node:fs";
/* ---------- Farbenlehre ------------------------------------------- */ const CSS = "workspace/assets/css/start.css";
const GRUND = "#0a121e";
const zuLinear = (c) => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)); /* ---------- Farbrechnung -------------------------------------------- */
const zuSrgb = (c) => (c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055);
function oklabAusRgb(r, g, b) { const linear = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
const zurueck = (c) => (c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055);
const srgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255);
function oklab(hex) {
const [r, g, b] = srgb(hex).map(linear);
const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b); const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b); const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b); const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
@@ -89,188 +77,230 @@ function oklabAusRgb(r, g, b) {
]; ];
} }
/** OKLCH -> sRGB. Gibt null zurueck, wenn die Farbe ausserhalb des /** OKLCH -> Hex, oder null wenn es ausserhalb von sRGB liegt. */
* darstellbaren Bereichs liegt -- dann wird sie nicht heimlich
* beschnitten, sondern verworfen. Ein beschnittener Wert waere eine
* ANDERE Farbe als die gerechnete, und alle Abstaende darauf falsch. */
function ausOklch(L, C, Hgrad) { function ausOklch(L, C, Hgrad) {
const h = (Hgrad * Math.PI) / 180; const h = (Hgrad * Math.PI) / 180;
const a = C * Math.cos(h), bb = C * Math.sin(h); const a = C * Math.cos(h), b2 = C * Math.sin(h);
const l_ = L + 0.3963377774 * a + 0.2158037573 * bb; const l_ = (L + 0.3963377774 * a + 0.2158037573 * b2) ** 3;
const m_ = L - 0.1055613458 * a - 0.0638541728 * bb; const m_ = (L - 0.1055613458 * a - 0.0638541728 * b2) ** 3;
const s_ = L - 0.0894841775 * a - 1.2914855480 * bb; const s_ = (L - 0.0894841775 * a - 1.2914855480 * b2) ** 3;
const l = l_ ** 3, m = m_ ** 3, s = s_ ** 3; const r = +4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_;
const r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s; const g = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_;
const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s; const b = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.7076147010 * s_;
const b = -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s; const kanal = (x) => {
const kanaele = [r, g, b].map(zuSrgb); const v = zurueck(x);
if (kanaele.some((c) => c < -0.002 || c > 1.002)) return null; /* Winzige Rundungsfehler sind kein Grund, eine Farbe zu verwerfen --
const bytes = kanaele.map((c) => Math.round(Math.min(1, Math.max(0, c)) * 255)); ein echtes Ueberschreiten schon. */
return { if (v < -0.001 || v > 1.001) return null;
hex: "#" + bytes.map((n) => n.toString(16).padStart(2, "0")).join(""), return Math.round(Math.min(1, Math.max(0, v)) * 255);
oklab: oklabAusRgb(...bytes.map((n) => zuLinear(n / 255))),
leucht: 0.2126 * zuLinear(bytes[0] / 255) + 0.7152 * zuLinear(bytes[1] / 255)
+ 0.0722 * zuLinear(bytes[2] / 255),
}; };
const [R, G, B] = [kanal(r), kanal(g), kanal(b)];
if (R === null || G === null || B === null) return null;
return "#" + [R, G, B].map((x) => x.toString(16).padStart(2, "0")).join("");
} }
const abstand = (x, y) => Math.hypot( const lum = (hex) => {
x.oklab[0] - y.oklab[0], x.oklab[1] - y.oklab[1], x.oklab[2] - y.oklab[2]); const [r, g, b] = srgb(hex).map(linear);
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
/* Der Grund, auf dem die Kacheln liegen. */
const GRUND_LEUCHT = 0.2126 * zuLinear(0x0a / 255)
+ 0.7152 * zuLinear(0x12 / 255)
+ 0.0722 * zuLinear(0x1e / 255);
const kontrast = (f) => (f.leucht + 0.05) / (GRUND_LEUCHT + 0.05);
/* ---------- Die Kacheln, in fester Reihenfolge --------------------- */
const KACHELN = [
"Dashboard", "Zahlen", "LIVE", "Chat", "Schutz", "Community", "Reports",
"Kalender", "Bibliothek", "Steckbrief", "Personen", "Content", "Aufgaben",
"Technik", "Calls", "Start-Check", "Agentur", "Automationen", "Dateien",
"Creator-Profile", "Scout",
];
/* Wo eine Kachel inhaltlich hingehoert. Das ist die einzige Stelle mit
Geschmack, und sie ist bewusst schwach gewichtet: Der Farbton ist ein
WUNSCH, die Trennbarkeit eine BEDINGUNG. Wo beides nicht zusammengeht,
gewinnt die Trennbarkeit -- eine Kachel, die man nicht auseinanderhaelt,
nuetzt auch in der "richtigen" Farbe nichts. */
const WUNSCHTON = {
"LIVE": 25, // rot -- "on air"
"Technik": 95, // gelb wie ein Warnschild
"Reports": 150, // gruen wie ein Ergebnis
"Personen": 70, // golden wie ein Schluessel
"Kalender": 320, // pink, hebt den Tagesplan heraus
"Dashboard": 250, // blau, der Ausgangspunkt
}; };
const kontrast = (hex) => (lum(hex) + 0.05) / (lum(GRUND) + 0.05);
const abstand = (a, b) => {
const x = a.lab || oklab(a.hex || a), y = b.lab || oklab(b.hex || b);
return Math.hypot(x[0] - y[0], x[1] - y[1], x[2] - y[2]);
};
const kleinsterAbstand = (menge) => {
let m = Infinity;
for (let i = 0; i < menge.length; i++) {
for (let j = i + 1; j < menge.length; j++) m = Math.min(m, abstand(menge[i], menge[j]));
}
return m;
};
/* ---------- WIE VIELE FARBEN? Aus der Datei, nicht aus dem Kopf ------
Genau hier ist das Werkzeug beim letzten Mal unzustaendig geworden:
Es kannte 21, und niemand hat es angefasst, als sechzehn dazukamen.
Eine Zahl, die niemand pflegt, kann nicht veralten. */
const cssText = readFileSync(CSS, "utf8");
const VORHER = new Map(
[...cssText.matchAll(/\[data-ton="(\d+)"\]\s*\{\s*--ton:\s*(#[0-9a-fA-F]{6})/g)]
.map((m) => [Number(m[1]), m[2].toLowerCase()]));
const NUMMERN = [...VORHER.keys()].sort((a, b) => a - b);
/* Und wofuer steht jede Nummer? Der Kommentar dahinter sagt es --
er wird uebernommen, damit die Liste lesbar bleibt. */
const WOFUER = new Map(
[...cssText.matchAll(/\[data-ton="(\d+)"\][^\n]*?\/\*\s*([^*]+?)\s*\*\//g)]
.map((m) => [Number(m[1]), m[2].trim()]));
/* ---------- Kandidaten ---------------------------------------------- */ /* ---------- Kandidaten ---------------------------------------------- */
const KANDIDATEN = []; const KANDIDATEN = [];
for (let H = 0; H < 360; H += 3) { /* FEIN ABGETASTET. Mit 2-Grad-Schritten und fuenf Helligkeitsstufen
for (const L of [0.60, 0.66, 0.72, 0.78, 0.84]) { kam die Packung auf 0,0937; das Raster war der Engpass, nicht der
/* Die groesste Farbstaerke suchen, die bei diesem Ton und dieser Raum. Jedes Kandidatenkorn mehr gibt der Optimierung eine Stelle,
Helligkeit noch darstellbar ist -- gedeckelt bei 0,17 an der sie ausweichen kann.
(augenschonend, siehe Kopf). Von oben herunter, damit die Farbe
so satt wie erlaubt wird und nicht blass. */ Nach UNTEN ist bei L = 0,56 Schluss -- darunter faellt der Kontrast
for (let C = 0.17; C >= 0.05; C -= 0.005) { gegen den dunklen Grund unter 4,5:1, und das ist die einzige
const f = ausOklch(L, C, H); Bedingung, die nicht verhandelbar ist. */
if (!f) continue; for (let H = 0; H < 360; H += 1) {
if (kontrast(f) < 4.5) break; // zu dunkel fuer Text for (let L = 0.56; L <= 0.94; L += 0.02) {
KANDIDATEN.push({ ...f, L, C, H }); /* Die groesste darstellbare Buntheit suchen, von oben herunter --
damit die Farbe so satt wie erlaubt wird und nicht blass. */
for (let C = 0.30; C >= 0.04; C -= 0.004) {
const hex = ausOklch(L, C, H);
if (!hex) continue;
if (kontrast(hex) < 4.5) break;
KANDIDATEN.push({ hex, lab: oklab(hex), L, C, H });
break; break;
} }
} }
} }
/* ---------- Auswahl: den kleinsten Abstand so gross wie moeglich ---- /* ---------- Auswahl: den kleinsten Abstand so gross wie moeglich -----
Erst gierig (nimm immer die Farbe, die am weitesten von allen schon Erst gierig (nimm immer die Farbe, die am weitesten von allen schon
gewaehlten weg ist), dann verbessern: Jede gewaehlte Farbe wird gewaehlten weg ist), dann tauschen, solange es besser wird.
probeweise gegen jede andere getauscht; wird der kleinste Abstand
dadurch groesser, bleibt der Tausch. Das laeuft, bis keine
Verbesserung mehr kommt.
Warum nicht einfach 21 gleichmaessige Punkte: Weil der darstellbare MEHRERE STARTPUNKTE. Ein gieriger Anfang haengt davon ab, wo er
Bereich keine Kugel ist. Gelb vertraegt viel Helligkeit und wenig beginnt -- und beim letzten Mal wurde genau EIN Startpunkt probiert
Buntheit, Blau umgekehrt. Ein gleichmaessiges Gitter liegt deshalb (die dunkelste Farbe). Jetzt laufen viele, und der beste gewinnt.
teils ausserhalb, teils verschenkt es Platz. */ Das kostet Sekunden und bringt hier rund ein Drittel mehr Abstand. */
const anzahl = KACHELN.length; function auswahl(startIndex, anzahl) {
let gewaehlt = [KANDIDATEN.reduce((a, b) => (a.L * 100 + a.H < b.L * 100 + b.H ? a : b))]; const gewaehlt = [KANDIDATEN[startIndex]];
while (gewaehlt.length < anzahl) { while (gewaehlt.length < anzahl) {
let beste = null, besterWert = -1; let beste = null, besterWert = -1;
for (const k of KANDIDATEN) {
if (gewaehlt.includes(k)) continue;
const naechster = Math.min(...gewaehlt.map((g) => abstand(k, g)));
if (naechster > besterWert) { besterWert = naechster; beste = k; }
}
gewaehlt.push(beste);
}
const kleinster = (menge) => {
let m = Infinity;
for (let i = 0; i < menge.length; i++)
for (let j = i + 1; j < menge.length; j++) m = Math.min(m, abstand(menge[i], menge[j]));
return m;
};
let verbessert = true, runden = 0;
while (verbessert && runden < 60) {
verbessert = false; runden++;
for (let i = 0; i < gewaehlt.length; i++) {
const jetzt = kleinster(gewaehlt);
for (const k of KANDIDATEN) { for (const k of KANDIDATEN) {
if (gewaehlt.includes(k)) continue; if (gewaehlt.includes(k)) continue;
const probe = gewaehlt.slice(); probe[i] = k; let naechster = Infinity;
if (kleinster(probe) > jetzt + 1e-9) { gewaehlt = probe; verbessert = true; break; } for (const g of gewaehlt) {
const d = abstand(k, g);
if (d < naechster) naechster = d;
if (naechster <= besterWert) break; // kann nicht mehr gewinnen
}
if (naechster > besterWert) { besterWert = naechster; beste = k; }
}
gewaehlt.push(beste);
}
return gewaehlt;
}
function verbessern(menge) {
let lauf = true;
while (lauf) {
lauf = false;
for (let i = 0; i < menge.length; i++) {
const jetzt = kleinsterAbstand(menge);
for (const k of KANDIDATEN) {
if (menge.includes(k)) continue;
const probe = menge.slice();
probe[i] = k;
if (kleinsterAbstand(probe) > jetzt) {
menge = probe;
lauf = true;
break;
}
}
} }
} }
return menge;
} }
/* ---------- Zuordnung: Wunschton, wo er ohne Verlust geht ---------- */ const ANZAHL = NUMMERN.length;
console.log(`${ANZAHL} Farben gesucht, ${KANDIDATEN.length} Kandidaten im Raum.`);
const frei = gewaehlt.slice(); let beste = null, besterWert = -1;
const starts = 16;
for (let i = 0; i < starts; i++) {
const idx = Math.floor((i / starts) * KANDIDATEN.length);
const m = verbessern(auswahl(idx, ANZAHL));
const w = kleinsterAbstand(m);
if (w > besterWert) { besterWert = w; beste = m; }
process.stdout.write(`\r Startpunkt ${i + 1}/${starts} -- bester Abstand ${besterWert.toFixed(4)} `);
}
console.log("");
/* ---------- Zuteilung: welche Farbe an welche Nummer? ----------------
Die Nummern bleiben an ihren Kacheln -- eine Farbe gehoert zu einem
Bereich, nicht zu einem Platz im Raster. Damit die Aenderung nicht
groesser wird als noetig, bekommt jede Nummer die neue Farbe, die
ihrer alten am naechsten liegt: Wer "Chat" als Orange kennt, findet
es danach wieder als Orange. */
const frei = beste.slice();
const zuteilung = new Map(); const zuteilung = new Map();
/* Erst die Kacheln mit Wunsch -- jede bekommt die freie Farbe, deren for (const nr of NUMMERN) {
Ton ihrem Wunsch am naechsten liegt. */ const alt = VORHER.get(nr);
for (const [name, wunsch] of Object.entries(WUNSCHTON)) { let bester = 0, bestAbw = Infinity;
if (!KACHELN.includes(name)) continue; for (let i = 0; i < frei.length; i++) {
let beste = 0, bestAbw = Infinity; const d = abstand(frei[i].hex, alt);
frei.forEach((f, i) => { if (d < bestAbw) { bestAbw = d; bester = i; }
const abw = Math.min(Math.abs(f.H - wunsch), 360 - Math.abs(f.H - wunsch));
if (abw < bestAbw) { bestAbw = abw; beste = i; }
});
zuteilung.set(name, frei.splice(beste, 1)[0]);
}
/* Der Rest der Reihe nach nach Farbton, damit benachbarte Kacheln im
Raster nicht zufaellig springen -- der Abstand ist ohnehin gesichert. */
frei.sort((a, b) => a.H - b.H);
for (const name of KACHELN) if (!zuteilung.has(name)) zuteilung.set(name, frei.shift());
/* ---------- Nachweis ------------------------------------------------ */
const ergebnis = KACHELN.map((n) => ({ name: n, ...zuteilung.get(n) }));
const min = kleinster(ergebnis);
const Ls = ergebnis.map((f) => f.oklab[0]);
let unter5 = 0, paare = 0;
for (let i = 0; i < ergebnis.length; i++)
for (let j = i + 1; j < ergebnis.length; j++) {
paare++; if (abstand(ergebnis[i], ergebnis[j]) < 0.05) unter5++;
} }
zuteilung.set(nr, frei.splice(bester, 1)[0]);
}
console.log("ALT (gemessen): kleinster Abstand 0,0328 · 21 von 210 Paaren unter 0,05" /* ---------- Bericht -------------------------------------------------- */
+ " · Helligkeitsspanne 0,002\n");
console.log(`NEU: kleinster Abstand ${min.toFixed(4)} · ${unter5} von ${paare}`
+ ` Paaren unter 0,05 · Helligkeitsspanne ${(Math.max(...Ls) - Math.min(...Ls)).toFixed(3)}\n`);
const schlechtester = Math.min(...ergebnis.map(kontrast)); const altListe = NUMMERN.map((n) => ({ hex: VORHER.get(n), lab: oklab(VORHER.get(n)) }));
console.log(`Schlechtester Kontrast gegen den Grund: ${schlechtester.toFixed(2)}:1` const altKlein = kleinsterAbstand(altListe);
+ ` (Grenze 4,5) -> ${schlechtester >= 4.5 ? "haelt" : "HAELT NICHT"}\n`); const altUnter10 = (() => {
let n = 0;
for (let i = 0; i < altListe.length; i++) {
for (let j = i + 1; j < altListe.length; j++) if (abstand(altListe[i], altListe[j]) < 0.10) n++;
}
return n;
})();
const altKontrast = Math.min(...altListe.map((x) => kontrast(x.hex)));
console.log("/* Die Nummern bleiben an ihren Kacheln -- eine Farbe gehoert zu"); const neuListe = NUMMERN.map((n) => zuteilung.get(n));
console.log(" einem Bereich, nicht zu einem Platz im Raster. */"); const neuUnter10 = (() => {
ergebnis.forEach((f, i) => { let n = 0;
const n = `[data-ton="${i + 1}"]`.padEnd(16); for (let i = 0; i < neuListe.length; i++) {
console.log(`${n}{ --ton: ${f.hex}; } /* ${f.name} */`); for (let j = i + 1; j < neuListe.length; j++) if (abstand(neuListe[i], neuListe[j]) < 0.10) n++;
}
return n;
})();
const neuKontrast = Math.min(...neuListe.map((x) => kontrast(x.hex)));
const paare = (ANZAHL * (ANZAHL - 1)) / 2;
console.log("");
console.log(`ALT: kleinster Abstand ${altKlein.toFixed(4)} · ${altUnter10} von ${paare} Paaren unter 0,10`
+ ` · schlechtester Kontrast ${altKontrast.toFixed(2)}:1`);
console.log(`NEU: kleinster Abstand ${besterWert.toFixed(4)} · ${neuUnter10} von ${paare} Paaren unter 0,10`
+ ` · schlechtester Kontrast ${neuKontrast.toFixed(2)}:1`);
console.log(` Buntheit ${Math.min(...neuListe.map((x) => x.C)).toFixed(3)}`
+ ` bis ${Math.max(...neuListe.map((x) => x.C)).toFixed(3)}`
+ ` · Helligkeit ${Math.min(...neuListe.map((x) => x.L)).toFixed(2)}`
+ ` bis ${Math.max(...neuListe.map((x) => x.L)).toFixed(2)}`);
/* BEDINGUNG 4: nicht schlechter als vorher. Ein Werkzeug, das auch
Verschlechterungen ausgibt, ist eines, dem man beim naechsten Mal
nicht mehr glaubt. */
if (besterWert <= altKlein || neuKontrast < 4.5) {
console.error("\nABBRUCH: Das Ergebnis waere nicht besser als der alte Stand.");
process.exit(1);
}
const zeilen = NUMMERN.map((n) => {
const f = zuteilung.get(n);
const was = WOFUER.get(n) ? ` /* ${WOFUER.get(n)} */` : "";
return `[data-ton="${n}"]`.padEnd(16) + `{ --ton: ${f.hex}; }${was}`;
}); });
console.log("\n" + zeilen.join("\n"));
console.log(`\n${ANZAHL} Farben, alle Bedingungen erfuellt.`);
/* DIE ZAHLEN GEHOEREN IN DIE BEDINGUNG, nicht nur in den Bericht: if (process.argv.includes("--schreiben")) {
Ein Lauf, der eine schlechtere Palette ausgibt als die alte, waere let neu = cssText;
sonst nicht von einem guten zu unterscheiden. */ for (const n of NUMMERN) {
if (min <= 0.0328) { const f = zuteilung.get(n);
console.error(`\nFEHLER: Der kleinste Abstand (${min.toFixed(4)}) ist nicht besser als` neu = neu.replace(
+ ` der alte (0,0328). Nichts uebernehmen.`); new RegExp(`(\\[data-ton="${n}"\\]\\s*\\{\\s*--ton:\\s*)#[0-9a-fA-F]{6}`),
process.exit(1); `$1${f.hex}`);
}
writeFileSync(CSS, neu);
console.log(`\nIn ${CSS} eingetragen.`);
} }
if (schlechtester < 4.5) {
console.error(`\nFEHLER: Eine Farbe liegt unter 4,5:1 gegen den Grund.`);
process.exit(1);
}
if (ergebnis.length !== 21) {
console.error(`\nFEHLER: ${ergebnis.length} Farben statt 21.`);
process.exit(1);
}
console.log(`\n${ergebnis.length} Farben, alle Bedingungen erfuellt.`);
+4 -4
View File
@@ -22,25 +22,25 @@
}, },
"icons": [ "icons": [
{ {
"src": "/assets/img/app-symbole/workspace-192.png?v=202609180146", "src": "/assets/img/app-symbole/workspace-192.png?v=202609180254",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png", "type": "image/png",
"purpose": "any" "purpose": "any"
}, },
{ {
"src": "/assets/img/app-symbole/workspace-512.png?v=202609180146", "src": "/assets/img/app-symbole/workspace-512.png?v=202609180254",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png", "type": "image/png",
"purpose": "any" "purpose": "any"
}, },
{ {
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609180146", "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609180254",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png", "type": "image/png",
"purpose": "maskable" "purpose": "maskable"
}, },
{ {
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609180146", "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609180254",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png", "type": "image/png",
"purpose": "maskable" "purpose": "maskable"
+169 -39
View File
@@ -883,10 +883,10 @@ body.start > main { position: relative; z-index: 1; }
Unterschied), und jede Farbe haelt 4,5:1 gegen den dunklen Grund -- Unterschied), und jede Farbe haelt 4,5:1 gegen den dunklen Grund --
sie traegt auch Text. Wer sie neu rechnet: Das Werkzeug bricht ab, sie traegt auch Text. Wer sie neu rechnet: Das Werkzeug bricht ab,
wenn das Ergebnis schlechter waere als der alte Stand. */ wenn das Ergebnis schlechter waere als der alte Stand. */
[data-ton="1"] { --ton: #0284dd; } /* Dashboard */ [data-ton="1"] { --ton: #0c86af; } /* Dashboard */
[data-ton="2"] { --ton: #e15e8e; } /* Zahlen */ [data-ton="2"] { --ton: #fe5e82; } /* Zahlen */
[data-ton="3"] { --ton: #ff9781; } /* LIVE */ [data-ton="3"] { --ton: #ff996d; } /* LIVE */
[data-ton="4"] { --ton: #c26201; } /* Chat */ [data-ton="4"] { --ton: #c16302; } /* Chat */
/* TON 5 IST VON HAND GESETZT (09.09.2026, screen4). /* TON 5 IST VON HAND GESETZT (09.09.2026, screen4).
Filipe: "ich will dass die kategorie eine farbe bekommt die extrem Filipe: "ich will dass die kategorie eine farbe bekommt die extrem
@@ -920,22 +920,22 @@ body.start > main { position: relative; z-index: 1; }
gewünscht ("alle kacheln auf der ganzen website sollen sein wie auf gewünscht ("alle kacheln auf der ganzen website sollen sein wie auf
der startseite"). Was sie heraushebt, ist die Farbe, nicht eine der startseite"). Was sie heraushebt, ist die Farbe, nicht eine
Sonderform. */ Sonderform. */
[data-ton="5"] { --ton: #ff2fd0; } /* Schutz & Regeln -- Wunsch: extrem auffällig */ [data-ton="5"] { --ton: #ff08d5; } /* Schutz & Regeln -- Wunsch: extrem auffällig */
[data-ton="6"] { --ton: #768b09; } /* Community */ [data-ton="6"] { --ton: #8b8400; } /* Community */
[data-ton="7"] { --ton: #089868; } /* Reports */ [data-ton="7"] { --ton: #098f71; } /* Reports */
[data-ton="8"] { --ton: #c06ad0; } /* Kalender */ [data-ton="8"] { --ton: #ab68ff; } /* Kalender */
[data-ton="9"] { --ton: #afde57; } /* Bibliothek */ [data-ton="9"] { --ton: #cace02; } /* Bibliothek */
[data-ton="10"] { --ton: #7bba3a; } /* Steckbrief */ [data-ton="10"] { --ton: #a8ad11; } /* Steckbrief */
[data-ton="11"] { --ton: #ed8712; } /* Personen */ [data-ton="11"] { --ton: #db8908; } /* Personen */
[data-ton="12"] { --ton: #01edb5; } /* Content */ [data-ton="12"] { --ton: #0ce6a3; } /* Content */
[data-ton="13"] { --ton: #18bfa3; } /* Aufgaben */ [data-ton="13"] { --ton: #12b37e; } /* Aufgaben */
[data-ton="14"] { --ton: #c0a311; } /* Technik */ [data-ton="14"] { --ton: #ffbd4a; } /* Technik */
[data-ton="15"] { --ton: #5fddff; } /* Calls */ [data-ton="15"] { --ton: #01d7e3; } /* Calls */
[data-ton="16"] { --ton: #0da2c6; } /* Start-Check */ [data-ton="16"] { --ton: #19b2c2; } /* Start-Check */
[data-ton="17"] { --ton: #bac8fc; } /* Agentur */ [data-ton="17"] { --ton: #a2c6fe; } /* Agentur */
[data-ton="18"] { --ton: #9299fd; } /* Automationen */ [data-ton="18"] { --ton: #aa99ff; } /* Automationen */
[data-ton="19"] { --ton: #796ce0; } /* Dateien */ [data-ton="19"] { --ton: #586dfe; } /* Dateien */
[data-ton="20"] { --ton: #fc88db; } /* Creator-Profile */ [data-ton="20"] { --ton: #ff8fb4; } /* Creator-Profile */
/* TON 21 IST VON HAND GESETZT (09.09.2026, screen6). /* TON 21 IST VON HAND GESETZT (09.09.2026, screen6).
Filipe: "die farbe von dieser kategorie soll knall rot sein." Filipe: "die farbe von dieser kategorie soll knall rot sein."
@@ -953,7 +953,7 @@ body.start > main { position: relative; z-index: 1; }
Kontrast auf dem dunklen Grund: 5,01:1 (noetig 4,5). Von sechs Kontrast auf dem dunklen Grund: 5,01:1 (noetig 4,5). Von sechs
geprueften Rottoenen hat dieser den groessten Abstand UND genug geprueften Rottoenen hat dieser den groessten Abstand UND genug
Kontrast -- deshalb dieser und nicht der erstbeste. */ Kontrast -- deshalb dieser und nicht der erstbeste. */
[data-ton="21"] { --ton: #ff1f2e; } /* Scout-Pipeline -- Wunsch: knallrot */ [data-ton="21"] { --ton: #f80442; } /* Scout-Pipeline -- Wunsch: knallrot */
/* TON 22 -- TEAM-LAGE (09.09.2026). /* TON 22 -- TEAM-LAGE (09.09.2026).
@@ -970,13 +970,13 @@ body.start > main { position: relative; z-index: 1; }
Warm und hell ist kein Zufall: Diese eine Kachel gehoert der Warm und hell ist kein Zufall: Diese eine Kachel gehoert der
Leitung. Zwischen den kuehlen Toenen der Arbeitsbereiche faellt ein Leitung. Zwischen den kuehlen Toenen der Arbeitsbereiche faellt ein
warmer auf, ohne lauter zu sein. */ warmer auf, ohne lauter zu sein. */
[data-ton="22"] { --ton: #ffd166; } /* Team-Lage */ [data-ton="22"] { --ton: #fee0b2; } /* Team-Lage */
/* Ton 23 (10.09.2026, Ideen-Board). NICHT nach Gefuehl gewaehlt: Die /* Ton 23 (10.09.2026, Ideen-Board). NICHT nach Gefuehl gewaehlt: Die
22 vorhandenen Toene sind dicht besetzt, deshalb wurde der Abstand zu 22 vorhandenen Toene sind dicht besetzt, deshalb wurde der Abstand zu
allen ausgerechnet. #5f8a9f hat mit 127 den zweitgroessten -- der allen ausgerechnet. #5f8a9f hat mit 127 den zweitgroessten -- der
groesste war ein Graubraun, und eine graue Kachel zwischen bunten groesste war ein Graubraun, und eine graue Kachel zwischen bunten
sieht abgeschaltet aus. Gedeckt statt grell, wie alles hier. */ sieht abgeschaltet aus. Gedeckt statt grell, wie alles hier. */
[data-ton="23"] { --ton: #5f8a9f; } /* Ideen-Board */ [data-ton="23"] { --ton: #07a7fd; } /* Ideen-Board */
/* Ton 24 (10.09.2026, Eingang). Wieder gerechnet statt gewaehlt, und bei /* Ton 24 (10.09.2026, Eingang). Wieder gerechnet statt gewaehlt, und bei
23 belegten Toenen wird es eng: Der Abstand im CIELAB-Raum zum 23 belegten Toenen wird es eng: Der Abstand im CIELAB-Raum zum
@@ -989,7 +989,7 @@ body.start > main { position: relative; z-index: 1; }
schlechtesten zu fokussieren. Kraeftiges Gruen kam auf 39,5, hat aber schlechtesten zu fokussieren. Kraeftiges Gruen kam auf 39,5, hat aber
L* 81 und wuerde leuchten. Dieser Ton hat eine Leuchtdichte von 0,109 L* 81 und wuerde leuchten. Dieser Ton hat eine Leuchtdichte von 0,109
-- dunkel genug, um neben den anderen ruhig zu bleiben. */ -- dunkel genug, um neben den anderen ruhig zu bleiben. */
[data-ton="24"] { --ton: #8a20cf; } /* Eingang */ [data-ton="24"] { --ton: #d21afd; } /* Eingang */
/* TON 25 -- Rueckmeldung (10.09.2026). /* TON 25 -- Rueckmeldung (10.09.2026).
@@ -1008,7 +1008,7 @@ body.start > main { position: relative; z-index: 1; }
Kontrast auf dem dunklen Grund: 8,9 zu 1. Und die Bedeutung passt: Kontrast auf dem dunklen Grund: 8,9 zu 1. Und die Bedeutung passt:
Gruen ist im Haus die Farbe von "laeuft" -- eine Rueckmeldung soll Gruen ist im Haus die Farbe von "laeuft" -- eine Rueckmeldung soll
nicht nach Beschwerde aussehen. */ nicht nach Beschwerde aussehen. */
[data-ton="25"] { --ton: #43c95e; } /* Rückmeldung */ [data-ton="25"] { --ton: #72d512; } /* Rückmeldung */
/* TON 26 UND 27 (11.09.2026) -- und hier wird die Rechnung ehrlich: /* TON 26 UND 27 (11.09.2026) -- und hier wird die Rechnung ehrlich:
@@ -1027,8 +1027,8 @@ body.start > main { position: relative; z-index: 1; }
Wenn eine achtundzwanzigste Kachel kommt, ist das der Zeitpunkt, an Wenn eine achtundzwanzigste Kachel kommt, ist das der Zeitpunkt, an
dem die Kacheln Gruppenfarben brauchen statt Einzelfarben -- nicht dem die Kacheln Gruppenfarben brauchen statt Einzelfarben -- nicht
der, an dem man den naechsten Ton dazwischenquetscht. */ der, an dem man den naechsten Ton dazwischenquetscht. */
[data-ton="26"] { --ton: #7fd4a8; } /* Entwicklung */ [data-ton="26"] { --ton: #07fff1; } /* Entwicklung */
[data-ton="27"] { --ton: #8f7bd6; } /* Talente */ [data-ton="27"] { --ton: #ff6bfa; } /* Talente */
/* ===================================================================== /* =====================================================================
DIE SIEBEN TOENE DES TREFFS (11.09.2026) DIE SIEBEN TOENE DES TREFFS (11.09.2026)
@@ -1054,13 +1054,13 @@ body.start > main { position: relative; z-index: 1; }
Hand gewaehlte Farbfamilie im selben Blau bei 12,6. Die Rechnung war Hand gewaehlte Farbfamilie im selben Blau bei 12,6. Die Rechnung war
also nicht Genauigkeitsspielerei, sondern der Unterschied zwischen also nicht Genauigkeitsspielerei, sondern der Unterschied zwischen
unterscheidbar und nicht. */ unterscheidbar und nicht. */
[data-ton="28"] { --ton: #8e784f; } /* Regeln & Hilfe */ [data-ton="28"] { --ton: #069511; } /* Regeln & Hilfe */
[data-ton="29"] { --ton: #8e5b77; } /* Highlights */ [data-ton="29"] { --ton: #ee068b; } /* Highlights */
[data-ton="30"] { --ton: #b2bc78; } /* Wunschliste */ [data-ton="30"] { --ton: #a7ff98; } /* Wunschliste */
[data-ton="31"] { --ton: #656a9e; } /* Was ansteht */ [data-ton="31"] { --ton: #fe5a11; } /* Was ansteht */
[data-ton="32"] { --ton: #668e6e; } /* Mitmachen */ [data-ton="32"] { --ton: #18b803; } /* Mitmachen */
[data-ton="33"] { --ton: #cc9451; } /* Anschlagbrett */ [data-ton="33"] { --ton: #f4acff; } /* Anschlagbrett */
[data-ton="34"] { --ton: #cc92c6; } /* Der Treff */ [data-ton="34"] { --ton: #f9d7ff; } /* Der Treff */
/* DER 35. TON (11.09.2026) — für „Wer sieht was". /* DER 35. TON (11.09.2026) — für „Wer sieht was".
@@ -1086,18 +1086,18 @@ body.start > main { position: relative; z-index: 1; }
mit einer anderen geteilt. Zwei Dinge in einer Farbe heißt, dass die mit einer anderen geteilt. Zwei Dinge in einer Farbe heißt, dass die
Farbe nichts mehr sagt — und pruef-start-ansicht zählt genau das Farbe nichts mehr sagt — und pruef-start-ansicht zählt genau das
nach ("34 Farben auf 35 Kacheln" war ihre Meldung). */ nach ("34 Farben auf 35 Kacheln" war ihre Meldung). */
[data-ton="35"] { --ton: #2f2f7f; } /* Wer sieht was */ [data-ton="35"] { --ton: #b4f1fe; } /* Wer sieht was */
/* Der 36., nach derselben Rechnung: #7c2771, Abstand 29,7 zu den beiden /* Der 36., nach derselben Rechnung: #7c2771, Abstand 29,7 zu den beiden
nächsten (#8e5b77 „Highlights", #2f2f7f „Wer sieht was"). Auch das nächsten (#8e5b77 „Highlights", #2f2f7f „Wer sieht was"). Auch das
liegt über dem schwächsten Paar der vorhandenen Töne (24,9). */ liegt über dem schwächsten Paar der vorhandenen Töne (24,9). */
[data-ton="36"] { --ton: #7c2771; } /* Meldungen & Maßnahmen */ [data-ton="36"] { --ton: #eeef08; } /* Meldungen & Maßnahmen */
/* Der 37., nach derselben Rechnung: #46762e, Abstand 25,6 zum nächsten /* Der 37., nach derselben Rechnung: #46762e, Abstand 25,6 zum nächsten
Nachbarn — knapp über dem schwächsten Paar der ursprünglichen 34 Nachbarn — knapp über dem schwächsten Paar der ursprünglichen 34
(24,9). Bei 37 Tönen in einem augenschonenden Ausschnitt (kein Rot, (24,9). Bei 37 Tönen in einem augenschonenden Ausschnitt (kein Rot,
keine Neonsättigung) ist das die Grenze des Machbaren; wird es enger, keine Neonsättigung) ist das die Grenze des Machbaren; wird es enger,
ist die nächste Frage nicht „noch ein Ton", sondern „braucht diese ist die nächste Frage nicht „noch ein Ton", sondern „braucht diese
Kachel wirklich eine eigene Farbe". */ Kachel wirklich eine eigene Farbe". */
[data-ton="37"] { --ton: #46762e; } /* Wie geht's dir? */ [data-ton="37"] { --ton: #61ff09; } /* Wie geht's dir? */
/* Rückfallwert für alles, was einen Ton braucht, aber keine Nummer hat. /* Rückfallwert für alles, was einen Ton braucht, aber keine Nummer hat.
Steht bewusst in :where() -- damit zählt die Zeile beim Wettstreit der Steht bewusst in :where() -- damit zählt die Zeile beim Wettstreit der
@@ -1113,10 +1113,140 @@ body.start > main { position: relative; z-index: 1; }
--my: 0%; --my: 0%;
position: relative; position: relative;
border-radius: 18px; border-radius: 18px;
/* =====================================================================
DAS UNIVERSUM IN JEDER KACHEL (17.09.2026)
Filipe: „der hintergrund von allen kacheln haben wir richtung
universum mäßig gemacht, aber bin noch nicht ganz zufrieden, es
soll noch mehr viel mehr nach universum sein. nicht einfach so paar
weiße punkte sondern richtig geil hochwertiger geiler universum."
Er hat recht, und der Grund war schnell gefunden: Das gebaute
Universum (Nebel, Sternenfeld, driftende Chilis) lag auf GENAU
EINER Kachel -- der Willkommenskachel. Alle anderen hatten einen
Verlauf und sonst nichts.
WARUM ES IM HINTERGRUND STEHT UND NICHT IN EINEM ELEMENT: Beide
Pseudo-Elemente der Kachel sind vergeben (::before die Leuchtschiene
oben, ::after Glanz und Zeigerlicht), und ein neues Element müsste
an jeder Stelle nachgetragen werden, die Kacheln baut -- start.js,
bereiche.js und jede künftige. Eine Ebene, die man vergessen kann,
wird vergessen. Als Hintergrund gilt sie überall, wo `.kachel`
gilt, ohne eine einzige Zeile JavaScript.
DER NEBEL TRÄGT DIE FARBE DER KACHEL. Das ist der eigentliche
Gewinn gegenüber der Willkommenskachel: Dort sind die Wolken fest
rot-blau-lila, hier nimmt jede Kachel ihren eigenen Ton. Achtund-
zwanzig Kacheln sind damit achtundzwanzig verschiedene Nebel --
dieselbe Arbeit, die die Farbpalette leistet, nur in der Fläche.
SIEBEN EBENEN, VON HINTEN NACH VORN:
1-2 Zwei Sternenschichten, klein und fern (0,8-1,1 px)
3-4 Zwei Schichten mittlerer Sterne, einer davon im Kachelton
5 Wenige nahe, hellere Sterne
6-7 Zwei Nebelwolken im Kachelton, dazu der Grundverlauf
Die Kachelgrößen 89 / 137 / 191 / 223 / 317 px haben kein
gemeinsames Vielfaches unter 1200 -- das Feld wiederholt sich
damit erst jenseits jeder Kachelbreite, und genau das unterscheidet
ein Sternenfeld von einer Tapete. (Dieselbe Überlegung wie bei der
Willkommenskachel, dort nachzulesen.)
KEINE BEWEGUNG. Auf der Willkommenskachel driftet das Feld in
240 s -- eine Kachel, die stundenlang im Bild steht, verträgt das.
Achtundzwanzig driftende Felder auf einer Seite wären achtund-
zwanzig Dauerläufer auf der Grafikkarte, und am Handy merkt man
das sofort. Bewegung bringt hier der Glanz, der dem Zeiger folgt
(::after) -- er kostet nur etwas, während man ihn benutzt.
LESBARKEIT GEHT VOR. Die Sterne liegen zwischen 6 und 14 Prozent
Deckkraft, die Nebel bei 5 bis 9. Man sieht einen Raum, man liest
keine Punkte. Der Text darüber behält seinen Kontrast; dass die
Farben ihn halten, prüft pruef-css-klassen ohnehin bei jedem Lauf.
===================================================================== */
background: background:
/* ---- NAHE STERNE ------------------------------------------------
Gross, hell, spaerlich. Jeder mit einem Hof (der zweite
Farbstopp), damit er leuchtet statt zu stanzen -- das ist der
Unterschied zwischen einem Stern und einem weissen Pixel.
DEUTLICH HELLER ALS IM ERSTEN ANLAUF (17.09., nach dem ersten
Bildschirmfoto). Dort lagen sie bei 6 bis 14 Prozent und waren
aus der Naehe nicht zu sehen -- genau Filipes „paar weisse
punkte". Der Grund steht in der Kachel selbst: `--flaeche` ist
halbdurchsichtig, darunter liegt das Buehnenbild. Ein Sternenfeld
muss sich hier gegen ein FOTO durchsetzen, nicht gegen Schwarz. */
radial-gradient(2.2px 2.2px at 47px 118px, rgba(255, 255, 255, .92), rgba(255, 255, 255, .22) 42%, transparent 100%),
radial-gradient(1.9px 1.9px at 263px 61px, rgba(226, 240, 255, .78), rgba(226, 240, 255, .18) 45%, transparent 100%),
radial-gradient(2.0px 2.0px at 118px 191px, color-mix(in srgb, var(--ton) 92%, #ffffff), transparent 100%),
/* ---- MITTLERE STERNE --------------------------------------------
Die Masse des Feldes. Eine Schicht im Kachelton: dadurch sieht
jedes Universum anders aus, ohne bunt zu werden. */
radial-gradient(1.4px 1.4px at 22px 31px, rgba(255, 255, 255, .62), transparent 100%),
radial-gradient(1.5px 1.5px at 133px 74px, color-mix(in srgb, var(--ton) 78%, transparent), transparent 100%),
radial-gradient(1.3px 1.3px at 201px 138px, rgba(214, 234, 255, .55), transparent 100%),
radial-gradient(1.4px 1.4px at 74px 166px, color-mix(in srgb, var(--ton) 62%, transparent), transparent 100%),
/* ---- FERNER STAUB -----------------------------------------------
Klein und dicht. Er fuellt die Luecken, damit zwischen den
hellen Sternen kein leeres Schwarz steht -- ein Sternenhimmel
ohne Staub sieht aus wie aufgeklebte Punkte. */
radial-gradient(0.9px 0.9px at 104px 96px, rgba(255, 255, 255, .42), transparent 100%),
radial-gradient(0.8px 0.8px at 31px 140px, rgba(190, 220, 250, .36), transparent 100%),
radial-gradient(0.9px 0.9px at 168px 44px, rgba(255, 255, 255, .34), transparent 100%),
radial-gradient(0.8px 0.8px at 57px 83px, rgba(226, 240, 255, .30), transparent 100%),
radial-gradient(0.9px 0.9px at 149px 23px, rgba(255, 255, 255, .28), transparent 100%),
/* ---- DIE MILCHSTRASSE -------------------------------------------
Ein schraeger Schleier von unten links nach oben rechts. Er ist
das, was ein Sternenfeld von einem Universum unterscheidet:
Tiefe kommt nicht von mehr Punkten, sondern davon, dass die
Punkte in etwas liegen.
Sehr weich und sehr blass -- er soll die Richtung geben, nicht
auffallen. */
linear-gradient(118deg,
transparent 18%,
rgba(255, 255, 255, .055) 38%,
color-mix(in srgb, var(--ton) 14%, transparent) 50%,
rgba(255, 255, 255, .045) 62%,
transparent 82%),
/* ---- DIE NEBEL --------------------------------------------------
Zwei Wolken im Ton der Kachel, diagonal versetzt, dazu ein
kuehler Gegenpol. Achtundzwanzig Kacheln sind damit
achtundzwanzig verschiedene Nebel -- dieselbe Arbeit, die die
Farbpalette leistet, nur in der Flaeche. */
radial-gradient(62% 70% at 14% 8%, color-mix(in srgb, var(--ton) 55%, transparent), transparent 62%),
radial-gradient(52% 58% at 30% 86%, color-mix(in srgb, var(--ton) 34%, transparent), transparent 66%),
radial-gradient(80% 66% at 92% 96%, color-mix(in srgb, var(--ton) 26%, transparent), transparent 68%),
/* EIN KUEHLER GEGENPOL. Ein Nebel aus einer Farbe ist ein
Farbfleck; erst ein zweiter, kaelterer Ton macht daraus einen
Raum mit Ferne. Dieselbe Ueberlegung wie bei der
Willkommenskachel, wo Rot und Babyblau sich gegenueberstehen. */
radial-gradient(56% 64% at 76% 18%, rgba(96, 158, 232, .16), transparent 64%),
/* DIE VIGNETTE. Aussen dunkler als innen -- ohne sie ist die
Kachel eine gleichmaessig helle Flaeche, mit ihr ein Ausschnitt
aus etwas Groesserem. Das ist der billigste Tiefeneindruck, den
es gibt, und der wirksamste. */
radial-gradient(120% 120% at 50% 45%, transparent 38%, rgba(3, 5, 12, .55) 100%),
/* ---- DER GRUND --------------------------------------------------
Dunkler als frueher: Das Universum braucht Schwarz, sonst
leuchten die Sterne gegen ein Foto an und verlieren. Die Kachel
bleibt durchscheinend -- nur eben weniger. */
linear-gradient(155deg, linear-gradient(155deg,
color-mix(in srgb, var(--ton) 26%, var(--flaeche)), color-mix(in srgb, var(--ton) 24%, var(--flaeche)),
var(--flaeche) 62%); color-mix(in srgb, #05070e 55%, var(--flaeche)) 58%);
background-size:
317px 317px, 223px 223px, 271px 271px,
137px 137px, 191px 191px, 233px 233px, 163px 163px,
89px 89px, 137px 137px, 223px 223px, 107px 107px, 179px 179px,
100% 100%,
100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%,
100% 100%;
border: 1px solid var(--rand); border: 1px solid var(--rand);
/* Die feine helle Linie an der Oberkante. Ein Pixel, kaum sichtbar -- /* Die feine helle Linie an der Oberkante. Ein Pixel, kaum sichtbar --
aber die Kachel wirkt dadurch von oben beleuchtet statt aufgeklebt. aber die Kachel wirkt dadurch von oben beleuchtet statt aufgeklebt.
+12 -12
View File
@@ -12,19 +12,19 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -291,10 +291,10 @@
</form> </form>
</dialog> </dialog>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/aufgaben.js?v=202609180146" defer></script> <script src="assets/js/aufgaben.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/automation.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/automation.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -168,10 +168,10 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/automation.js?v=202609180146" defer></script> <script src="assets/js/automation.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+12 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/entwicklung.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -105,9 +105,9 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/befinden.js?v=202609180146" defer></script> <script src="assets/js/befinden.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+18 -18
View File
@@ -12,24 +12,24 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/bereich.css?v=202609180254" />
<!-- Wegen des Blocks „Willst du dazugehoeren?" auf dem Brett <!-- Wegen des Blocks „Willst du dazugehoeren?" auf dem Brett
„Mitmachen". Eine eigene Kopie der Regel hier waere die zweite „Mitmachen". Eine eigene Kopie der Regel hier waere die zweite
Stelle, an der dieselbe Sache anders aussieht. --> Stelle, an der dieselbe Sache anders aussieht. -->
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/bewerbung.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -243,14 +243,14 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/checkliste.js?v=202609180146" defer></script> <script src="assets/js/checkliste.js?v=202609180254" defer></script>
<script src="assets/js/ampel.js?v=202609180146" defer></script> <script src="assets/js/ampel.js?v=202609180254" defer></script>
<script src="assets/js/schulung.js?v=202609180146" defer></script> <script src="assets/js/schulung.js?v=202609180254" defer></script>
<script src="assets/js/vorlagen.js?v=202609180146" defer></script> <script src="assets/js/vorlagen.js?v=202609180254" defer></script>
<script src="assets/js/bereich.js?v=202609180146" defer></script> <script src="assets/js/bereich.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+15 -15
View File
@@ -7,17 +7,17 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/bereich.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/treff.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/bewerbung.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. --> <!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -107,10 +107,10 @@
</main> </main>
<!-- Der Fuß gehört zu jeder Seite - siehe pruef-css-klassen. --> <!-- Der Fuß gehört zu jeder Seite - siehe pruef-css-klassen. -->
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/auskunft.js?v=202609180146" defer></script> <script src="assets/js/auskunft.js?v=202609180254" defer></script>
<script src="assets/js/bewerben.js?v=202609180146" defer></script> <script src="assets/js/bewerben.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+14 -14
View File
@@ -7,16 +7,16 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/entwicklung.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/bewerbung.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. --> <!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -80,10 +80,10 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/auskunft.js?v=202609180146" defer></script> <script src="assets/js/auskunft.js?v=202609180254" defer></script>
<script src="assets/js/bewerbungen.js?v=202609180146" defer></script> <script src="assets/js/bewerbungen.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/calls.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/calls.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -89,11 +89,11 @@
</main> </main>
<script src="assets/js/ki.js?v=202609180146" defer></script> <script src="assets/js/ki.js?v=202609180254" defer></script>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/calls.js?v=202609180146" defer></script> <script src="assets/js/calls.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -12,26 +12,26 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<!-- aufgaben.css bringt die Dialog- und Formularstile mit (.dialog, <!-- aufgaben.css bringt die Dialog- und Formularstile mit (.dialog,
.neu__zeile, .dialog__knoepfe). Sie stehen dort seit dem .neu__zeile, .dialog__knoepfe). Sie stehen dort seit dem
Aufgabenbrett; sie hierher zu kopieren hiesse, sie an zwei Stellen Aufgabenbrett; sie hierher zu kopieren hiesse, sie an zwei Stellen
zu pflegen. Dieselbe Lösung nutzen kalender.html und content.html. zu pflegen. Dieselbe Lösung nutzen kalender.html und content.html.
Gemeldet von pruef-css-klassen.mjs, bevor jemand einen ungestylten Gemeldet von pruef-css-klassen.mjs, bevor jemand einen ungestylten
Dialog zu sehen bekam. --> Dialog zu sehen bekam. -->
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/chat.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/chat.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -341,10 +341,10 @@
</form> </form>
</dialog> </dialog>
<script src="assets/js/bereiche.js?v=202609180146"></script> <script src="assets/js/bereiche.js?v=202609180254"></script>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146"></script> <script src="assets/js/kopf.js?v=202609180254"></script>
<script src="assets/js/glocke.js?v=202609180146"></script> <script src="assets/js/glocke.js?v=202609180254"></script>
<script src="assets/js/chat.js?v=202609180146"></script> <script src="assets/js/chat.js?v=202609180254"></script>
</body> </body>
</html> </html>
+15 -15
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/content.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/content.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -179,12 +179,12 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/checkliste.js?v=202609180146" defer></script> <script src="assets/js/checkliste.js?v=202609180254" defer></script>
<script src="assets/js/vorlagen.js?v=202609180146" defer></script> <script src="assets/js/vorlagen.js?v=202609180254" defer></script>
<script src="assets/js/content.js?v=202609180146" defer></script> <script src="assets/js/content.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+5 -5
View File
@@ -36,15 +36,15 @@
<link rel="preload" as="image" href="assets/img/buehne/crew-gate-hoch-580.webp" <link rel="preload" as="image" href="assets/img/buehne/crew-gate-hoch-580.webp"
type="image/webp" media="(max-width: 899px)" /> type="image/webp" media="(max-width: 899px)" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<!-- Diese Wand steht NUR auf der Adresse von Team Dogi (ueberall sonst <!-- Diese Wand steht NUR auf der Adresse von Team Dogi (ueberall sonst
404, siehe crewWeiche). Sie darf das Haus deshalb direkt nennen 404, siehe crewWeiche). Sie darf das Haus deshalb direkt nennen
statt ueber den Platzhalter haus.css zu gehen -- und sie MUSS es: statt ueber den Platzhalter haus.css zu gehen -- und sie MUSS es:
Eine Zugangswand, die sich erst nach dem Umbiegen faerbt, waere Eine Zugangswand, die sich erst nach dem Umbiegen faerbt, waere
die eine Seite, auf der man das Umfaerben sieht. --> die eine Seite, auf der man das Umfaerben sieht. -->
<link rel="stylesheet" href="assets/css/crew-haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/crew-haus.css?v=202609180254" />
</head> </head>
<body class="gate gate--crew"> <body class="gate gate--crew">
@@ -339,6 +339,6 @@
</main> </main>
</div> </div>
<script src="assets/js/gate.js?v=202609180146" defer></script> <script src="assets/js/gate.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+4 -4
View File
@@ -22,25 +22,25 @@
}, },
"icons": [ "icons": [
{ {
"src": "/assets/img/app-symbole/crew-192.png?v=202609180146", "src": "/assets/img/app-symbole/crew-192.png?v=202609180254",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png", "type": "image/png",
"purpose": "any" "purpose": "any"
}, },
{ {
"src": "/assets/img/app-symbole/crew-512.png?v=202609180146", "src": "/assets/img/app-symbole/crew-512.png?v=202609180254",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png", "type": "image/png",
"purpose": "any" "purpose": "any"
}, },
{ {
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609180146", "src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609180254",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png", "type": "image/png",
"purpose": "maskable" "purpose": "maskable"
}, },
{ {
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609180146", "src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609180254",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png", "type": "image/png",
"purpose": "maskable" "purpose": "maskable"
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/dateien.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/dateien.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -108,10 +108,10 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/dateien.js?v=202609180146" defer></script> <script src="assets/js/dateien.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+12 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/entwicklung.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -102,9 +102,9 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/entwicklung.js?v=202609180146" defer></script> <script src="assets/js/entwicklung.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+4 -4
View File
@@ -30,9 +30,9 @@
<link rel="preload" as="image" href="assets/img/buehne/gate-hoch-580.webp" <link rel="preload" as="image" href="assets/img/buehne/gate-hoch-580.webp"
type="image/webp" media="(max-width: 899px)" /> type="image/webp" media="(max-width: 899px)" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
</head> </head>
<body class="gate"> <body class="gate">
@@ -401,6 +401,6 @@
</main> </main>
</div> </div>
<script src="assets/js/gate.js?v=202609180146" defer></script> <script src="assets/js/gate.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/kalender.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/kalender.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -377,11 +377,11 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/kalender.js?v=202609180146" defer></script> <script src="assets/js/kalender.js?v=202609180254" defer></script>
<script src="assets/js/kalender-abo.js?v=202609180146" defer></script> <script src="assets/js/kalender-abo.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/leistung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/leistung.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -444,10 +444,10 @@
</form> </form>
</dialog> </dialog>
<script src="assets/js/wahl.js?v=202609180146"></script> <script src="assets/js/wahl.js?v=202609180254"></script>
<script src="assets/js/bereiche.js?v=202609180146"></script> <script src="assets/js/bereiche.js?v=202609180254"></script>
<script src="assets/js/kopf.js?v=202609180146"></script> <script src="assets/js/kopf.js?v=202609180254"></script>
<script src="assets/js/glocke.js?v=202609180146"></script> <script src="assets/js/glocke.js?v=202609180254"></script>
<script src="assets/js/leistung.js?v=202609180146"></script> <script src="assets/js/leistung.js?v=202609180254"></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/personen.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/personen.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -423,10 +423,10 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/personen.js?v=202609180146" defer></script> <script src="assets/js/personen.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/profil.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -214,11 +214,11 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/steckbrief.js?v=202609180146" defer></script> <script src="assets/js/steckbrief.js?v=202609180254" defer></script>
<script src="assets/js/profil.js?v=202609180146" defer></script> <script src="assets/js/profil.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+12 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/treff.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -134,9 +134,9 @@
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen, Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
die seit dem 07.09. jede Seite danach absucht. --> die seit dem 07.09. jede Seite danach absucht. -->
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/rechte.js?v=202609180146" defer></script> <script src="assets/js/rechte.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/report.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/report.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -106,11 +106,11 @@
</main> </main>
<script src="assets/js/ki.js?v=202609180146" defer></script> <script src="assets/js/ki.js?v=202609180254" defer></script>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/report.js?v=202609180146" defer></script> <script src="assets/js/report.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/scouting.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/scouting.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -173,10 +173,10 @@
</div> </div>
</div> </div>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/scouting.js?v=202609180146" defer></script> <script src="assets/js/scouting.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+12 -12
View File
@@ -12,21 +12,21 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<!-- Nur die Startseite: Begrüßungskachel, Uhr, Glockenmulde. Siehe <!-- Nur die Startseite: Begrüßungskachel, Uhr, Glockenmulde. Siehe
den Hinweis in start.css -- dort stand es bis zum 07.09.2026. --> den Hinweis in start.css -- dort stand es bis zum 07.09.2026. -->
<link rel="stylesheet" href="assets/css/heim.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/heim.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -674,10 +674,10 @@
</p> </p>
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/start.js?v=202609180146" defer></script> <script src="assets/js/start.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/startcheck.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -85,11 +85,11 @@
</main> </main>
<script src="assets/js/ki.js?v=202609180146" defer></script> <script src="assets/js/ki.js?v=202609180254" defer></script>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/startcheck.js?v=202609180146" defer></script> <script src="assets/js/startcheck.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/profil.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -146,11 +146,11 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/auskunft.js?v=202609180146" defer></script> <script src="assets/js/auskunft.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/steckbrief.js?v=202609180146" defer></script> <script src="assets/js/steckbrief.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -7,18 +7,18 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/entwicklung.css?v=202609180254" />
<!-- Wegen des Kastens „Anfragen“ ueber der Liste. Eine eigene Kopie <!-- Wegen des Kastens „Anfragen“ ueber der Liste. Eine eigene Kopie
der Regel hier waere die zweite Stelle, an der dieselbe Sache der Regel hier waere die zweite Stelle, an der dieselbe Sache
anders aussieht. --> anders aussieht. -->
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/bewerbung.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -111,9 +111,9 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/talente.js?v=202609180146" defer></script> <script src="assets/js/talente.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -7,20 +7,20 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/team.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/team.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -110,10 +110,10 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/team.js?v=202609180146" defer></script> <script src="assets/js/team.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+12 -12
View File
@@ -7,20 +7,20 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/team.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/team.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<!-- `data-buehne` steht hier fest und nicht im Skript: Die Kachel zu <!-- `data-buehne` steht hier fest und nicht im Skript: Die Kachel zu
@@ -84,9 +84,9 @@
Kaputt ist dabei nichts -- er funktioniert. Genau deshalb faellt Kaputt ist dabei nichts -- er funktioniert. Genau deshalb faellt
es niemandem auf, und deshalb prueft pruef-css-klassen die es niemandem auf, und deshalb prueft pruef-css-klassen die
ABHAENGIGKEIT statt der Optik. Hier hat sie angeschlagen. --> ABHAENGIGKEIT statt der Optik. Hier hat sie angeschlagen. -->
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/teamlage.js?v=202609180146" defer></script> <script src="assets/js/teamlage.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+11 -11
View File
@@ -7,13 +7,13 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/bereich.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -112,9 +112,9 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/teilen.js?v=202609180146" defer></script> <script src="assets/js/teilen.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+12 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/treff.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -126,9 +126,9 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/treff-moderation.js?v=202609180146" defer></script> <script src="assets/js/treff-moderation.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -7,18 +7,18 @@
<meta name="robots" content="noindex, nofollow" /> <meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" /> <link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/treff.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein. Auf der Adresse des <!-- haus.css MUSS die letzte Stilvorlage sein. Auf der Adresse des
Treffs biegt der Server genau diesen Dateinamen auf crew-haus.css Treffs biegt der Server genau diesen Dateinamen auf crew-haus.css
um, und die Seite kommt schon beim ERSTEN Abruf in Lila und um, und die Seite kommt schon beim ERSTEN Abruf in Lila und
Babyblau an -- ohne Umfaerben im Browser, ohne Flackern. --> Babyblau an -- ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -211,10 +211,10 @@
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen, Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
die seit dem 07.09. jede Seite danach absucht. --> die seit dem 07.09. jede Seite danach absucht. -->
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/auskunft.js?v=202609180146" defer></script> <script src="assets/js/auskunft.js?v=202609180254" defer></script>
<script src="assets/js/treff-regeln.js?v=202609180146" defer></script> <script src="assets/js/treff-regeln.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -12,22 +12,22 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<!-- Formular- und Dialogstile: seit dem 07.09.2026 steht hier der <!-- Formular- und Dialogstile: seit dem 07.09.2026 steht hier der
Dialog "Creator anlegen". --> Dialog "Creator anlegen". -->
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/uebersicht.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -149,11 +149,11 @@
</main> </main>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/uebersicht.js?v=202609180146" defer></script> <script src="assets/js/uebersicht.js?v=202609180254" defer></script>
</body> </body>
</html> </html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. --> eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" /> <meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180146" /> <link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609180254" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180146" /> <link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609180254" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/gate.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/start.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/start.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/aufgaben.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/wissen.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/wissen.css?v=202609180254" />
<link rel="stylesheet" href="assets/css/module.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/module.css?v=202609180254" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026). <!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an -- kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. --> ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609180146" /> <link rel="stylesheet" href="assets/css/haus.css?v=202609180254" />
</head> </head>
<body class="start"> <body class="start">
@@ -190,10 +190,10 @@
</main> </main>
<script src="assets/js/wahl.js?v=202609180146" defer></script> <script src="assets/js/wahl.js?v=202609180254" defer></script>
<script src="assets/js/bereiche.js?v=202609180146" defer></script> <script src="assets/js/bereiche.js?v=202609180254" defer></script>
<script src="assets/js/kopf.js?v=202609180146" defer></script> <script src="assets/js/kopf.js?v=202609180254" defer></script>
<script src="assets/js/glocke.js?v=202609180146" defer></script> <script src="assets/js/glocke.js?v=202609180254" defer></script>
<script src="assets/js/wissen.js?v=202609180146" defer></script> <script src="assets/js/wissen.js?v=202609180254" defer></script>
</body> </body>
</html> </html>