Jede Seite erklaert sich selbst -- drei Zeilen, und die dritte rechnet sich aus

Filipe: "ich will in jeder seite auch eine kleine detaillierte aber
schnelle erklaerung kurz und knapps noch zu jeder seite."

DREI ZEILEN AUF JEDER DER 25 SEITEN

  WOFUER    was auf dieser Seite steht
  DU TUST   was man hier konkret macht
  MERKE     nur dort, wo es etwas gibt, das man falsch versteht
  SIEHT     wer diese Seite ueberhaupt oeffnen kann

Offen sichtbar und nicht hinter einem Aufklapper: "schnell" war seine
Bedingung, und eine Erklaerung, die man erst aufklappen muss, ist
genau dann nicht da, wenn man sie braucht.

DIE ZEILE "SIEHT" IST GERECHNET, NICHT GESCHRIEBEN

Sie kommt aus der Rechtetafel -- aus derselben, aus der auch die
Schranke ihre Entscheidung holt. Haette ich sie danebengeschrieben,
waere sie beim ersten Umstellen in "Wer sieht was" still falsch
geworden, in einem Satz, der behauptet, wer etwas sieht. Die Pruefung
stellt die Tafel deshalb wirklich um und sieht nach, ob der Satz
mitwandert.

Die Erklaerung haengt hinter derselben Schranke wie die Seite: Wer sie
nicht oeffnen darf, bekommt 404 -- nicht 403, sonst waere dieser Weg
eine Landkarte des Hauses.

Eingebunden ist sie nicht ueber eine Liste von Dateinamen, sondern
ueber "wer kopf.js laedt": die 26. Seite ist damit automatisch dabei.
Fuenf Seiten haben keine Kopfzeile (Chat, Kalender, Start, Team,
Teamlage) -- dort haengt der Kasten an <main>, sonst waeren
ausgerechnet die haeufigsten Seiten lautlos leer geblieben.

ZWEI EIGENE MAENGEL, GEFUNDEN DURCH HINSEHEN, NICHT DURCH DIE PRUEFUNG

Die erste Fassung war gruen -- und stand mitten auf dem Buehnenbild,
mit einem Lichtfleck hinter "SIEHT". Und "Wofuer" sprach fast woertlich
die Unterzeile darueber nach. Beides misst die Pruefung jetzt: Kontrast
mit dem dritten Ausgang ("steht auf der Buehne" ist kein Ergebnis) und
die Wortueberschneidung mit der Unterzeile.

ZWEI BEFUNDE, DIE SCHON VORHER ROT WAREN

1. pruef-tempo-workspace verglich die UNKOMPRIMIERTE Groesse gegen eine
   Grenze, die fuer die Leitung gedacht war -- waehrend der Kommentar
   daneben "das ist, was wirklich ueber die Leitung ging" behauptete.
   Live steht Caddy davor. Nachgemessen an der echten Adresse:
   start.css 345 KB -> 111 KB zstd. Die Pruefung wog also 1,2 MB, wo
   Filipe 500 KB bekommt. Jetzt wird Komprimierbares im Pruefstand
   gzip-gepackt (115 KB gegen 111 KB live -- auf vier Prozent genau),
   geurteilt wird ueber die uebertragene Groesse, berichtet werden
   beide. Dabei prompt in die dokumentierte Falle getappt: `body()` auf
   einen Ereignisstrom endet nie, der Lauf blieb stehen. Jetzt
   ausgenommen, plus Notbremse je Koerper.

2. pruef-ueberlappung konnte seit Tagen nicht mehr zeigen, dass sie
   eine Ueberlappung ueberhaupt findet: Ihre Gegenprobe legt einen Knopf
   auf einen anderen, traf aber 6 px daneben. Zwei Ursachen in einer
   Zeile -- `position: fixed` bezieht sich auf einen Vorfahren mit
   `transform`, und die `transition` der Knoepfe liefert beim sofortigen
   Messen die Lage von vorher. Jetzt `transform` + `transition: none`:
   34x36 px erkannt, 20 Seiten-Breiten-Paare, 0 Befunde.

PRUEFUNGEN: pruef-erklaerung neu mit 44, davon 8 im Browser (Seite mit
und ohne Kopfzeile, Handy, Kontrast, Echo). Mein Schild stand auf
10,88 px und lag unter der Hausgrenze von 11,5 -- gefunden von
pruef-css-klassen, nicht vom Auge.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-14 18:20:30 +02:00
co-authored by Claude Opus 5
parent 0cce22c08c
commit de19684883
36 changed files with 1307 additions and 353 deletions
+2
View File
@@ -26,6 +26,7 @@ import { bereicheRouter } from "./workspace-bereiche.js";
import { treffRouter } from "./workspace-treff.js";
import { entwicklungRouter } from "./workspace-entwicklung.js";
import { rechteRouter, tafelLaden } from "./workspace-rechte.js";
import { erklaerungRouter } from "./workspace-erklaerung.js";
import { reportRouter } from "./workspace-reports.js";
import { scoutRouter } from "./workspace-scouts.js";
import { callRouter } from "./workspace-calls.js";
@@ -252,6 +253,7 @@ app.use(treffRouter);
app.use(entwicklungRouter);
/* Die Rechtetafel -- ansehen und umstellen (11.09.2026). */
app.use(rechteRouter);
app.use(erklaerungRouter);
app.use(reportRouter);
app.use(scoutRouter);
app.use(callRouter);
+455
View File
@@ -0,0 +1,455 @@
/* =====================================================================
Die kurze Erklärung auf jeder Seite (14.09.2026)
Filipe: „ich will in jeder seite auch eine kleine detaillierte aber
schnelle erklärung kurz und knapps noch zu jeder seite."
---------------------------------------------------------------------
WAS HIER WIRKLICH GEMESSEN WIRD
Dass ein Text ankommt, ist die leichteste und unwichtigste Frage.
Die drei, auf die es ankommt:
1. GIBT ES ZU JEDER SEITE EINEN? — abgeleitet aus der Rechtetafel,
nicht gegen eine Zahl. Kommt morgen eine 26. Seite dazu und
niemand schreibt ihr einen Text, muss das hier rot werden.
2. IST DIE ZEILE „SIEHT" GERECHNET ODER BEHAUPTET? — geprüft,
indem die Rechtetafel wirklich umgestellt wird. Wandert der
Satz mit, kommt er aus der Tafel. Ohne diese Gegenprobe wäre
„steht da" auch dann grün, wenn der Satz danebengeschrieben
wäre — und das ist die eine Angabe, die niemals lügen darf.
3. IST DIE ERKLÄRUNG SO VERSCHLOSSEN WIE DIE SEITE? — ein Modi
fragt nach „Personen & Zugänge" und muss 404 bekommen, nicht
den Text und nicht „verboten". Sonst ist dieser Weg eine
Landkarte des Hauses.
Dazu, im Browser: Der Kasten muss auf einer Seite MIT Kopfzeile
erscheinen und auf einer OHNE. Der zweite Fall ist der, der lautlos
ausfallen würde — fünf Seiten haben keine `.kopf-zeile`, darunter
Chat und Kalender.
Aufrufen mit: node server/pruef-erklaerung.mjs
===================================================================== */
import { mkdtempSync, rmSync, readFileSync, readdirSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { request as httpAnfrage } from "node:http";
import { portMussFreiSein } from "./helfer-port.mjs";
const PORT = await portMussFreiSein(4406, "pruef-erklaerung");
const ordner = mkdtempSync(join(tmpdir(), "ws-erkl-"));
process.env.WORKSPACE_DB = join(ordner, "workspace.db");
process.env.PORT = String(PORT);
process.env.SITE_ACCESS_SECRET = "lokaler-test";
process.env.SITE_PUBLIC_LAUNCH_AT = "2020-01-01T00:00:00+01:00";
const express = (await import("express")).default;
const ec = express.response.cookie;
express.response.cookie = function (n, w, o) { return ec.call(this, n, w, { ...(o || {}), secure: false }); };
import { notbremse } from "./helfer-notbremse.mjs";
await import("./index.js");
notbremse(240_000, "pruef-erklaerung");
await new Promise((r) => setTimeout(r, 700));
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 CREW = "crew.dogfather-universe.com";
const HAUS = "workspace.dogfather-universe.com";
const BASIS = `http://127.0.0.1:${PORT}`;
const { DatabaseSync } = await import("node:sqlite");
const { scryptSync, randomBytes, createHmac } = await import("node:crypto");
const rechte = await import("./rechte.js");
const { ERKLAERUNGEN } = await import("./workspace-erklaerung.js");
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 hash = scryptSync(code, salt, 64, { N: 32768, r: 8, p: 1, maxmem: 96 * 1024 * 1024 }).toString("hex");
d.prepare("INSERT INTO personen (name, rolle, code_hash, code_salt, code_n, code_kennung, aktiv, erstellt)"
+ " VALUES (?,?,?,?,?,?,1,?)")
.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");
anlegen("Rieke", "hand", "CODE-HAND-0001");
anlegen("Frida", "modi", "CODE-MODI-0001");
d.close();
function roh(pfad, host, kopf = {}, koerper = null, methode = null) {
if (methode === "DELETE") koerper = null;
return new Promise((fertig, schief) => {
const a = httpAnfrage({
host: "127.0.0.1", port: PORT, path: pfad,
method: methode || (koerper ? "POST" : "GET"),
headers: { Host: host, ...(koerper ? { "Content-Type": "application/json" } : {}), ...kopf },
}, (antwort) => {
let text = "";
antwort.on("data", (s) => { text += s; });
antwort.on("end", () => fertig({ code: antwort.statusCode, text, kopf: antwort.headers }));
});
a.on("error", schief);
if (koerper) a.write(JSON.stringify(koerper));
a.end();
});
}
const json = (a) => { try { return JSON.parse(a.text); } catch { return {}; } };
async function anmelden(rolle, code, host) {
const r = await roh("/workspace/api/anmelden", host, {}, { rolle, code });
return [].concat(r.kopf?.["set-cookie"] || []).map((c) => c.split(";")[0]).join("; ");
}
const kDogi = await anmelden("admin", "CODE-DOGI-0001", HAUS);
const kHand = await anmelden("hand", "CODE-HAND-0001", CREW);
const kModi = await anmelden("modi", "CODE-MODI-0001", CREW);
ok(!!kDogi && !!kHand && !!kModi, "DogFather, rechte Hand und ein Modi sind angemeldet");
const erkl = (datei, host, keks) =>
roh("/workspace/api/erklaerung?seite=" + datei, host, { cookie: keks });
/* =======================================================================
1. ZU JEDER SEITE EIN TEXT — abgeleitet, nicht gegen eine Zahl
======================================================================= */
melde("");
melde("=== 1. Jede Seite hat einen Text ===");
{
const seiten = rechte.alleSeiten().map((p) => p.replace("/workspace/", ""));
ok(seiten.length > 20, `${seiten.length} Seiten in der Rechtetafel`);
const ohne = seiten.filter((s) => !ERKLAERUNGEN[s]);
ok(ohne.length === 0,
ohne.length ? `OHNE TEXT: ${ohne.join(", ")}` : `zu allen ${seiten.length} Seiten steht ein Text`);
/* Und umgekehrt: kein Text zu einer Seite, die es gar nicht gibt.
Sonst sammelt sich hier Prosa zu Seiten, die längst weg sind. */
const verwaist = Object.keys(ERKLAERUNGEN).filter((s) => !seiten.includes(s));
ok(verwaist.length === 0,
verwaist.length ? `TEXT OHNE SEITE: ${verwaist.join(", ")}` : "und kein Text zu einer Seite, die es nicht gibt");
/* GEGENPROBE zum Sucher selbst: Eine erfundene Seite MUSS als fehlend
auffallen -- sonst wäre die Zeile darüber auch bei leerer Tabelle grün. */
ok(!ERKLAERUNGEN["gibt-es-nicht.html"],
"eine erfundene Seite hat erwartungsgemäß keinen Text");
}
/* =======================================================================
2. KURZ UND KNAPP — seine Bedingung, also gemessen
======================================================================= */
melde("");
melde("=== 2. Kurz und knapp ===");
{
const alle = Object.entries(ERKLAERUNGEN);
ok(alle.length > 20, `${alle.length} Erklärungen geprüft`);
const zuLang = alle.filter(([, e]) =>
[e.wofuer, e.tun, e.merke].filter(Boolean).some((s) => s.length > 135));
ok(zuLang.length === 0,
zuLang.length ? `ZU LANG: ${zuLang.map(([s]) => s).join(", ")}`
: "kein Satz über 135 Zeichen — „kurz und knapp“ war die Bedingung");
const leer = alle.filter(([, e]) => !e.wofuer?.trim() || !e.tun?.trim());
ok(leer.length === 0, "jede Erklärung hat „Wofür“ und „Du tust“");
/* KEINE KLICKANLEITUNGEN. Sie altern mit jedem Umbau der Oberfläche
und zeigen danach ins Leere -- schlimmer als gar kein Text. */
const klick = alle.filter(([, e]) =>
/klicke|tippe auf|oben rechts|unten links|Schaltfläche/i.test(
[e.wofuer, e.tun, e.merke].filter(Boolean).join(" ")));
ok(klick.length === 0,
klick.length ? `KLICKANLEITUNG: ${klick.map(([s]) => s).join(", ")}`
: "keine Klickanleitungen — erklärt wird der Zweck, nicht der Weg");
ok(/klicke/i.test("dann klicke oben rechts"), "und der Sucher findet so eine auch wirklich");
/* HAUSREGEL: echte Umlaute in allem, was ein Mensch liest. */
const ascii = alle.filter(([, e]) =>
/\b(fuer|koenn|muess|ueber|waer|moecht|oeffn|schliess)/i.test(
[e.wofuer, e.tun, e.merke].filter(Boolean).join(" ")));
ok(ascii.length === 0,
ascii.length ? `ASCII-UMLAUTE: ${ascii.map(([s]) => s).join(", ")}` : "keine ASCII-Ersatzumlaute");
}
/* =======================================================================
3. DIE ZEILE „SIEHT" IST GERECHNET, NICHT BEHAUPTET
Das ist die Prüfung, derentwegen es diese Datei gibt.
======================================================================= */
melde("");
melde("=== 3. Gerechnet, nicht behauptet ===");
{
const vorher = json(await erkl("talente.html", HAUS, kDogi));
ok(vorher.hat_text === true, "DogFather bekommt die Erklärung zu „Talente“");
ok(Array.isArray(vorher.sichtbar) && vorher.sichtbar.includes("Rechte Hand"),
`dort steht, wer sie sieht: ${(vorher.sichtbar || []).join(" · ")}`);
/* Die Rangfolge gilt auch hier: die rechte Hand direkt hinter DogFather. */
ok(vorher.sichtbar[0] === "DogFather" && vorher.sichtbar[1] === "Rechte Hand",
"in der Rangfolge des Hauses, nicht alphabetisch");
/* JETZT DIE TAFEL WIRKLICH UMSTELLEN. */
const zu = await roh("/workspace/api/rechte/feld", HAUS, { cookie: kDogi },
{ pfad: "/workspace/talente.html", rolle: "hand", erlaubt: false }, "PUT");
ok(zu.code === 200, `die rechte Hand wird für „Talente“ abgeschaltet (${zu.code})`);
const nachher = json(await erkl("talente.html", HAUS, kDogi));
ok(!(nachher.sichtbar || []).includes("Rechte Hand"),
`danach steht sie nicht mehr da: ${(nachher.sichtbar || []).join(" · ")}`);
ok(vorher.sichtbar.length - 1 === nachher.sichtbar.length,
"genau eine Rolle weniger — der Satz kommt also aus der Tafel");
/* Und sie bekommt die Erklärung jetzt auch selbst nicht mehr. */
const ihre = await erkl("talente.html", CREW, kHand);
ok(ihre.code === 404,
`und sie selbst bekommt jetzt 404 statt des Textes (${ihre.code})`);
/* ZURÜCK — eine Prüfung, die den Stand verändert zurücklässt, ist
eine Falle für die nächste. */
const auf = await roh("/workspace/api/rechte/feld", HAUS, { cookie: kDogi },
{ pfad: "/workspace/talente.html", rolle: "hand", erlaubt: true }, "PUT");
ok(auf.code === 200, "danach ist alles wieder wie vorher");
const zurueck = json(await erkl("talente.html", HAUS, kDogi));
ok((zurueck.sichtbar || []).join() === vorher.sichtbar.join(),
"und der Satz steht wieder genau so da wie am Anfang");
}
/* =======================================================================
4. SO VERSCHLOSSEN WIE DIE SEITE SELBST
======================================================================= */
melde("");
melde("=== 4. Dieselbe Schranke ===");
{
const fremd = await erkl("personen.html", CREW, kModi);
ok(fremd.code === 404,
`ein Modi bekommt zu „Personen & Zugänge“ ein 404 (${fremd.code})`);
ok(!/Zugangscode|Rolle/.test(fremd.text),
"und kein Wort aus dem Text — die Absage verrät nichts über die Seite");
/* GEGENPROBE: Eine Seite, die er öffnen darf, bekommt er auch erklärt.
Ohne sie wäre „404“ oben auch dann grün, wenn der Weg gar nicht
funktioniert. */
const seine = json(await erkl("entwicklung.html", CREW, kModi));
ok(seine.hat_text === true, "seine eigene Entwicklungsseite bekommt er erklärt");
const ohneAnmeldung = await erkl("start.html", HAUS, "");
ok(ohneAnmeldung.code === 401, `ohne Anmeldung gar nichts (${ohneAnmeldung.code})`);
/* Kein Weg aus dem Verzeichnis heraus. */
for (const bösartig of ["../../etc/passwd", "..%2Fgeheim.html", "start.html%00", "start"]) {
const r = await erkl(encodeURIComponent(bösartig), HAUS, kDogi);
ok(r.code === 400, `„${bösartig}“ wird abgelehnt (${r.code})`);
}
}
/* =======================================================================
5. AUF JEDER SEITE EINGEBUNDEN — auch auf denen ohne Kopfzeile
======================================================================= */
melde("");
melde("=== 5. Auf jeder Seite eingebunden ===");
{
const dateien = readdirSync("workspace").filter((n) => n.endsWith(".html"));
const mitKopf = dateien.filter((n) =>
/assets\/js\/kopf\.js/.test(readFileSync("workspace/" + n, "utf8")));
ok(mitKopf.length > 20, `${mitKopf.length} Seiten laden kopf.js`);
const ohne = mitKopf.filter((n) =>
!/assets\/js\/erklaerung\.js/.test(readFileSync("workspace/" + n, "utf8")));
ok(ohne.length === 0,
ohne.length ? `OHNE erklaerung.js: ${ohne.join(", ")}` : "alle davon laden auch erklaerung.js");
/* Die fünf ohne Kopfzeile sind der Fall, der lautlos ausfallen würde
-- der Kasten hängt sich dort an <main> statt hinter die Kopfzeile.
Die Zahl gehört in die Bedingung: Fände die Suche keine, wäre der
zweite Weg nie geprüft worden. */
const ohneKopfzeile = mitKopf.filter((n) =>
!/class="kopf-zeile"/.test(readFileSync("workspace/" + n, "utf8")));
ok(ohneKopfzeile.length > 0,
`${ohneKopfzeile.length} Seiten haben keine Kopfzeile: ${ohneKopfzeile.join(", ")}`);
}
/* =======================================================================
6. UND STEHT SIE AUCH WIRKLICH AUF DEM BILDSCHIRM?
======================================================================= */
melde("");
melde("=== 6. Im Browser ===");
{
const { chromium } = await import(
"file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs");
const browser = await chromium.launch();
const kontext = await browser.newContext({ viewport: { width: 1280, height: 900 } });
const seite = await kontext.newPage();
const konsole = [];
seite.on("console", (m) => { if (m.type() === "error" && !/favicon|ERR_/i.test(m.text())) konsole.push(m.text()); });
seite.on("pageerror", (e) => konsole.push("Absturz: " + e.message));
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: 20000 });
/** Wartet, bis der Kasten da ist -- oder bis feststeht, dass er nicht kommt. */
async function ansehen(datei) {
await seite.goto(`${BASIS}/workspace/${datei}`, { waitUntil: "networkidle" });
await seite.waitForSelector(".erkl", { timeout: 6000 }).catch(() => {});
return seite.evaluate(() => {
const k = document.querySelector(".erkl");
if (!k) return { da: false };
const r = k.getBoundingClientRect();
const schilder = [...k.querySelectorAll(".erkl__schild")].map((s) => s.textContent.trim());
return {
da: true, hoehe: Math.round(r.height), breite: Math.round(r.width),
inMain: !!k.closest("main"),
schilder, text: k.innerText.trim(),
/* Steht er VOR dem ersten Inhalt und nicht irgendwo mittendrin? */
erstesDrittel: r.top < window.innerHeight,
};
});
}
/* Eine Seite MIT Kopfzeile ... */
const mit = await ansehen("talente.html");
ok(mit.da === true, "auf „Talente“ (mit Kopfzeile) steht der Kasten");
ok(mit.inMain && mit.erstesDrittel, "im Inhalt und ohne Scrollen sichtbar");
ok(mit.schilder.join(",").includes("SIEHT") || /SIEHT/i.test(mit.text),
`mit allen Zeilen: ${mit.schilder.join(" / ")}`);
ok(mit.hoehe > 30 && mit.hoehe < 260, `und er bleibt klein (${mit.hoehe} px hoch)`);
/* ===================================================================
STEHT DER TEXT AUF EINER FLAECHE -- UND IST ER LESBAR?
BEIDE MAENGEL WAREN IN DER ERSTEN FASSUNG GRUEN. Gefunden hat sie
nicht diese Datei, sondern ein Blick auf das Bildschirmfoto: Der
Kasten stand mitten auf der Buehne, mit einem Lichtfleck hinter
„SIEHT". Eine Pruefung, die Groesse und Position misst und nicht
die Lesbarkeit, prueft das Bequeme statt das Wichtige.
DREI AUSGAENGE, wie ueberall: lesbar / zu dunkel / konnte nicht
nachsehen. Der dritte ist hier der eigentliche Fund -- Text auf
einem Foto hat gar keinen berechenbaren Kontrast, und genau das
war der Zustand. */
const KONTRAST = `(() => {
const leuchte = (r, g, b) => {
const f = (c) => { c /= 255; return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); };
return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);
};
const zahlen = (s) => (s.match(/[\d.]+/g) || []).map(Number);
/* Der erste Vorfahr mit einer WIRKLICH deckenden Flaeche. Alles
darunter ist Durchsicht -- und ein Foto ist keine Flaeche. */
const grund = (e) => {
let n = e;
while (n && n !== document.documentElement) {
const st = getComputedStyle(n);
const f = zahlen(st.backgroundColor);
const deckend = f.length >= 3 && (f.length < 4 || f[3] >= 0.92);
if (deckend && st.backgroundImage === 'none') return f.slice(0, 3);
if (deckend) return null; // deckend, aber ein Bild darauf
n = n.parentElement;
}
return null;
};
const kasten = document.querySelector('.erkl');
if (!kasten) return { fehlt: true };
const stuecke = [...kasten.querySelectorAll('.erkl__schild, .erkl__satz')];
const schlecht = [], geraten = [];
let gemessen = 0;
for (const s of stuecke) {
if (!s.textContent.trim()) continue;
const h = grund(s);
if (!h) { geraten.push(s.textContent.trim().slice(0, 30)); continue; }
const v = zahlen(getComputedStyle(s).color).slice(0, 3);
const a = leuchte(...v), b = leuchte(...h);
const v2 = (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);
gemessen++;
if (v2 < 4.5) schlecht.push(s.textContent.trim().slice(0, 30) + ' = ' + v2.toFixed(2));
}
return { gemessen, schlecht, geraten };
})()`;
const k = await seite.evaluate(KONTRAST);
/* DIE ZAHL GEHOERT IN DIE BEDINGUNG: Faende die Messung kein
Textstueck, waere „alles lesbar" trivial wahr. */
ok(k.gemessen >= 6 && k.schlecht.length === 0,
`${k.gemessen} Textstücke im Kasten, alle lesbar`
+ (k.schlecht.length ? " -- ZU DUNKEL: " + k.schlecht.join(" | ") : ""));
ok(k.geraten.length === 0,
`jedes davon steht auf einer deckenden Fläche`
+ (k.geraten.length ? ` -- AUF DER BÜHNE (${k.geraten.length}): ` + k.geraten.slice(0, 3).join(" | ") : ""));
/* ===================================================================
SPRICHT „WOFUER" DIE UNTERZEILE NACH?
Auch das war gruen und trotzdem falsch: Auf „Talente" stand oben
„Zuschauer, die ins Team passen koennten. Ein Trichter, keine
Liste" -- und zwei Zeilen darunter fast woertlich dasselbe. Das
liest sich wie ein Kopierfehler und verschenkt die Zeile.
Gemessen wird der Anteil der langen Woerter, die in BEIDEN Saetzen
vorkommen. Ueber der Haelfte ist es keine Erklaerung mehr, sondern
ein Echo. */
const echo = await seite.evaluate(() => {
const u = document.querySelector('main .unterzeile')?.textContent?.trim() || '';
const zeilen = [...document.querySelectorAll('.erkl__zeile')];
const w = zeilen.find((z) => /wof/i.test(z.querySelector('.erkl__schild')?.textContent || ''));
const wofuer = w?.querySelector('.erkl__satz')?.textContent?.trim() || '';
if (!u || !wofuer) return { pruefbar: false, u, wofuer };
const lang = (s) => new Set((s.toLowerCase().match(/[a-zäöüß]{5,}/g) || []));
const a = lang(wofuer), b = lang(u);
if (!a.size) return { pruefbar: false, u, wofuer };
let gleich = 0;
for (const x of a) if (b.has(x)) gleich++;
return { pruefbar: true, anteil: gleich / a.size, gleich, gesamt: a.size, u, wofuer };
});
ok(echo.pruefbar === true,
echo.pruefbar ? "Unterzeile und „Wofür“ stehen beide da — vergleichbar"
: `nicht vergleichbar (Unterzeile: „${(echo.u || "").slice(0, 40)}")`);
ok(echo.pruefbar && echo.anteil < 0.5,
`„Wofür“ sagt etwas anderes als die Unterzeile (${echo.gleich} von ${echo.gesamt} langen Wörtern gleich)`);
/* ... und eine OHNE. Das ist der Fall, der lautlos ausfallen würde. */
const ohne = await ansehen("kalender.html");
ok(ohne.da === true, "auf „Kalender“ (OHNE Kopfzeile) steht er genauso");
ok(ohne.inMain, "und zwar im Inhalt, nicht davor");
/* Am Handy: bricht nichts seitlich aus? */
const handy = await browser.newContext({ viewport: { width: 390, height: 844 } });
const s2 = await handy.newPage();
await s2.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" });
await s2.click('.rolle[data-rolle="admin"]');
await s2.fill("#code", "CODE-DOGI-0001");
await s2.click("button[type=submit]");
await s2.waitForURL("**/start.html", { timeout: 20000 });
await s2.goto(BASIS + "/workspace/talente.html", { waitUntil: "networkidle" });
await s2.waitForSelector(".erkl", { timeout: 6000 }).catch(() => {});
const eng = await s2.evaluate(() => {
const k = document.querySelector(".erkl");
if (!k) return null;
const r = k.getBoundingClientRect();
return { raus: Math.round(r.right - document.documentElement.clientWidth), hoehe: Math.round(r.height) };
});
ok(eng !== null && eng.raus <= 1, `am Handy nichts seitlich draußen (${eng?.raus} px)`);
ok(eng !== null && eng.hoehe < 340, `und immer noch kompakt (${eng?.hoehe} px)`);
ok(konsole.length === 0,
konsole.length ? "Fehler im Browser: " + konsole[0].slice(0, 90) : "keine Fehler im Browser");
await browser.close();
}
/* ------------------------------------------------------------------- */
melde("");
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
melde(fehler ? "NICHT IN ORDNUNG" : "ALLES IN ORDNUNG");
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* Aufraeumrest */ }
process.exit(fehler ? 1 : 0);
+86 -5
View File
@@ -28,6 +28,7 @@
GEGENPROBE am Ende: eine kuenstlich erzeugte Doppelanfrage und ein
kuenstlicher Layout-Sprung muessen gefunden werden. */
import { gzipSync } from "node:zlib";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
@@ -153,9 +154,45 @@ await seite.waitForTimeout(600);
/* Grenzen. Grosszuegig -- sie sollen den Ausreisser finden, nicht das
Kilobyte. */
const GRENZE_ANFRAGEN = 40;
const GRENZE_BYTES = 1_200_000;
const GRENZE_MS = 4000;
/* ---- DAS GEWICHT: GEMESSEN WIRD, WAS UEBER DIE LEITUNG GEHT ----------
BIS ZUM 14.09.2026 WURDE HIER DAS FALSCHE GEMESSEN, und der Kommentar
daneben behauptete sogar das Richtige („das ist, was wirklich ueber
die Leitung ging"). Der Pruefstand spricht mit dem nackten
Express-Server auf 127.0.0.1, und der komprimiert nicht. Live steht
davor Caddy.
NACHGEMESSEN an der echten Adresse, nicht vermutet:
curl -H 'Accept-Encoding: zstd' workspace.dogfather-universe.com/…
start.css 345 KB -> 111 KB (Content-Encoding: zstd)
gate.css 120 KB -> 40 KB
kopf.js 65 KB -> 24 KB
Die Prueferei verglich also rund 1,2 MB gegen eine Grenze, die fuer
die Leitung gedacht war -- waehrend Filipe rund 500 KB bekommt. Die
Folge war eine Warnung, die nichts ueber sein Erlebnis sagt: genau
die Sorte, die man nach dreimal Lesen wegklickt.
JETZT WIRD BEIDES GEMESSEN. Komprimierbares wird im Pruefstand
gzip-gepackt (gemessen: start.css 356 KB -> 115 KB gzip gegen 111 KB
zstd live -- ein Stellvertreter, der auf vier Prozent genau ist),
alles andere zaehlt roh. Geurteilt wird ueber die uebertragene
Groesse, berichtet werden beide.
DIE GRENZE: 900 KB uebertragen. Die schwerste Seite liegt heute bei
rund 500 KB, davon 286 KB Buehnenbild -- das ist der Ausreisser, den
diese Zahl finden soll, mit Luft fuer eine zweite. Die rohe Groesse
bleibt in der Ausgabe stehen: Sie kostet zwar keine Leitung, aber
Rechenzeit beim Auswerten, und sie ist die Zahl, die man senken kann. */
const GRENZE_UEBERTRAGEN = 900_000;
/* Was Caddy komprimiert. Bilder, Schriften und Videos sind bereits
gepackt -- sie noch einmal durch gzip zu schicken kostet Zeit und
spart nichts. */
const KOMPRIMIERBAR = /^(text\/|application\/(javascript|json|xml|manifest)|image\/svg)/i;
/* ---- Layout-Sprung: eine GRUNDLINIE, kein Wunschwert ------------------
Gemessen am 04.09.2026 (Audit): Die Seiten springen beim Aufbau
zwischen 0 und 0,54. Nach Web Vitals gilt unter 0,1 als gut. Der
@@ -175,6 +212,7 @@ const ZIEL_SPRUNG = 0.1; // Web Vitals "gut" -- noch nicht erreicht
const zeilen = [];
let seitenGesamt = 0, anfragenGesamt = 0, bytesGesamt = 0;
const nichtGewogen = [];
const doppelte = [];
const langsame = [];
const springende = [];
@@ -184,9 +222,34 @@ const zuGross = [];
for (const datei of SEITEN) {
const gesehen = new Map();
let bytes = 0;
let roheBytes = 0, uebertragen = 0;
const warten = [];
const zaehler = (antwort) => {
const u = antwort.url();
gesehen.set(u, (gesehen.get(u) || 0) + 1);
/* Den Koerper JETZT holen -- nach dem Seitenwechsel ist er weg.
Ein Fehlschlag (Umleitung, 204, abgebrochen) ist kein Befund,
sondern schlicht nichts zu wiegen. */
const art = antwort.headers()["content-type"] || "";
/* EIN EREIGNISSTROM ENDET NIE -- und `body()` darauf auch nicht.
Genau daran ist am 06.09.2026 schon einmal ein ganzer Lauf
stehengeblieben, und hier ist es sofort wieder passiert: Der
Workspace haelt eine offene Verbindung fuer Benachrichtigungen.
Erst gar nicht anfassen -- und fuer alles andere trotzdem eine
Notbremse, weil die naechste Sorte Dauerverbindung noch nicht
erfunden ist. */
if (/event-stream/i.test(art)) return;
warten.push((async () => {
try {
const k = await Promise.race([
antwort.body(),
new Promise((r) => setTimeout(() => r(null), 3000)),
]);
if (!k?.length) return;
roheBytes += k.length;
uebertragen += KOMPRIMIERBAR.test(art) ? gzipSync(k).length : k.length;
} catch { /* nichts zu wiegen */ }
})());
};
seite.on("response", zaehler);
@@ -195,6 +258,7 @@ for (const datei of SEITEN) {
await seite.waitForTimeout(500);
const dauer = Date.now() - start;
seite.off("response", zaehler);
await Promise.all(warten);
/* Uebertragene Groesse aus der Zeitleiste des Browsers -- das ist,
was wirklich ueber die Leitung ging. */
@@ -309,12 +373,23 @@ for (const datei of SEITEN) {
schwankend.push(`${datei} ${sprung} → beim Nachmessen ${zweitens.wert}`);
}
}
if (anfragen > GRENZE_ANFRAGEN || bytes > GRENZE_BYTES) {
zuGross.push(`${datei} ${anfragen} Anfragen / ${Math.round(bytes / 1024)} KB`);
/* KONNTE ueberhaupt gewogen werden? Kommt aus den Koerpern nichts
zurueck (Browser aus dem Zwischenspeicher, alles abgebrochen),
waere „unter der Grenze" trivial wahr. Dann gilt die Zeitleiste
des Browsers als Rueckfall -- und der dritte Ausgang steht in der
Ausgabe. */
const gewogen = uebertragen > 0;
const zaehlwert = gewogen ? uebertragen : bytes;
if (!gewogen) nichtGewogen.push(datei);
if (anfragen > GRENZE_ANFRAGEN || zaehlwert > GRENZE_UEBERTRAGEN) {
zuGross.push(`${datei} ${anfragen} Anfragen / ${Math.round(zaehlwert / 1024)} KB übertragen`);
}
zeilen.push(` ${datei.padEnd(22)} ${String(anfragen).padStart(3)} Anfragen `
+ `${String(Math.round(bytes / 1024)).padStart(4)} KB ${String(dauer).padStart(4)} ms `
+ `${String(Math.round(zaehlwert / 1024)).padStart(4)} KB über die Leitung `
+ `(roh ${String(Math.round((roheBytes || bytes) / 1024)).padStart(4)}) `
+ `${String(dauer).padStart(4)} ms `
+ `Sprung ${String(sprung).padStart(5)} ${String(messung.knoten).padStart(4)} Knoten`);
}
@@ -388,7 +463,13 @@ console.log(` hinw ${ueberZiel} von ${seitenGesamt} Seiten liegen ueber dem Z
+ `${ZIEL_SPRUNG} fuer den Layout-Sprung (bauartbedingt: Geruest zuerst, Daten danach)`);
ok(zuGross.length === 0,
zuGross.length ? `zu schwer: ${zuGross.join(", ")}`
: `keine Seite ueber ${GRENZE_ANFRAGEN} Anfragen oder ${Math.round(GRENZE_BYTES / 1024)} KB`);
: `keine Seite ueber ${GRENZE_ANFRAGEN} Anfragen oder ${Math.round(GRENZE_UEBERTRAGEN / 1024)} KB ueber die Leitung`);
/* DER DRITTE AUSGANG: Konnte ueberhaupt gewogen werden? Eine Seite,
deren Koerper der Browser aus dem Zwischenspeicher genommen hat,
waere sonst lautlos „leicht“. */
ok(nichtGewogen.length === 0,
nichtGewogen.length ? `KONNTE NICHT WIEGEN: ${nichtGewogen.join(", ")} -- Ergebnis unbrauchbar`
: `alle ${seitenGesamt} Seiten wirklich gewogen`);
/* =======================================================================
GEGENPROBE
+23 -3
View File
@@ -133,9 +133,29 @@ for (const breite of BREITEN) {
/* Den letzten Knopf genau auf den ersten legen. */
const erst = teile[0].getBoundingClientRect();
const letzt = teile[teile.length - 1];
letzt.style.position = "fixed";
letzt.style.left = erst.left + "px";
letzt.style.top = erst.top + "px";
/* MIT transform STATT position:fixed (14.09.2026).
`position: fixed` bezieht sich NICHT immer auf das Fenster: Hat
ein Vorfahr `transform`, `filter` oder `backdrop-filter`, wird er
selbst zum Bezugsrahmen. Die Kopfleiste hat so einen. Der Knopf
landete dadurch 6 px neben dem Ziel -- gemessen {x:-6, y:36} --,
die Gegenprobe meldete „nicht erkannt“, und damit konnte diese
Pruefung tagelang nicht mehr zeigen, dass sie eine Ueberlappung
ueberhaupt findet. Eine Pruefung, die das nicht kann, bestaetigt
nichts.
`transform` verschiebt relativ zur EIGENEN aktuellen Lage. Wo der
Bezugsrahmen liegt, ist damit gleichgueltig. */
/* UND OHNE UEBERBLENDUNG. Die Knoepfe der Kopfleiste haben eine
`transition`; wer unmittelbar nach dem Setzen misst, bekommt die
Lage von VORHER zurueck -- die Bewegung hat noch nicht
stattgefunden. Das war die zweite Haelfte desselben Fehlers.
Derselbe Grund, aus dem in pruef-dabei-optik das Haekchen
„0 → 0“ meldete, bis dort die Ueberblendung abgewartet wurde. */
letzt.style.transition = "none";
const vorher = letzt.getBoundingClientRect();
letzt.style.transform =
`translate(${erst.left - vorher.left}px, ${erst.top - vorher.top}px)`;
letzt.style.zIndex = "99";
// Messen wie oben, aber nur dieses eine Paar.
const a2 = teile[0].getBoundingClientRect(), b2 = letzt.getBoundingClientRect();
+229
View File
@@ -0,0 +1,229 @@
/* =====================================================================
Die kurze Erklärung auf jeder Seite (14.09.2026)
Filipe: *„ich will in jeder seite auch eine kleine detaillierte aber
schnelle erklärung kurz und knapps noch zu jeder seite."*
---------------------------------------------------------------------
DREI ZEILEN, UND DIE DRITTE RECHNET SICH SELBST AUS
WOFÜR wozu es diese Seite gibt
DU TUST was man hier konkret macht — nicht was man könnte
SIEHT wer diese Seite überhaupt öffnen kann
Die ersten beiden sind geschriebener Text. Die dritte ist es NICHT:
Sie wird aus der Rechtetafel gerechnet, aus derselben, aus der auch
die Schranke ihre Entscheidung holt. Das ist der ganze Grund, warum
diese Zeile hier stehen darf.
Hätte ich sie danebengeschrieben, wäre sie beim ersten Umstellen in
„Wer sieht was" falsch geworden — und zwar STILL falsch, in einem
Satz, der behauptet, wer etwas sieht. Genau diese Sorte Zweitschrift
hat im Projekt schon dreimal Daten oder Vertrauen gekostet (die
abgeschriebene Spaltenliste, die zweite Rollenreihenfolge im
Browser, das fest eingetragene Wort „Agentur"). Eine Angabe über
Sichtbarkeit ist der schlechteste Ort, um es ein viertes Mal zu tun.
---------------------------------------------------------------------
WARUM DIE ERKLÄRUNG HINTER DERSELBEN SCHRANKE STEHT WIE DIE SEITE
Wer eine Seite nicht öffnen darf, bekommt auch ihre Erklärung nicht
— mit 404, nicht mit 403. Sonst wäre dieser Weg eine Landkarte des
Hauses: Ein Modi könnte abfragen, dass es „Personen & Zugänge" gibt,
wozu die Seite dient und wer sie sieht. Die Seite selbst antwortet
ihm mit „gibt es nicht"; die Erklärung dazu muss dasselbe sagen.
---------------------------------------------------------------------
WAS HIER BEWUSST NICHT STEHT
Keine Anleitung in Schritten („klicke oben rechts auf …"). Solche
Texte altern mit jedem Umbau der Oberfläche und werden dann zu
Anweisungen, die ins Leere zeigen. Was hier steht, ist der ZWECK —
der ändert sich, wenn die Seite sich ändert, und nicht vorher.
===================================================================== */
import express from "express";
import { sitzungLesen, ROLLEN_NAME, ROLLEN_REIHE } from "./workspace.js";
import { darfSeite, tafelJetzt } from "./rechte.js";
export const erklaerungRouter = express.Router();
/** Der Text zu jeder Seite.
*
* `wofuer` beantwortet „wozu gibt es das?", `tun` beantwortet „was
* mache ich hier?". `merke` ist der eine Satz, der am häufigsten
* missverstanden wird — er steht nur dort, wo es ihn wirklich gibt.
* Ein Feld, das auf jeder Seite gefüllt ist, wird nicht mehr gelesen.
*/
export const ERKLAERUNGEN = {
"start.html": {
wofuer: "Deine Startseite. Jede Kachel führt zu einem Bereich, und du siehst nur die, die dir offenstehen.",
tun: "Aussuchen, wo du hinwillst – oder oben auf die Glocke schauen, wenn etwas auf dich wartet.",
},
"uebersicht.html": {
wofuer: "Alle betreuten Creator nebeneinander, mit Zahlen, offenen Aufgaben und dem Datum des letzten Kontakts.",
tun: "Die oberste Karte zuerst ansehen – sortiert wird nach dem, was Handlung verlangt, nicht nach Namen.",
},
"aufgaben.html": {
wofuer: "Alle Aufgaben des Teams in vier Spalten, mit Frist, Zuständigkeit und Rückmeldungen.",
tun: "Eine Aufgabe weiterschieben, sobald sich ihr Stand ändert – nicht sammeln und später nachtragen.",
merke: "Was hier nicht steht, passiert nicht. Aufgaben aus einem Call landen automatisch hier.",
},
"kalender.html": {
wofuer: "Alle Termine des Teams an einer Stelle, mit Serien und Feiertagen.",
tun: "Termin anlegen und unten auswählen, wer ihn im eigenen Kalender sehen soll.",
merke: "Wen du nicht auswählst, sieht den Termin nicht – auch nicht, dass es ihn gibt.",
},
"chat.html": {
wofuer: "Nachrichten an einzelne Menschen oder an einen Kanal.",
tun: "Schreiben. Auf eine Nachricht kannst du auch nur reagieren, statt zu antworten.",
},
"calls.html": {
wofuer: "Alle Gespräche mit Datum, Teilnehmern und Protokoll.",
tun: "Nach dem Call das Protokoll schreiben; die To-dos daraus landen direkt im Aufgabenbrett.",
merke: "Ein Call ohne Protokoll bleibt auf der Startseite stehen, bis eines da ist.",
},
"dateien.html": {
wofuer: "Alle Dateien zu einem Creator, jede mit Stand und Versionsverlauf.",
tun: "Hochladen und den Stand setzen – die aktuelle Fassung ist dadurch immer erkennbar.",
},
"content.html": {
wofuer: "Alle Videoideen mit Säule, Hook, Format und geplantem Datum.",
tun: "Eine Idee eintragen und ihr eine Säule geben; die Strecke danach ist immer dieselbe.",
},
"bereich.html": {
wofuer: "Die Einträge dieses Bretts, je nach Brett mit Art, Datum, Dringlichkeit oder Bewertung.",
tun: "Eintrag anlegen, Art wählen, und bei „Gilt für“ entscheiden, ob er dir gehört oder allen.",
},
"wissen.html": {
wofuer: "Anleitungen, PDFs und Kurzfassungen – durchsuchbar, nach Themen sortiert.",
tun: "Nachschlagen, bevor du fragst – und selbst etwas dazulegen, wenn du es erklärt hast.",
},
"report.html": {
wofuer: "Je Creator und Zeitraum: was lief, was nicht, was als Nächstes kommt.",
tun: "Den Zeitraum durchgehen und drei Dinge festhalten: was lief, was nicht, was als Nächstes kommt.",
},
"leistung.html": {
wofuer: "Livestunden, Zuschauer und Einnahmen je Tag – aus Backstage oder von Hand.",
tun: "Zeitraum importieren oder einen Tag von Hand eintragen, dann mit den Wochenzielen vergleichen.",
},
"scouting.html": {
wofuer: "Alle Kontakte mit Stufe, Kanal, Reichweite und dem, was zuletzt passiert ist.",
tun: "Jeden Kontakt eine Stufe weiterschieben – oder bewusst beenden, statt ihn liegen zu lassen.",
},
"startcheck.html": {
wofuer: "Ein Fragebogen je neuem Creator und die Arbeitspakete, die daraus entstehen.",
tun: "Die Fragen durchgehen; daraus entstehen automatisch die ersten Arbeitspakete.",
},
"profil.html": {
wofuer: "Zahlen, Aufgaben, Dateien, Termine und Verlauf zu einer Creatorin an einer Stelle.",
tun: "Nachsehen, bevor du mit ihr oder ihm sprichst.",
},
"steckbrief.html": {
wofuer: "Dein Bild, ein paar Worte über dich und deine Kanäle.",
tun: "Ausfüllen. Dein Bild steht danach überall dort, wo dein Name auftaucht.",
merke: "Das hier gehört dir. Niemand außer dir ändert daran etwas.",
},
"personen.html": {
wofuer: "Zugänge: wer hereinkommt, mit welcher Rolle, und wer wen betreut.",
tun: "Zugang anlegen und den Code persönlich weitergeben.",
merke: "Ein Zugangscode wird genau einmal angezeigt. Danach gibt es nur einen neuen, keinen alten.",
},
"automation.html": {
wofuer: "Jede Automatik des Hauses mit Zustand, letzter Ausführung und Schalter.",
tun: "Nachsehen, was gerade greift, bevor du dich über etwas wunderst, das du nicht angestoßen hast.",
},
"team.html": {
wofuer: "Die Arbeitslast von Managern und Scouts nebeneinander.",
tun: "Stellen suchen, an denen jemand zu viel hat – und dort umverteilen.",
merke: "Das ist keine Kontrolle. Die Seite gibt es, um fehlende Unterstützung zu finden.",
},
"teamlage.html": {
wofuer: "Was in deinem Team gerade offen ist – und bei wem.",
tun: "Die offenen Punkte durchgehen und ansprechen.",
merke: "„Offen“ heißt: darüber habt ihr noch nicht geredet. Es ist keine Note über jemanden.",
},
"entwicklung.html": {
wofuer: "34 Beobachtungen je Person, gesetzt von zwei Augenpaaren unabhängig voneinander.",
tun: "Pro Person die Punkte setzen, die du wirklich beobachtet hast. Den Rest lässt du offen.",
merke: "Keine Noten, keine Punktzahl. Das Ergebnis ist die Abweichung zwischen euch beiden – ein Gesprächsanlass.",
},
"talente.html": {
wofuer: "Kandidaten für dein Mod-Team in fünf Stufen – mit 21 Merkmalen und 6 Warnzeichen je Karte.",
tun: "Pro Karte den einen nächsten Schritt machen, der dort steht.",
merke: "Hier stehen Namen von Menschen, die nichts davon wissen. Nichts davon geht nach außen.",
},
"rechte.html": {
wofuer: "Jede Rolle mal jede Seite als Tafel – und jedes Feld lässt sich umstellen.",
tun: "Ein Feld umstellen und speichern. Die Änderung gilt sofort, auch für alle, die gerade angemeldet sind.",
merke: "Drei Felder lassen sich nicht abschalten – sonst könntest du dich selbst aussperren.",
},
"treff-regeln.html": {
wofuer: "Die Regeln des Treffs und was passiert, wenn sie jemand nicht einhält.",
tun: "Einmal lesen. Was hier steht, gilt auch – und du siehst, was passiert, wenn es jemand nicht einhält.",
},
"treff-moderation.html": {
wofuer: "Offene Meldungen, erledigte Fälle und jede Maßnahme mit Begründung.",
tun: "Eine Meldung ansehen und entscheiden: Hinweis, Pause oder Ausschluss – immer mit Begründung.",
merke: "Jede Maßnahme steht nachher mit Grund da. Das schützt auch dich.",
},
};
/** Die Rollen, die diese Seite gerade öffnen dürfen — als Namen.
*
* AUS DER TAFEL GERECHNET, NICHT DANEBENGESCHRIEBEN. Wer in „Wer
* sieht was" ein Feld umstellt, ändert damit auch diesen Satz; eine
* zweite Liste hier wäre spätestens dann eine Behauptung.
*
* In der Reihenfolge des Hauses (ROLLEN_REIHE), damit die rechte Hand
* auch hier direkt hinter DogFather steht. */
function sichtbarFuer(pfad) {
const erlaubt = tafelJetzt()[pfad] || [];
const bekannt = ROLLEN_REIHE.filter((r) => erlaubt.includes(r));
/* Rollen, die (noch) nicht in der Rangfolge stehen -- heute nur
'gast'. Sie faellt ans Ende, statt stillschweigend zu fehlen. */
const rest = erlaubt.filter((r) => !bekannt.includes(r));
return [...bekannt, ...rest].map((r) => ROLLEN_NAME[r] || r);
}
erklaerungRouter.get("/workspace/api/erklaerung", (req, res) => {
try {
const person = sitzungLesen(req);
if (!person) return res.status(401).json({ fehler: "nicht_angemeldet" });
/* Nur der Dateiname, und nur aus dem eigenen Verzeichnis. Ohne das
waere `?seite=../../etwas` eine Frage, die dieser Weg gar nicht
beantworten koennen soll. */
const datei = String(req.query?.seite || "").trim();
if (!/^[a-z0-9-]+\.html$/.test(datei)) {
return res.status(400).json({ fehler: "ungueltig" });
}
const pfad = "/workspace/" + datei;
/* DIESELBE SCHRANKE WIE FUER DIE SEITE SELBST -- und dieselbe
Antwort, wenn sie zu ist: 404, nicht 403. Wer "kein Zugriff"
liest, weiss, dass es die Seite gibt. */
if (!darfSeite(person, pfad)) {
return res.status(404).json({ fehler: "nicht_gefunden" });
}
const text = ERKLAERUNGEN[datei];
/* Eine Seite ohne Text ist KEIN Fehler, aber auch keine leere
Erklaerung: Der Browser bekommt `hat_text: false` und zeichnet
gar nichts. Ein Kasten mit drei leeren Zeilen waere schlechter
als keiner. */
if (!text) return res.json({ hat_text: false, seite: datei });
res.json({
hat_text: true,
seite: datei,
wofuer: text.wofuer,
tun: text.tun,
merke: text.merke || null,
sichtbar: sichtbarFuer(pfad),
});
} catch (fehler) {
console.error("[erklaerung]", fehler?.message);
res.status(503).json({ fehler: "nicht_verfuegbar" });
}
});
+4 -4
View File
@@ -13,25 +13,25 @@
"theme_color": "#06090f",
"icons": [
{
"src": "/assets/img/app-symbole/workspace-192.png?v=202609141634",
"src": "/assets/img/app-symbole/workspace-192.png?v=202609141819",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/workspace-512.png?v=202609141634",
"src": "/assets/img/app-symbole/workspace-512.png?v=202609141819",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609141634",
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609141819",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609141634",
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609141819",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
+56
View File
@@ -7878,3 +7878,59 @@ body.start .k-leiste .feldschild::after {
word-break: break-all;
}
.code-kasten__hinweis { margin: 0 0 14px; font-size: .85rem; color: var(--text-leise); }
/* =====================================================================
DIE KURZE ERKLAERUNG AUF JEDER SEITE (14.09.2026)
Drei Zeilen, Schild links, Satz rechts. Sie soll gelesen werden
koennen und danach nicht mehr auffallen -- deshalb kleine Schrift,
gedaempfte Farbe und keine eigene Flaeche, die mit den Karten
darunter um Aufmerksamkeit kaempft. Nur eine Kante links.
===================================================================== */
.erkl {
margin: 0 0 22px;
padding: 13px 17px 13px 15px;
/* DECKEND, und das ist keine Kosmetik: Auf mehreren Seiten liegt
hinter dem Inhalt die Buehne -- ein Foto. Text darauf hat keinen
berechenbaren Kontrast, und „gut lesbar" waere dann eine
Vermutung statt einer Messung. */
background: color-mix(in srgb, var(--tinte) 94%, #ffffff 6%);
border: 1px solid var(--rand);
border-left: 3px solid color-mix(in srgb, var(--akzent) 55%, transparent);
display: grid;
gap: 5px;
}
.erkl__zeile {
display: grid;
grid-template-columns: 5.5rem 1fr;
gap: 10px;
align-items: baseline;
}
/* .75rem = 12 px. Die erste Fassung stand auf .68rem = 10,88 px und
lag damit unter der Hausgrenze von 11,5 px -- gefunden von
pruef-css-klassen, nicht vom Auge. */
.erkl__schild {
font-size: .75rem; font-weight: 700;
letter-spacing: .08em; text-transform: uppercase;
color: var(--text-still);
}
.erkl__satz {
font-size: .84rem; line-height: 1.6;
max-width: 78ch;
color: var(--text-leise);
}
/* „Merke" ist die Zeile, die jemand einmal falsch verstanden hat.
Sie darf etwas deutlicher sein als die anderen -- aber nicht
alarmierend, sonst liest man die drei darueber nicht mehr. */
.erkl__zeile[data-merke="ja"] .erkl__satz { color: var(--text); }
.erkl__zeile[data-merke="ja"] .erkl__schild {
color: color-mix(in srgb, var(--akzent) 70%, var(--text-still));
}
/* Am Handy untereinander: 5,5rem Schild plus ein Satz gehen bei 390 px
nicht nebeneinander, ohne dass jedes zweite Wort umbricht. */
@media (max-width: 560px) {
.erkl__zeile { grid-template-columns: 1fr; gap: 1px; }
.erkl__satz { font-size: .83rem; }
}
+86
View File
@@ -0,0 +1,86 @@
/* =====================================================================
Die kurze Erklärung auf jeder Seite (14.09.2026)
Filipe: „ich will in jeder seite auch eine kleine detaillierte aber
schnelle erklärung kurz und knapps noch zu jeder seite."
---------------------------------------------------------------------
WARUM SIE OFFEN DASTEHT UND NICHT HINTER EINEM KLICK
„Schnell" war seine Bedingung. Eine Erklärung, die man erst
aufklappen muss, ist genau dann nicht da, wenn man sie braucht —
nämlich beim ersten Mal, wenn man noch nicht weiß, dass es sie gibt.
Drei kurze Zeilen kosten weniger Platz als ein Aufklapper kostet:
Aufmerksamkeit.
---------------------------------------------------------------------
WO SIE HINGEHÄNGT WIRD
Nach der Kopfzeile, wenn es eine gibt — sonst als erstes Element im
Inhalt. Fünf Seiten haben keine `.kopf-zeile` (Chat, Kalender,
Start, Team, Teamlage); ohne den zweiten Fall hätten ausgerechnet
die am häufigsten benutzten Seiten keine Erklärung bekommen, und
zwar lautlos.
---------------------------------------------------------------------
SIE BAUT NICHTS UM, WENN NICHTS DA IST
Kein Text zur Seite, keine Antwort, nicht angemeldet: dann entsteht
auch kein Kasten. Ein leerer Rahmen mit drei Überschriften wäre
schlechter als gar keiner — er sieht aus wie ein Fehler.
===================================================================== */
(() => {
const datei = (location.pathname.split('/').pop() || '').toLowerCase();
if (!/^[a-z0-9-]+\.html$/.test(datei)) return; // Anmeldeseiten u. ä.
const el = (t, k, text) => {
const n = document.createElement(t);
if (k) n.className = k;
if (text !== undefined) n.textContent = text;
return n;
};
/** Eine Zeile: Schild links, Satz rechts. */
function zeile(schild, satz) {
const z = el('div', 'erkl__zeile');
z.append(el('span', 'erkl__schild', schild));
z.append(el('span', 'erkl__satz', satz));
return z;
}
function zeichne(d) {
const kasten = el('section', 'erkl');
/* Ein Bereich mit Namen: Ein Vorleseprogramm sagt dadurch an, was
das hier ist, statt drei Wortpaare vorzulesen. */
kasten.setAttribute('aria-label', 'Kurze Erklärung zu dieser Seite');
kasten.append(zeile('Wofür', d.wofuer));
kasten.append(zeile('Du tust', d.tun));
if (d.merke) {
const z = zeile('Merke', d.merke);
z.dataset.merke = 'ja';
kasten.append(z);
}
if (Array.isArray(d.sichtbar) && d.sichtbar.length) {
/* DIESE ZEILE IST GERECHNET, NICHT GESCHRIEBEN -- sie kommt aus
derselben Rechtetafel wie die Schranke selbst. Deshalb darf
sie hier so bestimmt dastehen. */
kasten.append(zeile('Sieht', d.sichtbar.join(' · ')));
}
const kopf = document.querySelector('main .kopf-zeile');
if (kopf) { kopf.insertAdjacentElement('afterend', kasten); return; }
const inhalt = document.querySelector('main');
if (inhalt) inhalt.insertBefore(kasten, inhalt.firstElementChild);
}
(async () => {
try {
const a = await fetch('/workspace/api/erklaerung?seite=' + encodeURIComponent(datei),
{ credentials: 'same-origin' });
if (!a.ok) return; // 401/404: dann eben nicht
const d = await a.json();
if (d?.hat_text) zeichne(d);
} catch { /* ohne Erklärung ist die Seite vollständig benutzbar */ }
})();
})();
+13 -12
View File
@@ -12,19 +12,19 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -252,10 +252,11 @@
</form>
</dialog>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/aufgaben.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/aufgaben.js?v=202609141819" defer></script>
</body>
</html>
+14 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/automation.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/automation.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -147,10 +147,11 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/automation.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/automation.js?v=202609141819" defer></script>
</body>
</html>
+18 -17
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -181,14 +181,15 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/checkliste.js?v=202609141634" defer></script>
<script src="assets/js/ampel.js?v=202609141634" defer></script>
<script src="assets/js/schulung.js?v=202609141634" defer></script>
<script src="assets/js/vorlagen.js?v=202609141634" defer></script>
<script src="assets/js/bereich.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/checkliste.js?v=202609141819" defer></script>
<script src="assets/js/ampel.js?v=202609141819" defer></script>
<script src="assets/js/schulung.js?v=202609141819" defer></script>
<script src="assets/js/vorlagen.js?v=202609141819" defer></script>
<script src="assets/js/bereich.js?v=202609141819" defer></script>
</body>
</html>
+15 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/calls.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/calls.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -89,11 +89,12 @@
</main>
<script src="assets/js/ki.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/calls.js?v=202609141634" defer></script>
<script src="assets/js/ki.js?v=202609141819" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/calls.js?v=202609141819" defer></script>
</body>
</html>
+14 -13
View File
@@ -12,26 +12,26 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<!-- aufgaben.css bringt die Dialog- und Formularstile mit (.dialog,
.neu__zeile, .dialog__knoepfe). Sie stehen dort seit dem
Aufgabenbrett; sie hierher zu kopieren hiesse, sie an zwei Stellen
zu pflegen. Dieselbe Lösung nutzen kalender.html und content.html.
Gemeldet von pruef-css-klassen.mjs, bevor jemand einen ungestylten
Dialog zu sehen bekam. -->
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/chat.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/chat.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -341,10 +341,11 @@
</form>
</dialog>
<script src="assets/js/bereiche.js?v=202609141634"></script>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634"></script>
<script src="assets/js/glocke.js?v=202609141634"></script>
<script src="assets/js/chat.js?v=202609141634"></script>
<script src="assets/js/bereiche.js?v=202609141819"></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819"></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819"></script>
<script src="assets/js/chat.js?v=202609141819"></script>
</body>
</html>
+16 -15
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/content.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/content.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -179,12 +179,13 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/checkliste.js?v=202609141634" defer></script>
<script src="assets/js/vorlagen.js?v=202609141634" defer></script>
<script src="assets/js/content.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/checkliste.js?v=202609141819" defer></script>
<script src="assets/js/vorlagen.js?v=202609141819" defer></script>
<script src="assets/js/content.js?v=202609141819" defer></script>
</body>
</html>
+5 -5
View File
@@ -36,15 +36,15 @@
<link rel="preload" as="image" href="assets/img/buehne/crew-gate-hoch-580.webp"
type="image/webp" media="(max-width: 899px)" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<!-- Diese Wand steht NUR auf der Adresse von Team Dogi (ueberall sonst
404, siehe crewWeiche). Sie darf das Haus deshalb direkt nennen
statt ueber den Platzhalter haus.css zu gehen -- und sie MUSS es:
Eine Zugangswand, die sich erst nach dem Umbiegen faerbt, waere
die eine Seite, auf der man das Umfaerben sieht. -->
<link rel="stylesheet" href="assets/css/crew-haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/crew-haus.css?v=202609141819" />
</head>
<body class="gate gate--crew">
@@ -319,6 +319,6 @@
</main>
</div>
<script src="assets/js/gate.js?v=202609141634" defer></script>
<script src="assets/js/gate.js?v=202609141819" defer></script>
</body>
</html>
+4 -4
View File
@@ -13,25 +13,25 @@
"theme_color": "#06090f",
"icons": [
{
"src": "/assets/img/app-symbole/crew-192.png?v=202609141634",
"src": "/assets/img/app-symbole/crew-192.png?v=202609141819",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/crew-512.png?v=202609141634",
"src": "/assets/img/app-symbole/crew-512.png?v=202609141819",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609141634",
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609141819",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609141634",
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609141819",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
+14 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/dateien.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/dateien.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -108,10 +108,11 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/dateien.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/dateien.js?v=202609141819" defer></script>
</body>
</html>
+13 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -94,9 +94,10 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/entwicklung.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/entwicklung.js?v=202609141819" defer></script>
</body>
</html>
+4 -4
View File
@@ -30,9 +30,9 @@
<link rel="preload" as="image" href="assets/img/buehne/gate-hoch-580.webp"
type="image/webp" media="(max-width: 899px)" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
</head>
<body class="gate">
@@ -401,6 +401,6 @@
</main>
</div>
<script src="assets/js/gate.js?v=202609141634" defer></script>
<script src="assets/js/gate.js?v=202609141819" defer></script>
</body>
</html>
+15 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/kalender.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/kalender.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -377,11 +377,12 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/kalender.js?v=202609141634" defer></script>
<script src="assets/js/kalender-abo.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/kalender.js?v=202609141819" defer></script>
<script src="assets/js/kalender-abo.js?v=202609141819" defer></script>
</body>
</html>
+14 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/leistung.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/leistung.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -412,10 +412,11 @@
</form>
</dialog>
<script src="assets/js/wahl.js?v=202609141634"></script>
<script src="assets/js/bereiche.js?v=202609141634"></script>
<script src="assets/js/kopf.js?v=202609141634"></script>
<script src="assets/js/glocke.js?v=202609141634"></script>
<script src="assets/js/leistung.js?v=202609141634"></script>
<script src="assets/js/wahl.js?v=202609141819"></script>
<script src="assets/js/bereiche.js?v=202609141819"></script>
<script src="assets/js/kopf.js?v=202609141819"></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819"></script>
<script src="assets/js/leistung.js?v=202609141819"></script>
</body>
</html>
+14 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/personen.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/personen.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -423,10 +423,11 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/personen.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/personen.js?v=202609141819" defer></script>
</body>
</html>
+15 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -214,11 +214,12 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/steckbrief.js?v=202609141634" defer></script>
<script src="assets/js/profil.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/steckbrief.js?v=202609141819" defer></script>
<script src="assets/js/profil.js?v=202609141819" defer></script>
</body>
</html>
+13 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -134,9 +134,10 @@
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
die seit dem 07.09. jede Seite danach absucht. -->
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/rechte.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/rechte.js?v=202609141819" defer></script>
</body>
</html>
+15 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/report.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/report.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -106,11 +106,12 @@
</main>
<script src="assets/js/ki.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/report.js?v=202609141634" defer></script>
<script src="assets/js/ki.js?v=202609141819" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/report.js?v=202609141819" defer></script>
</body>
</html>
+14 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/scouting.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/scouting.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -173,10 +173,11 @@
</div>
</div>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/scouting.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/scouting.js?v=202609141819" defer></script>
</body>
</html>
+13 -12
View File
@@ -12,21 +12,21 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<!-- Nur die Startseite: Begrüßungskachel, Uhr, Glockenmulde. Siehe
den Hinweis in start.css -- dort stand es bis zum 07.09.2026. -->
<link rel="stylesheet" href="assets/css/heim.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/heim.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -674,10 +674,11 @@
</p>
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/start.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/start.js?v=202609141819" defer></script>
</body>
</html>
+15 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -85,11 +85,12 @@
</main>
<script src="assets/js/ki.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/startcheck.js?v=202609141634" defer></script>
<script src="assets/js/ki.js?v=202609141819" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/startcheck.js?v=202609141819" defer></script>
</body>
</html>
+14 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -126,10 +126,11 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/steckbrief.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/steckbrief.js?v=202609141819" defer></script>
</body>
</html>
+13 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -94,9 +94,10 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/talente.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/talente.js?v=202609141819" defer></script>
</body>
</html>
+14 -13
View File
@@ -7,20 +7,20 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/team.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/team.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -110,10 +110,11 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/team.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/team.js?v=202609141819" defer></script>
</body>
</html>
+13 -12
View File
@@ -7,20 +7,20 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/team.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/team.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<!-- `data-buehne` steht hier fest und nicht im Skript: Die Kachel zu
@@ -84,9 +84,10 @@
Kaputt ist dabei nichts -- er funktioniert. Genau deshalb faellt
es niemandem auf, und deshalb prueft pruef-css-klassen die
ABHAENGIGKEIT statt der Optik. Hier hat sie angeschlagen. -->
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/teamlage.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/teamlage.js?v=202609141819" defer></script>
</body>
</html>
+13 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -110,9 +110,10 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/treff-moderation.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/treff-moderation.js?v=202609141819" defer></script>
</body>
</html>
+13 -12
View File
@@ -7,18 +7,18 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein. Auf der Adresse des
Treffs biegt der Server genau diesen Dateinamen auf crew-haus.css
um, und die Seite kommt schon beim ERSTEN Abruf in Lila und
Babyblau an -- ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -190,9 +190,10 @@
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
die seit dem 07.09. jede Seite danach absucht. -->
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/treff-regeln.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/treff-regeln.js?v=202609141819" defer></script>
</body>
</html>
+14 -13
View File
@@ -12,22 +12,22 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<!-- Formular- und Dialogstile: seit dem 07.09.2026 steht hier der
Dialog "Creator anlegen". -->
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -149,11 +149,12 @@
</main>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/uebersicht.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/uebersicht.js?v=202609141819" defer></script>
</body>
</html>
+14 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141634" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141634" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/wissen.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141634" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609141819" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609141819" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/start.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/wissen.css?v=202609141819" />
<link rel="stylesheet" href="assets/css/module.css?v=202609141819" />
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
genau diesen Dateinamen auf crew-haus.css um, und die Seite
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609141634" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609141819" />
</head>
<body class="start">
@@ -190,10 +190,11 @@
</main>
<script src="assets/js/wahl.js?v=202609141634" defer></script>
<script src="assets/js/bereiche.js?v=202609141634" defer></script>
<script src="assets/js/kopf.js?v=202609141634" defer></script>
<script src="assets/js/glocke.js?v=202609141634" defer></script>
<script src="assets/js/wissen.js?v=202609141634" defer></script>
<script src="assets/js/wahl.js?v=202609141819" defer></script>
<script src="assets/js/bereiche.js?v=202609141819" defer></script>
<script src="assets/js/kopf.js?v=202609141819" defer></script>
<script src="assets/js/erklaerung.js?v=202609141819" defer></script>
<script src="assets/js/glocke.js?v=202609141819" defer></script>
<script src="assets/js/wissen.js?v=202609141819" defer></script>
</body>
</html>