Vier Stufen im Agenturhaus -- und die Modi-Liste verschwindet von dort

Filipe, mit dem Bildschirmfoto der LIVE-Punkte: "diese aufgaben auf
screen. alle auf dieser app getrennt von denen auf der team dogi
website bitte, sehr wichtig. die sollen die manager und scouts bewerten
können mit passt passt nicht verbesserung möglich und was weiß ich. und
die creator sollen sehen was bei ihnen passt oder nicht mit der notiz
vom manager oder scout. spicy und dogfather sollen auch bewerten können
wie vorher. ... und wie gesagt von der team dogi seite da ist ein
anderes system auf diesen aufgaben."

WAS AUF DEM BILDSCHIRMFOTO STAND, WAR NICHT SEINE SEITE
Unter "Vor der Sendung" stand die Liste eines MODIS -- erkennbar am
Satz darueber ("Was du vor und beim Start gesehen hast") und an den
Punkten ("Die Ankuendigung kam rechtzeitig"). Am echten Bestand
nachgemessen: Die Auswahl "Person" fuellte sich aus allen Creatorn PLUS
allen Modis, sortiert nach Namen. Der erste Name im Haus ist "Diene",
eine Modi -- und ohne ausdrueckliche Wahl nimmt die Seite den ersten.
DogFather bekam auf der Agenturadresse also zuverlaessig das Teamhaus
zu sehen, und druecken konnte er dort nichts, weil ein Modi-Bericht nur
dem Modi selbst gehoert.

DIE GRENZE, AN DREI STELLEN STATT AN EINER
  * Die Auswahl geht durch EIN Sieb (hat diese Person ueberhaupt eine
    Liste, und steht sie in diesem Haus?) statt durch drei einzeln
    gepflegte Bedingungen.
  * Die Grenze haelt auch gegen eine von Hand eingetragene Nummer --
    eine ausgeduennte Auswahlliste ist Kosmetik, solange ?creator_id=
    durchgeht.
  * Die gueltigen Punkt-Schluessel lagen fuer beide Haeuser in EINER
    Menge. Ein Scout konnte damit bei einem Creator den Stand eines
    Modi-Punktes setzen: angenommen, gespeichert, nie zu sehen.
  * Dazu: `darfCreator` sagt fuer DogFather bei JEDER Nummer ja -- er
    konnte einen Stand an einer Managerin oder an sich selbst setzen.
Drei Lagen wie bei den Aufgaben: crew / agentur / keine Adresse. Der
dritte Ausgang ist kein Schlupfloch, sondern die Bedingung dafuer, dass
die Pruefungen ueberhaupt noch etwas messen koennen.

ZWEI SKALEN, WEIL ES ZWEI VERSCHIEDENE DINGE SIND
Agentur (Betreuung urteilt, Creator liest): Passt / Verbesserung
moeglich / Passt nicht / Trifft nicht zu. Team (Modi berichtet,
DogFather behandelt im Eingang): Passt so / Verbessern, unveraendert --
eine Stufe "Passt nicht" haette dort keinen Empfaenger.
"Trifft nicht zu" ist kein Beiwerk: Ohne sie steht ein Punkt, der bei
diesem Creator gar nicht vorkommt, fuer immer auf "offen" und die
Bilanz zaehlt ihn als unerledigt mit.
Die Worte, die Toene und die Frage im Nachfragefenster kommen vom
Server. Der Browser baut Knoepfe, Marken und Kacheln daraus und kennt
keine Stufe beim Namen -- sonst muesste er ausserdem wissen, WANN
welche gilt, und das waere ein Rollenvergleich in einer Datei, die
jeder herunterladen kann.

DIE NOTIZ TRAEGT JETZT AUCH DIE ROLLE
"mit der notiz vom manager oder scout" -- bis hierher stand am Satz nur
ein Vorname. Wer die Namen im ersten Monat nicht kennt, weiss nicht,
wer da urteilt. Jetzt: "Patrick, Scout · 24.09., 23:43".

DIE UMSTELLUNG DER DATENBANK KOMMT NICHT VON MIR
Eine CHECK-Regel laesst sich in SQLite nicht aendern; die Tabelle muss
neu gebaut werden. Ich hatte den Griff hier zuerst ein zweites Mal
geschrieben -- mit Zeilenzaehlung und PRAGMA-Spaltenliste, aber OHNE
die Sicherung davor, ohne die Indizes und ohne `foreign_key_check`
danach. Drei von fuenf Absicherungen fehlten, und keine davon haette
gefehlt, wenn ich die vorhandene Funktion benutzt haette. Genau davor
warnt ihr eigener Kommentar seit dem 09.09.2026.
Jetzt: `checkListeErweitern` aus workspace.js, ausgegeben statt
nachgebaut. Der Marker ist die erste fehlende Stufe und keine
hingeschriebene -- eine feste Angabe waere an dem Tag falsch, an dem
eine weitere dazukommt.
Und danach wird NACHGESEHEN, was wirklich erlaubt ist: Bricht die
Umstellung ab, werden die neuen Stufen auch nicht angeboten. Ein Knopf,
der beim Druecken scheitert, ist schlechter als kein Knopf.

WAS SONST NOCH NACHGEZOGEN WURDE
  * Der Zaehler auf der Creator-Startseite zaehlte fest
    `stufe = 'verbessern'`. Die staerkste Rueckmeldung, die es gibt,
    waere als Einzige nicht dort erschienen. Jetzt aus dem Katalog.
  * Der Satz unter "Feste Punkte" stand im Browser und sprach in BEIDEN
    Haeusern vom "Creator". Die Teamfassung bleibt wortgleich -- ab dem
    24.09. wird jeder Umbau je Haus getrennt gefuehrt, und dies ist der
    des Agenturhauses.
  * "Passt" setzt weiterhin mit einem Klick. Ein Nachfragefenster vor
    dem haeufigsten Klick einer Betreuung, die vierzig Punkte durchgeht,
    macht aus einem Durchgang eine Sitzung.

GEMESSEN
  * pruef-checkliste-stufen.mjs, neu: 56 Pruefungen, 0 Fehler. Darin
    die Umstellung an einer Datenbank mit dem ALTEN Bauplan und echten
    Zeilen -- Zeilen, Spalten UND Spalteninhalte nachgezaehlt, plus die
    Sicherung. Zu jeder Schranke die Gegenprobe, die durchkommen muss.
  * pruef-checkliste 97, pruef-modi-checkliste 75, pruef-haus-trennung
    97, pruef-manager-sicht 43 -- alle unveraendert gruen.
  * pruef-checkliste rechnete mit festen Zahlen (drei Bilanzkacheln,
    zwei Knoepfe je Punkt) und war rot, ohne dass etwas kaputt war. Sie
    fragt die Zahlen jetzt bei der Schnittstelle ab und zaehlt sie im
    Browser nach. Gleich viele Pruefstellen, 57.
  * Bildschirmfotos bei 1280 px und 390 px (Betreuung, Creator, das
    Nachfragefenster): vier Knoepfe passen auf dem Handy als 2x2, 0 px
    Ueberhang, keine Konsolenfehler.
  * Die neuen Toene sind gerechnet, nicht gegriffen: #d97f87 hat die
    relative Helligkeit 0,317 -- so hell wie das vorhandene Gruen
    (0,320) und heller als das Blaugrau von "offen" (0,241), das den
    Barrierefreiheits-Lauf schon bestanden hat. Kein Signalrot: Ein
    gedaempftes Rosé sagt "das gehoert geaendert", ein Rot sagt "du
    hast versagt".

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-24 23:49:01 +02:00
co-authored by Claude Opus 5
parent 9863645952
commit e1ee778c04
49 changed files with 2012 additions and 740 deletions
+142
View File
@@ -0,0 +1,142 @@
/* Bild der vier Urteilsstufen (24.09.2026)
Gebaut wurde heute die zweite Skala fuer das Agenturhaus: Passt,
Verbesserung moeglich, Passt nicht, Trifft nicht zu. Die Zahlen
stimmen (pruef-checkliste-stufen: 48 Pruefungen), aber eine Zahl
sagt nicht, ob vier Knoepfe auf einem Handy noch nebeneinander
passen und ob das neue Rosé neben dem Gelb noch ruhig wirkt.
Zwei Breiten, zwei Rollen: die Betreuung (Scout, mit Knoepfen) und
der Creator (ohne, dafuer mit Notiz).
Aufrufen mit: node server/bild-checkliste-stufen.mjs
*/
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
const ordner = mkdtempSync(join(tmpdir(), "ws-bild-st-"));
process.env.WORKSPACE_DB = join(ordner, "workspace.db");
const { portMussFreiSein } = await import("./helfer-port.mjs");
await portMussFreiSein(4333, "das Bildwerkzeug fuer die Stufen");
process.env.PORT = "4333";
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 }); };
await import("./index.js");
await new Promise((r) => setTimeout(r, 1200));
const BASIS = "http://127.0.0.1:4333";
const { DatabaseSync } = await import("node:sqlite");
const { scryptSync, randomBytes } = await import("node:crypto");
for (let i = 0; i < 60; i++) {
try {
const p = new DatabaseSync(process.env.WORKSPACE_DB);
try { p.prepare("SELECT 1 FROM personen LIMIT 1").get(); break; } finally { p.close(); }
} catch { await new Promise((r) => setTimeout(r, 250)); }
}
const d = new DatabaseSync(process.env.WORKSPACE_DB);
const j = new Date().toISOString();
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,aktiv,erstellt) VALUES (?,?,?,?,?,1,?)")
.run(name, rolle, hash, salt, 32768, j);
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
}
anlegen("Filipe", "admin", "CODE-DOGI-0001");
const idScout = anlegen("Patrick", "scout", "CODE-SCOU-0001");
const idCrea = anlegen("Luna", "creator", "CODE-CREA-0001");
d.prepare("INSERT INTO betreuung (creator_id, betreuer_id, seit) VALUES (?,?,?)")
.run(idCrea, idScout, j);
d.close();
const anmelden = async (rolle, code) => {
const a = await fetch(BASIS + "/workspace/api/anmelden", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ rolle, code }) });
return (a.headers.getSetCookie?.() || []).map((k) => k.split(";")[0]).join("; ");
};
const kScout = await anmelden("scout", "CODE-SCOU-0001");
/* Jede der vier Stufen einmal setzen -- sonst zeigt das Bild vier
graue Knoepfe und beantwortet keine der beiden Fragen. */
for (const [schluessel, stufe, grund] of [
["ton-geprueft", "gut", ""],
["licht-sitzt", "verbessern", "Das Gesicht liegt im Schatten, der Rest ist hell. Lampe eine Handbreit höher."],
["titel-und-thema-stehen", "passt_nicht", "Der Titel sagt nichts über das Thema. Bitte vor dem nächsten Mal ändern."],
["moderation-geklaert", "entfaellt", "Du sendest bisher ohne Gäste – der Punkt kommt bei dir nicht vor."],
]) {
const a = await fetch(`${BASIS}/workspace/api/checkliste/live/${schluessel}`, {
method: "PUT", headers: { "Content-Type": "application/json", Cookie: kScout },
body: JSON.stringify({ stufe, begruendung: grund, creator_id: idCrea }) });
if (!a.ok) console.log(" konnte nicht setzen:", schluessel, a.status, await a.text());
}
const pw = await import("file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs");
const browser = await pw.chromium.launch();
for (const [wer, rolle, code, breite, datei] of [
["Scout", "scout", "CODE-SCOU-0001", 1280, "bild-stufen-betreuung.png"],
["Creator", "creator", "CODE-CREA-0001", 1280, "bild-stufen-creator.png"],
["Scout", "scout", "CODE-SCOU-0001", 390, "bild-stufen-handy.png"],
]) {
const ctx = await browser.newContext({
viewport: { width: breite, height: breite < 500 ? 900 : 1000 }, deviceScaleFactor: 2 });
const seite = await ctx.newPage();
const laut = [];
seite.on("console", (m) => { if (m.type() === "error") laut.push(m.text()); });
seite.on("pageerror", (f) => laut.push(String(f)));
await seite.goto(BASIS + "/workspace/", { waitUntil: "domcontentloaded" });
await seite.click(`.rolle[data-rolle="${rolle}"]`);
await seite.fill("#code", code);
await seite.click("button[type=submit]");
await seite.waitForURL("**/start.html", { timeout: 15000 });
await seite.goto(BASIS + "/workspace/bereich.html?b=live", { waitUntil: "networkidle" });
await seite.waitForTimeout(1200);
/* Die erste Gruppe aufklappen -- zugeklappt sieht man nichts von dem,
was hier zu beurteilen ist. */
await seite.evaluate(() => {
const k = document.querySelector(".fest-gruppe__kopf");
if (k && k.getAttribute("aria-expanded") !== "true") k.click();
});
await seite.waitForTimeout(500);
/* NUR DIE ERSTEN VIER KARTEN. Eine Aufnahme ueber 200 Punkte wird
so lang, dass man beim Ansehen jedes Detail wegskaliert -- und
genau die Details sind die Frage: Passen vier Knoepfe nebeneinander,
ist das Rosé ruhig genug, steht die Notiz lesbar da. */
await seite.evaluate(() => {
const k = [...document.querySelectorAll(".fest-punkt")];
for (let i = 4; i < k.length; i++) k[i].remove();
for (const g of [...document.querySelectorAll(".fest-gruppe")].slice(1)) g.remove();
});
await seite.waitForTimeout(200);
const block = await seite.$(".liste-fest");
await (block || seite).screenshot({ path: datei });
/* Und das Nachfragefenster einmal offen -- dort steht die Frage,
die der Katalog zu dieser Stufe mitbringt. */
if (datei === "bild-stufen-betreuung.png") {
await seite.evaluate(() => {
const b = [...document.querySelectorAll('.stufe-knopf[data-stufe="passt_nicht"]')][1];
if (b) b.click();
});
await seite.waitForTimeout(700);
await seite.screenshot({ path: "bild-stufen-nachfrage.png" });
}
const zahlen = await seite.evaluate(() => ({
knoepfe: document.querySelectorAll(".fest-punkt:not([hidden]) .stufe-knopf").length,
bilanz: [...document.querySelectorAll(".bilanz-zahl")]
.map((z) => `${z.querySelector(".bilanz-zahl__n")?.textContent} ${z.querySelector(".bilanz-zahl__text")?.textContent}`),
ueber: document.documentElement.scrollWidth - document.documentElement.clientWidth,
}));
console.log(` ${datei} (${wer}, ${breite}px): ${zahlen.knoepfe} Knöpfe, `
+ `Bilanz [${zahlen.bilanz.join(" | ")}], ${zahlen.ueber}px über`
+ (laut.length ? ` KONSOLE: ${laut.join(" | ")}` : ""));
await ctx.close();
}
await browser.close();
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ }
process.exit(0);
+520
View File
@@ -0,0 +1,520 @@
/* =====================================================================
pruef-checkliste-stufen.mjs — die zwei Urteilsskalen und die Grenze
zwischen den Häusern (24.09.2026)
Filipe, mit einem Bildschirmfoto der LIVE-Punkte:
*"diese aufgaben auf screen. alle auf dieser app getrennt von denen
auf der team dogi website bitte, sehr wichtig. die sollen die manager
und scouts bewerten können mit passt passt nicht verbesserung möglich
und was weiß ich. und die creator sollen sehen was bei ihnen passt
oder nicht mit der notiz vom manager oder scout. ... und wie gesagt
von der team dogi seite da ist ein anderes system auf diesen
aufgaben."*
WAS ER GESEHEN HATTE, UND WARUM ES KEINE ANSICHTSSACHE WAR.
Auf workspace.dogfather-universe.com stand unter "Vor der Sendung"
die Liste eines MODIS. Nachgemessen am echten Bestand: Die Auswahl
füllte sich aus allen Creatorn PLUS allen Modis, sortiert nach Namen,
und ohne ausdrückliche Wahl nimmt die Seite den ersten. Der erste
Name im Haus ist "Diene" -- eine Modi. Bewerten ließ sich dort
nichts, weil ein Modi-Bericht nur dem Modi selbst gehört.
DIESE PRÜFUNG MISST VIER DINGE, und jedes einzeln:
1. DIE GRENZE. Auf der Agenturadresse steht kein Mensch aus dem
Teamhaus zur Auswahl, auf der Teamadresse kein Creator -- auch
nicht für DogFather, der in beiden Häusern arbeitet. Und die
Grenze hält auch, wenn jemand die Nummer von Hand einträgt.
2. DIE SKALA. Vier Stufen im Agenturhaus, zwei im Teamhaus. Was
hier gilt, gilt dort nicht: "Passt nicht" an einem Modi muss
abgelehnt werden.
3. DIE NOTIZ. Ohne Satz kein "Passt nicht" und kein "Verbesserung
möglich" -- und der Creator sieht den Satz samt Rolle dessen,
der ihn geschrieben hat.
4. DIE UMSTELLUNG DER DATENBANK. Die CHECK-Regel ließ bis heute
nur drei Werte zu; sie lässt sich in SQLite nicht ändern, die
Tabelle muss neu gebaut werden. Am 11.09.2026 hat genau dieser
Griff drei Spalten samt Inhalt gekostet, ohne Fehlermeldung.
Deshalb wird hier eine Datenbank mit dem ALTEN Bauplan und
echten Zeilen darin hergestellt und danach nachgezählt --
Zeilen UND Spalten.
GEGENPROBEN, weil eine Prüfung, die immer bestätigt, nichts
bestätigt: Zu jeder Schranke steht daneben der Fall, der durchkommen
MUSS. Eine Absage allein beweist nur, dass etwas abgelehnt wird --
nicht, dass das Richtige abgelehnt wird.
===================================================================== */
import { mkdtempSync, readdirSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { request } from "node:http";
const ordner = mkdtempSync(join(tmpdir(), "ws-stufen-"));
process.env.WORKSPACE_DB = join(ordner, "workspace.db");
const { eigenerPort } = await import("./helfer-port.mjs");
const PORT = await eigenerPort(import.meta, "die Checklisten-Stufen");
process.env.PORT = `${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 }); };
await import("./index.js");
/* Die Notbremse NACH index.js -- der Server hängt dort zwei
Auffangnetze ein, die einen Absturz nur protokollieren. Richtig für
den Betrieb, fatal für eine Prüfung: Ohne eigene Zuhörer bliebe der
Prozess nach einem Fehler ewig stehen. */
for (const art of ["uncaughtException", "unhandledRejection"]) {
process.on(art, (f) => { console.error(""); console.error("ABBRUCH:", f?.stack || f); process.exit(1); });
}
setTimeout(() => { console.error(""); console.error("ABBRUCH: 150 s vorbei."); process.exit(1); },
150000).unref?.();
await new Promise((r) => setTimeout(r, 900));
let fehler = 0, geprueft = 0;
const ok = (b, t) => { geprueft++; console.log((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
const CREW = "crew.dogfather-universe.com";
const WS = "workspace.dogfather-universe.com";
function hole(pfad, { host, methode = "GET", rumpf = null, keks = "" } = {}) {
return new Promise((fertig, schief) => {
const kopf = { Host: host };
if (rumpf) { kopf["Content-Type"] = "application/json"; kopf["Content-Length"] = Buffer.byteLength(rumpf); }
if (keks) kopf.Cookie = keks;
const a = request({ host: "127.0.0.1", port: PORT, path: pfad, method: methode, headers: kopf },
(antwort) => {
let text = "";
antwort.setEncoding("utf8");
antwort.on("data", (t) => { text += t; });
antwort.on("end", () => {
let daten = null;
try { daten = JSON.parse(text); } catch { /* kein JSON */ }
fertig({ status: antwort.statusCode, text, daten,
keks: (antwort.headers["set-cookie"] || []).map((z) => z.split(";")[0]).join("; ") });
});
});
a.on("error", schief);
a.setTimeout(15000, () => { a.destroy(new Error("Zeitueberschreitung")); });
if (rumpf) a.write(rumpf);
a.end();
});
}
/* ---- Bestand -------------------------------------------------------- */
const { DatabaseSync } = await import("node:sqlite");
const { scryptSync, randomBytes } = await import("node:crypto");
await hole("/workspace/api/anmelden", { host: WS, methode: "POST",
rumpf: JSON.stringify({ rolle: "admin", code: "x" }) }).catch(() => {});
for (let i = 0; i < 60; i++) {
try {
const p = new DatabaseSync(process.env.WORKSPACE_DB);
try { p.prepare("SELECT 1 FROM personen LIMIT 1").get(); break; } finally { p.close(); }
} catch { await new Promise((r) => setTimeout(r, 250)); }
}
const d = new DatabaseSync(process.env.WORKSPACE_DB);
const jetzt = new Date().toISOString();
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, aktiv, erstellt) VALUES (?,?,?,?,?,1,?)")
.run(name, rolle, hash, salt, 32768, jetzt);
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
}
/* Die Namen sind ABSICHTLICH so gewählt, dass die Modi alphabetisch
VOR dem Creator steht -- genau die Lage, die den Fehler auf Filipes
Bildschirm erzeugt hat. Hieße die Modi "Zoe", wäre die Prüfung grün,
ohne je etwas gemessen zu haben. */
const idDogi = anlegen("Filipe", "admin", "CODE-DOGI-0001");
const idModi = anlegen("Ayla", "modi", "CODE-MODI-0001");
const idScout = anlegen("Patrick", "scout", "CODE-SCOU-0001");
const idMana = anlegen("Cigdem", "manager", "CODE-MANA-0001");
const idCrea = anlegen("Luna", "creator", "CODE-CREA-0001");
const idSpicy = anlegen("Agentur", "spicy", "CODE-SPIC-0001");
d.prepare("INSERT INTO betreuung (creator_id, betreuer_id, seit) VALUES (?,?,?)").run(idCrea, idScout, jetzt);
/* =====================================================================
DIE ALTE TABELLE HERSTELLEN -- sonst prüft die Umstellung nichts
Der Server baut sie beim ersten Aufruf einer Checkliste mit der
NEUEN Schranke. Eine Prüfung, die danach nachsieht, findet die neue
Schranke vor und meldet "in Ordnung", ohne dass je etwas umgestellt
wurde. Das ist die Sorte grüner Haken, die nichts bedeutet.
Deshalb wird hier der Zustand von gestern hergestellt: der alte
Bauplan, die vier später ergänzten Spalten, und echte Zeilen darin.
Die Zeilen tragen einen Wert in JEDER Spalte -- sonst könnte ein
Verlust unbemerkt bleiben, weil überall ohnehin NULL stünde.
===================================================================== */
d.exec(`
CREATE TABLE punkt_stand (
bereich TEXT NOT NULL,
schluessel TEXT NOT NULL,
creator_id INTEGER NOT NULL REFERENCES personen(id) ON DELETE CASCADE,
stufe TEXT NOT NULL CHECK (stufe IN ('offen','gut','verbessern')),
begruendung TEXT,
von INTEGER REFERENCES personen(id) ON DELETE SET NULL,
am TEXT NOT NULL,
behandelt_am TEXT, behandelt_von INTEGER, behandelt_art TEXT, aufgabe_id INTEGER,
PRIMARY KEY (bereich, schluessel, creator_id)
);
`);
d.prepare(`INSERT INTO punkt_stand
(bereich, schluessel, creator_id, stufe, begruendung, von, am,
behandelt_am, behandelt_von, behandelt_art, aufgabe_id)
VALUES ('live','ton-geprueft',?,'gut','Klang sauber.',?,?,?,?,'aufgabe',77)`)
.run(idCrea, idScout, jetzt, jetzt, idDogi);
d.prepare(`INSERT INTO punkt_stand
(bereich, schluessel, creator_id, stufe, begruendung, von, am)
VALUES ('live','m-ton-von-anfang-an',?,'verbessern','Erste Minute stumm.',?,?)`)
.run(idModi, idModi, jetzt);
const VORHER_ZEILEN = d.prepare("SELECT COUNT(*) AS n FROM punkt_stand").get().n;
const VORHER_SPALTEN = d.prepare("PRAGMA table_info(punkt_stand)").all().map((z) => z.name);
d.close();
async function anmelden(rolle, code, wand) {
const a = await hole("/workspace/api/anmelden", { host: wand, methode: "POST",
rumpf: JSON.stringify({ rolle, code }) });
return { ok: a.status === 200, keks: a.keks };
}
const dogiWs = await anmelden("admin", "CODE-DOGI-0001", WS);
const dogiCrew = await anmelden("admin", "CODE-DOGI-0001", CREW);
const scout = await anmelden("scout", "CODE-SCOU-0001", WS);
const mana = await anmelden("manager", "CODE-MANA-0001", WS);
const crea = await anmelden("creator", "CODE-CREA-0001", WS);
const modi = await anmelden("modi", "CODE-MODI-0001", CREW);
const spicy = await anmelden("spicy", "CODE-SPIC-0001", WS);
ok(dogiWs.ok && dogiCrew.ok && scout.ok && mana.ok && crea.ok && modi.ok && spicy.ok,
"alle sieben sind angemeldet");
const liste = (host, keks, zusatz = "") =>
hole(`/workspace/api/checkliste/live${zusatz}`, { host, keks });
const setzen = (host, keks, schluessel, rumpf) =>
hole(`/workspace/api/checkliste/live/${schluessel}`, { host, keks,
methode: "PUT", rumpf: JSON.stringify(rumpf) });
/* =======================================================================
1. Die Umstellung der Datenbank
======================================================================= */
console.log("");
console.log("=== Die Tabelle wurde umgebaut, ohne etwas zu verlieren ===");
{
/* Der erste Aufruf löst tabellen() aus -- vorher ist nichts passiert. */
await liste(WS, dogiWs.keks);
const p = new DatabaseSync(process.env.WORKSPACE_DB, { readOnly: true });
const bauplan = p.prepare(
"SELECT sql FROM sqlite_master WHERE type='table' AND name='punkt_stand'").get()?.sql || "";
const zeilen = p.prepare("SELECT COUNT(*) AS n FROM punkt_stand").get().n;
const spalten = p.prepare("PRAGMA table_info(punkt_stand)").all().map((z) => z.name);
const alt = p.prepare(
"SELECT * FROM punkt_stand WHERE creator_id = ? AND schluessel = 'ton-geprueft'").get(idCrea);
const rest = p.prepare(
"SELECT COUNT(*) AS n FROM sqlite_master WHERE name = 'punkt_stand_neu'").get().n;
p.close();
ok(/passt_nicht/.test(bauplan) && /entfaellt/.test(bauplan),
"die Schranke lässt jetzt alle Stufen beider Häuser zu");
ok(zeilen === VORHER_ZEILEN,
`alle Zeilen sind noch da (${zeilen} von ${VORHER_ZEILEN})`);
/* DIE ZEILENZÄHLUNG ALLEIN BEWEIST NICHTS -- am 11.09.2026 war sie
unverändert, während drei Spalten samt Inhalt verschwunden waren.
Deshalb daneben die Spalten. */
const verloren = VORHER_SPALTEN.filter((sp) => !spalten.includes(sp));
ok(verloren.length === 0,
`alle ${VORHER_SPALTEN.length} Spalten sind noch da`
+ (verloren.length ? ` — fehlen: ${verloren.join(", ")}` : ""));
/* UND DER INHALT DER SPALTEN, nicht nur ihre Namen. Eine Tabelle mit
den richtigen Überschriften und leeren Feldern zählt genauso viele
Zeilen und Spalten wie eine richtige. */
ok(alt?.begruendung === "Klang sauber." && alt?.von === idScout
&& alt?.behandelt_art === "aufgabe" && alt?.aufgabe_id === 77,
`auch der Inhalt der später ergänzten Spalten steht noch `
+ `(behandelt_art=${alt?.behandelt_art}, aufgabe_id=${alt?.aufgabe_id})`);
ok(rest === 0, "die Behelfstabelle ist wieder weg");
/* UND DIE SICHERUNG? Sie ist die einzige der fuenf Absicherungen,
die man nach einem gelungenen Lauf nicht mehr sieht -- und die
einzige, die zaehlt, wenn er misslingt. Beim ersten Anlauf dieses
Umbaus hatte ich die Umstellung selbst geschrieben und genau sie
vergessen; gefunden habe ich das nicht durch eine Pruefung,
sondern beim Nachsehen, wie das Haus dasselbe Problem schon
dreimal geloest hat. Diese Zeile sorgt dafuer, dass es beim
naechsten Mal die Pruefung findet. */
const sicherungen = readdirSync(ordner).filter((f) => f.includes(".vor-passt_nicht-"));
ok(sicherungen.length === 1,
`vor dem Umbau wurde die ganze Datenbank gesichert (${sicherungen[0] || "keine gefunden"})`);
/* GEGENPROBE: Die Prüfung oben kann einen Verlust überhaupt sehen. */
const erfunden = VORHER_SPALTEN.filter((sp) => !["bereich", "aufgabe_id"].includes(sp));
ok(VORHER_SPALTEN.filter((sp) => !erfunden.includes(sp)).length === 2,
"Gegenprobe: eine Spaltenliste mit zwei fehlenden Namen fällt auf");
}
/* =======================================================================
2. Die Grenze zwischen den Häusern
======================================================================= */
console.log("");
console.log("=== Auf welcher Adresse steht wer zur Auswahl? ===");
{
const ws = (await liste(WS, dogiWs.keks)).daten;
const cr = (await liste(CREW, dogiCrew.keks)).daten;
const namenWs = (ws?.creatoren || []).map((z) => z.name);
const namenCr = (cr?.creatoren || []).map((z) => z.name);
ok(namenWs.includes("Luna") && !namenWs.includes("Ayla"),
`auf workspace. nur die Agentur (${namenWs.join(", ") || "leer"})`);
ok(namenCr.includes("Ayla") && !namenCr.includes("Luna"),
`auf crew. nur das Team (${namenCr.join(", ") || "leer"})`);
/* DAS WAR DER EIGENTLICHE BEFUND: nicht die Auswahlliste, sondern
das, was ohne Wahl VORAUSGEWÄHLT wird. "Ayla" steht alphabetisch
vor "Luna" -- bis zum 24.09.2026 bekam DogFather deshalb auf der
Agenturadresse zuverlässig die Liste einer Modi vorgesetzt. */
ok(ws?.creator_id === idCrea,
`ohne Wahl steht auf workspace. der Creator da (${ws?.creator_id} = ${idCrea})`);
ok(cr?.creator_id === idModi,
`und auf crew. die Modi (${cr?.creator_id} = ${idModi})`);
/* Und die Punkte selbst: Die Teamfassung erkennt man am Präfix "m-". */
const ersterWs = ws?.gruppen?.[0]?.punkte?.[0]?.schluessel || "";
const ersterCr = cr?.gruppen?.[0]?.punkte?.[0]?.schluessel || "";
ok(!ersterWs.startsWith("m-"),
`auf workspace. steht der Creator-Katalog ("${ersterWs}")`);
ok(ersterCr.startsWith("m-"),
`auf crew. der des Teams ("${ersterCr}")`);
ok(ws?.gruppen?.[0]?.text !== cr?.gruppen?.[0]?.text,
"auch der Satz unter der Überschrift ist nicht derselbe");
}
console.log("");
console.log("=== Die Grenze hält auch gegen eine von Hand eingetragene Nummer ===");
{
/* Die Auswahlliste auszudünnen ist Kosmetik, solange die Nummer in
der Adresse durchgeht. Genau so sind in diesem Haus schon Wege
offen geblieben, die auf keinem Bildschirm zu sehen waren. */
const a = await liste(WS, dogiWs.keks, `?creator_id=${idModi}`);
ok(a.status === 404,
`DogFather kommt auf workspace. nicht an die Liste der Modi (${a.status})`);
const b = await liste(CREW, dogiCrew.keks, `?creator_id=${idCrea}`);
ok(b.status === 404,
`und auf crew. nicht an die des Creators (${b.status})`);
const c = await setzen(WS, dogiWs.keks, "m-ton-von-anfang-an",
{ stufe: "gut", creator_id: idModi });
ok(c.status === 404, `auch schreibend nicht (${c.status})`);
/* GEGENPROBE: Auf der jeweils RICHTIGEN Adresse geht derselbe Griff
durch. Ohne sie bewiese die 404 oben nur, dass irgendetwas
abgelehnt wird -- nicht, dass die Adresse den Unterschied macht. */
const d1 = await liste(CREW, dogiCrew.keks, `?creator_id=${idModi}`);
ok(d1.status === 200,
`auf crew. dagegen schon -- die Adresse macht den Unterschied (${d1.status})`);
const d2 = await liste(WS, dogiWs.keks, `?creator_id=${idCrea}`);
ok(d2.status === 200, `und auf workspace. der Creator (${d2.status})`);
}
console.log("");
console.log("=== Wer gar keine Liste hat, bekommt auch keine ===");
{
/* `darfCreator` sagt für DogFather bei JEDER Personennummer ja. Bis
zum 24.09.2026 konnte er damit einen Stand an einer Managerin
setzen -- für einen Punkt, der in ihrer Ansicht nie erscheint.
Die Zeile lag danach in der Datenbank und war nirgends zu sehen. */
const a = await liste(WS, dogiWs.keks, `?creator_id=${idMana}`);
ok(a.status === 404, `eine Managerin hat keine Checkliste (${a.status})`);
const b = await setzen(WS, dogiWs.keks, "ton-geprueft",
{ stufe: "gut", creator_id: idMana });
ok(b.status === 404, `und bekommt auch keinen Stand gesetzt (${b.status})`);
const c = await setzen(WS, dogiWs.keks, "ton-geprueft",
{ stufe: "gut", creator_id: idDogi });
ok(c.status === 404, `DogFather sich selbst ebenfalls nicht (${c.status})`);
}
/* =======================================================================
3. Die Skala -- vier Stufen hier, zwei dort
======================================================================= */
console.log("");
console.log("=== Zwei Häuser, zwei Skalen ===");
{
const ws = (await liste(WS, dogiWs.keks)).daten;
const cr = (await liste(CREW, dogiCrew.keks)).daten;
const wsS = (ws?.stufen || []).map((s) => s.schluessel);
const crS = (cr?.stufen || []).map((s) => s.schluessel);
ok(wsS.join(",") === "gut,verbessern,passt_nicht,entfaellt",
`im Agenturhaus vier Stufen (${wsS.join(", ")})`);
ok(crS.join(",") === "gut,verbessern",
`im Teamhaus zwei (${crS.join(", ")})`);
/* Jede Stufe braucht ein Wort und eine Bilanzzeile -- sonst steht in
der Oberfläche ein leerer Knopf oder eine leere Kachel. */
const stumm = (ws?.stufen || []).filter((s) => !s.name || !s.bilanz);
ok(stumm.length === 0,
`jede Stufe hat Wort und Bilanzzeile (${(ws?.stufen || []).length} geprüft)`);
/* Und "offen" darf NICHT darin stehen: Es ist keine Stufe, sondern
das Zurücknehmen einer. Stünde es im Katalog, baute die Oberfläche
einen Knopf "Offen" neben die anderen. */
ok(!wsS.includes("offen"), "„offen“ steht in keinem Katalog");
}
console.log("");
console.log("=== Was hier gilt, gilt dort nicht ===");
{
const a = await setzen(WS, scout.keks, "ton-geprueft",
{ stufe: "passt_nicht", begruendung: "Der Ton rauscht durchgehend.", creator_id: idCrea });
ok(a.status === 200, `ein Scout setzt „Passt nicht“ bei seinem Creator (${a.status})`);
const b = await hole("/workspace/api/checkliste/live/m-ton-von-anfang-an",
{ host: CREW, keks: modi.keks, methode: "PUT",
rumpf: JSON.stringify({ stufe: "passt_nicht", begruendung: "Ging gar nicht." }) });
ok(b.status === 400,
`dieselbe Stufe an einem Modi-Bericht wird abgelehnt (${b.status})`);
ok(/Passt so|Verbessern/.test(b.daten?.fehler || ""),
`und die Absage nennt, was dort möglich ist ("${(b.daten?.fehler || "").slice(0, 60)}…")`);
/* GEGENPROBE: Der Modi kommt mit SEINER Stufe durch. Ohne sie hieße
die 400 oben womöglich nur "der Modi darf gar nichts". */
const c = await hole("/workspace/api/checkliste/live/m-ton-von-anfang-an",
{ host: CREW, keks: modi.keks, methode: "PUT",
rumpf: JSON.stringify({ stufe: "verbessern", begruendung: "Erste Minute stumm." }) });
ok(c.status === 200, `„Verbessern“ geht dort weiterhin (${c.status})`);
}
console.log("");
console.log("=== Ein Punkt aus dem anderen Katalog geht nicht durch ===");
{
/* Bis zum 24.09.2026 lagen beide Kataloge in EINER Menge gültiger
Schlüssel. Ein Scout konnte damit bei einem Creator den Stand
eines Modi-Punktes setzen: angenommen, gespeichert, nie zu sehen. */
const a = await setzen(WS, scout.keks, "m-ton-von-anfang-an",
{ stufe: "gut", creator_id: idCrea });
ok(a.status === 404, `ein Modi-Punkt an einem Creator: abgelehnt (${a.status})`);
/* EIN ANDERER PUNKT ALS ton-geprueft -- der traegt weiter unten das
"Passt nicht", das der Creator sehen soll. Eine Gegenprobe, die
den Bestand der naechsten Pruefung umschreibt, macht aus einem
echten Befund einen Fehlalarm; genau das ist beim ersten Lauf
dieser Datei passiert. */
const b = await setzen(WS, scout.keks, "angekuendigt",
{ stufe: "gut", creator_id: idCrea });
ok(b.status === 200, `Gegenprobe: sein eigener Punkt geht (${b.status})`);
}
/* =======================================================================
4. Die Notiz -- und wer sie geschrieben hat
======================================================================= */
console.log("");
console.log("=== Ohne Satz kein Urteil ===");
{
const a = await setzen(WS, scout.keks, "licht-sitzt",
{ stufe: "passt_nicht", creator_id: idCrea });
ok(a.status === 400, `„Passt nicht“ ohne Satz wird abgelehnt (${a.status})`);
const b = await setzen(WS, scout.keks, "licht-sitzt",
{ stufe: "verbessern", begruendung: "kurz", creator_id: idCrea });
ok(b.status === 400, `vier Zeichen sind noch kein Satz (${b.status})`);
/* GEGENPROBE: "Passt" braucht keinen -- eine Pflicht an der
häufigsten und harmlosesten Handlung wäre nur eine Hürde. */
const c = await setzen(WS, scout.keks, "licht-sitzt",
{ stufe: "gut", creator_id: idCrea });
ok(c.status === 200, `„Passt“ dagegen schon (${c.status})`);
/* Und "Trifft nicht zu" ebenfalls nicht -- sie fragt freiwillig. */
const e = await setzen(WS, scout.keks, "verbindung-getestet",
{ stufe: "entfaellt", creator_id: idCrea });
ok(e.status === 200, `„Trifft nicht zu“ ebenso (${e.status})`);
}
console.log("");
console.log("=== Was der Creator sieht ===");
{
const r = (await liste(WS, crea.keks)).daten;
const s = r?.stand?.["ton-geprueft"];
ok(r?.creator_id === idCrea, `er sieht immer nur sich selbst (${r?.creator_id})`);
ok(r?.darf_bewerten === false, `und darf nichts setzen (${r?.darf_bewerten})`);
ok(s?.stufe === "passt_nicht", `die Stufe steht da (${s?.stufe})`);
ok(s?.begruendung === "Der Ton rauscht durchgehend.", "der Satz dazu ebenfalls");
/* Filipe: "mit der notiz vom manager oder scout." Ein Vorname allein
beantwortet nicht, WER das ist -- im ersten Monat kennt ein
Creator die Namen nicht. */
ok(s?.von_name === "Patrick" && s?.von_rolle_name === "Scout",
`mit Name UND Rolle (${s?.von_name}, ${s?.von_rolle_name})`);
/* Die Skala bekommt er auch -- ohne sie könnte er die Marke an
seinem Punkt nicht beschriften. */
ok((r?.stufen || []).length === 4, `und die vier Stufen (${(r?.stufen || []).length})`);
ok(/Betreuung/.test(r?.einleitung || ""),
`der Satz oben ist seiner, nicht der der Betreuung`);
}
console.log("");
console.log("=== Ein Manager darf dasselbe wie ein Scout ===");
{
/* Filipe: "die sollen die manager und scouts bewerten können."
Ein Manager ohne zugeteilten Creator sieht keinen -- das ist die
Betreuungsregel und nicht die Haustrennung. Geprüft wird deshalb
mit Zuteilung. */
const p = new DatabaseSync(process.env.WORKSPACE_DB);
p.prepare("INSERT INTO betreuung (creator_id, betreuer_id, seit) VALUES (?,?,?) "
+ "ON CONFLICT(creator_id) DO UPDATE SET betreuer_id = excluded.betreuer_id")
.run(idCrea, idMana, jetzt);
p.close();
const r = (await liste(WS, mana.keks)).daten;
ok(r?.darf_bewerten === true, `die Managerin darf drücken (${r?.darf_bewerten})`);
const a = await setzen(WS, mana.keks, "titel-und-thema-stehen",
{ stufe: "verbessern", begruendung: "Titel sagt noch nichts über das Thema.",
creator_id: idCrea });
ok(a.status === 200, `und tut es (${a.status})`);
ok(a.daten?.stand?.stufe === "verbessern", "der Stand kommt zurück");
}
/* =======================================================================
5. Und die Zahl, die Filipe oben sieht
======================================================================= */
console.log("");
console.log("=== Spicy Media und DogFather drücken wie vorher ===");
{
/* Filipe: "spicy und dogfather sollen auch bewerten können wie
vorher." An ihren Rechten sollte dieser Umbau nichts ändern -- aber
"sollte nichts ändern" ist eine Absicht und keine Messung. Beide
laufen durch dieselbe neue Haus-Schranke wie alle anderen, und
eine Schranke, die zu viel wegnimmt, sieht von außen genauso aus
wie eine, die richtig sitzt. */
for (const [wer, sitzung] of [["Spicy Media", spicy], ["DogFather", dogiWs]]) {
const r = (await liste(WS, sitzung.keks)).daten;
ok(r?.darf_bewerten === true, `${wer} darf drücken (${r?.darf_bewerten})`);
ok((r?.creatoren || []).some((z) => z.id === idCrea),
` und hat den Creator in der Auswahl (${(r?.creatoren || []).map((z) => z.name).join(", ")})`);
ok((r?.stufen || []).length === 4, ` mit allen vier Stufen (${(r?.stufen || []).length})`);
}
const a = await setzen(WS, spicy.keks, "technik-hat-gehakt",
{ stufe: "passt_nicht", begruendung: "Zweimal komplett weg, ohne Ansage.", creator_id: idCrea });
ok(a.status === 200, `und Spicy Media setzt auch wirklich (${a.status})`);
/* Zurück auf offen -- sonst zählt der Hinweis weiter unten drei statt
zwei, und die nächste Prüfung meldete einen Fehler, den diese hier
verursacht hat. */
await setzen(WS, spicy.keks, "technik-hat-gehakt", { stufe: "offen", creator_id: idCrea });
}
console.log("");
console.log("=== „Passt nicht“ landet auf der Startseite des Creators ===");
{
/* Der Zähler auf der Kachel zählte fest `stufe = 'verbessern'`. Ohne
Nachziehen wäre die stärkste Rückmeldung, die es gibt, als
Einzige nicht auf der Startseite erschienen -- der Creator sähe
ein ruhiges Kästchen, während sein Scout auf etwas wartet. */
const r = (await hole("/workspace/api/hinweise", { host: WS, keks: crea.keks })).daten;
const h = (r?.hinweise || []).find((x) => x.art === "markiert_live");
ok(!!h, `der Hinweis zur LIVE-Analyse steht da (${h ? h.anzahl : "fehlt"})`);
/* Zwei markierte Punkte: „Passt nicht" bei ton-geprueft und
„Verbesserung möglich" bei titel-und-thema-stehen. */
ok(h?.anzahl === 2, `und zählt beide markierten Stufen (${h?.anzahl} von 2)`);
}
console.log("");
console.log(`${geprueft} Pruefungen, ${fehler} Fehlschlaege.`);
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ }
process.exit(fehler ? 1 : 0);
+42 -9
View File
@@ -334,9 +334,22 @@ const browser = await chromium.launch();
await senden(`/workspace/api/checkliste/live/${punkt}`, kScout, "PUT",
{ stufe: "verbessern", begruendung: "Mikro naeher heranstellen.", creator_id: idTili });
for (const [rolle, code, name, darf] of [
["scout", "CODE-SCOU-0001", "Patrick", true],
["creator", "CODE-ANNA-0001", "Tili", false],
/* WIE VIELE KNOEPFE UND KACHELN ES SEIN MUESSEN, WIRD NICHT MEHR
HINGESCHRIEBEN (24.09.2026).
Hier standen feste Zahlen: drei Bilanzkacheln, zwei Knoepfe je Punkt.
Am Tag, an dem das Agenturhaus vier Stufen bekam, war diese Pruefung
rot -- nicht weil etwas kaputt war, sondern weil sie eine Zahl von
gestern gegen einen Stand von heute hielt. Genau die Sorte
Fehlalarm, die Vertrauen in einen ganzen Pruefsatz kostet.
Jetzt fragt sie fuer JEDE Rolle und JEDEN Bereich die Schnittstelle
und rechnet daraus, was auf dem Bildschirm stehen muss. Das ist kein
Selbstgespraech: Die Antwort kommt vom Server, gezaehlt wird im
Browser -- weichen sie voneinander ab, faellt es auf. */
for (const [rolle, code, name, darf, keksRolle] of [
["scout", "CODE-SCOU-0001", "Patrick", true, kScout],
["creator", "CODE-ANNA-0001", "Tili", false, kTili],
]) {
const kontext = await browser.newContext({ viewport: { width: 1280, height: 1100 } });
const konsole = [];
@@ -387,15 +400,27 @@ for (const [rolle, code, name, darf] of [
})(),
ueber: document.documentElement.scrollWidth - document.documentElement.clientWidth,
}));
/* Dieselbe Auskunft, die auch die Seite bekommen hat. */
const api = await (await ruf(`/workspace/api/checkliste/${bereich}`, keksRolle)).json();
const inListe = api.gruppen.flatMap((g) => g.punkte);
const gesetzt = new Set(inListe.map((p) => api.stand[p.schluessel]?.stufe || "offen"));
/* Eine "stille" Stufe bekommt erst dann eine Kachel, wenn sie
vorkommt -- "0 trifft nicht zu" ueber jeder Liste waere eine
Auskunft, die niemand gesucht hat. Dazu immer "noch offen". */
const sollBilanz = api.stufen.filter((x) => !x.still || gesetzt.has(x.schluessel)).length + 1;
const sollKnoepfe = api.darf_bewerten ? r.punkte * api.stufen.length : 0;
const gut = r.stufenleiter === 5
&& r.da && r.gruppen === 3 && r.punkte >= 6 && r.bilanz === 3 && r.gestaltet === true
&& r.da && r.gruppen === 3 && r.punkte >= 6 && r.bilanz === sollBilanz
&& r.gestaltet === true
&& r.marken === r.punkte && r.ueber <= 0
&& (darf ? r.stufenKnoepfe === r.punkte * 2 : r.stufenKnoepfe === 0);
&& r.stufenKnoepfe === sollKnoepfe
&& api.darf_bewerten === darf;
if (!gut) fehler++;
console.log(` ${gut ? "ok " : "FEHL"} ${name} · ${bereich}: `
+ `${r.gruppen} Gruppen, ${r.punkte} Punkte, ${r.bilanz} Bilanzzahlen, `
+ `${r.stufenKnoepfe} Bewertungsknoepfe, ${r.marken} Marken, `
+ `Stufenleiste ${r.stufenleiter}/5, ${r.ueber}px über`
+ `${r.gruppen} Gruppen, ${r.punkte} Punkte, `
+ `${r.bilanz}/${sollBilanz} Bilanzzahlen, `
+ `${r.stufenKnoepfe}/${sollKnoepfe} Bewertungsknoepfe (${api.stufen.length} Stufen), `
+ `${r.marken} Marken, Stufenleiste ${r.stufenleiter}/5, ${r.ueber}px über`
+ (r.gestaltet ? "" : " STIL FEHLT"));
}
ok(konsole.length === 0,
@@ -414,7 +439,15 @@ for (const [rolle, code, name, darf] of [
} : null;
});
ok(!!s, "der Creator sieht den Punkt als 'zu verbessern' markiert");
ok(/Verbessern/i.test(s?.marke || ""), ` mit lesbarer Marke ("${s?.marke}")`);
/* DAS WORT AUF DER MARKE KOMMT VOM SERVER und steht hier nicht als
Muster. Es hiess bis zum 24.09.2026 "Verbessern" und heisst im
Agenturhaus jetzt "Verbesserung möglich" -- ein `/Verbessern/i`
hier war damit rot, ohne dass etwas kaputt war. Geprueft wird die
Sache dahinter: Auf der Marke steht GENAU das Wort, das der
Katalog fuer diese Stufe vorsieht. */
const wort = (listen.live.stufen || []).find((x) => x.schluessel === "verbessern")?.name;
ok(!!wort && (s?.marke || "").trim() === wort,
` mit dem Wort aus dem Katalog ("${s?.marke}" = "${wort}")`);
ok(/Mikro/.test(s?.grund || ""), ` und dem Grund ("${s?.grund}")`);
await seite.screenshot({ path: "pruef-checkliste.png", fullPage: false });
+484 -41
View File
@@ -36,8 +36,9 @@ import express from "express";
import {
db, sitzungLesen, istLeitung, istDogFather, siehtAlles, darfCreator, betreuteIds,
protokolliere, echteIp,
siehtModis, TEAM_DOGI_ROLLEN, istHand,
siehtModis, TEAM_DOGI_ROLLEN, istHand, ROLLEN_NAME, checkListeErweitern,
} from "./workspace.js";
import { hausVonRolle } from "./crew-adresse.js";
import { MODI_PUNKTE, MODI_GRUPPENTEXTE } from "./workspace-modi-punkte.js";
import {
CONTENT_IDEEN, LIVE_PUNKTE, COMMUNITY_PUNKTE, TECHNIK_PUNKTE,
@@ -46,8 +47,152 @@ import {
export const checklisteRouter = express.Router();
const jetzt = () => new Date().toISOString();
const STUFEN = new Set(["offen", "gut", "verbessern"]);
const GRUND_MAX = 2000;
const GRUND_MIN = 5;
/* =====================================================================
ZWEI URTEILSSKALEN -- EINE JE HAUS (24.09.2026)
Filipe, mit dem Bildschirmfoto der LIVE-Punkte:
*"die sollen die manager und scouts bewerten können mit passt passt
nicht verbesserung möglich und was weiß ich. und die creator sollen
sehen was bei ihnen passt oder nicht mit der notiz vom manager oder
scout. ... und wie gesagt von der team dogi seite da ist ein anderes
system auf diesen aufgaben."*
ES SIND ZWEI VERSCHIEDENE DINGE, DIE BIS HEUTE DIESELBEN DREI WORTE
BENUTZT HABEN.
Im AGENTURHAUS urteilt eine Betreuung ueber die Arbeit eines
Creators: Manager, Scout, Spicy Media, DogFather druecken, der
Creator liest. Dafuer reichen zwei Stufen nicht. "Verbessern" muss
heute alles tragen, von "fast perfekt, eine Kleinigkeit" bis "so
geht es gar nicht" -- und ein Creator kann an dem Wort nicht
ablesen, wie ernst es gemeint ist. Genau danach hat Filipe gefragt.
Im TEAMHAUS ist es umgekehrt: Der Modi BERICHTET ueber eine Sendung,
die er gesehen hat, und DogFather behandelt den Bericht im Eingang
("Dein Team"). Dort ist "Verbessern" kein Urteil, sondern ein
Eingang -- aus ihm wird eine Aufgabe oder eine begruendete Absage.
Eine dritte Stufe "Passt nicht" haette dort keinen Empfaenger; sie
wuerde im Eingang entweder verschwinden oder ihn verdoppeln.
DESHALB ZWEI KATALOGE UND NICHT EIN GEMEINSAMER MIT AUSNAHMEN. Ein
gemeinsamer waere die Stelle, an der beim naechsten Wunsch wieder
beides zusammenwaechst.
WARUM "TRIFFT NICHT ZU" DAZUGEHOERT und nicht Beiwerk ist: Ohne sie
bleibt ein Punkt, der bei diesem Creator gar nicht vorkommt (kein
Gast, kein Sendeplan, keine Zweitkamera), fuer immer auf "offen"
stehen. Die Bilanz oben zaehlt ihn dann als unerledigt mit -- und
eine Zahl, die etwas mitzaehlt, was nie erledigt werden kann, wird
nach zwei Wochen nicht mehr angesehen.
`grund: "pflicht"` heisst: ohne Satz geht es nicht. Er steht dort,
wo der Creator sonst raten muesste, was gemeint ist -- und nur dort.
Ein Pflichtfeld an "Passt" waere eine Huerde vor der haeufigsten und
harmlosesten Handlung.
DIE WORTE STEHEN HIER UND NICHT IM BROWSER. Der Browser baut die
Knoepfe aus dieser Liste. Stuenden sie dort noch einmal, haette das
Haus zwei Wahrheiten darueber, was es gerade misst -- und die
Oberflaeche wuerde einem Modi eines Tages einen Knopf zeigen, den
der Server mit 400 abweist. Das ist schlechter als kein Knopf.
===================================================================== */
/* Die Felder, die jede Stufe traegt -- einmal erklaert, damit die
Listen darunter ohne Kommentar auskommen:
schluessel steht in der Datenbank. Aendert sich nie.
name steht auf dem Knopf und auf der Marke am Punkt.
bilanz steht in der Zaehlkachel oben, HINTER der Zahl
("8 passt so"). Deshalb klein und ohne Punkt.
grund "pflicht" = ohne Satz keine Bewertung.
frage die Zeile ueber dem Textfeld im Nachfragefenster --
UND zugleich die Entscheidung, ob ueberhaupt gefragt
wird. Eine Stufe ohne `frage` wird mit einem Klick
gesetzt. Das ist Absicht und keine Sparsamkeit:
"Passt" ist der haeufigste Klick einer Betreuung,
die vierzig Punkte durchgeht, und er braucht keine
Erklaerung. Ein Nachfragefenster davor macht aus
einem Durchgang eine Sitzung. Alles, was der andere
verstehen oder tun muss, fragt dagegen nach.
merk zaehlt in das Merkzeichen (die Raute) und in den
Sprung "zeig mir die markierten Punkte".
still erscheint in der Bilanz erst, wenn es vorkommt.
Eine Kachel "0 trifft nicht zu" ueber jeder Liste
waere eine Auskunft, die niemand gesucht hat. */
export const STUFEN_AGENTUR = [
{ schluessel: "gut", name: "Passt", bilanz: "passt so", grund: "frei",
merk: false, still: false, frage: null, platzhalter: null },
{ schluessel: "verbessern", name: "Verbesserung möglich", bilanz: "zu verbessern",
grund: "pflicht", merk: true, still: false,
frage: "Was genau lässt sich verbessern?",
platzhalter: "z. B. Die Ankündigung kam erst 10 Minuten vorher." },
{ schluessel: "passt_nicht", name: "Passt nicht", bilanz: "passt nicht",
grund: "pflicht", merk: true, still: false,
frage: "Was passt nicht – und was soll stattdessen passieren?",
platzhalter: "z. B. Der Titel sagt nichts über das Thema. Bitte vorher ändern." },
{ schluessel: "entfaellt", name: "Trifft nicht zu", bilanz: "trifft nicht zu",
grund: "frei", merk: false, still: true,
frage: "Warum trifft das hier nicht zu? (freiwillig)",
platzhalter: "z. B. Du sendest ohne Gäste – der Punkt kommt bei dir nicht vor." },
];
export const STUFEN_CREW = [
{ schluessel: "gut", name: "Passt so", bilanz: "passt so", grund: "frei",
merk: false, still: false, frage: null, platzhalter: null },
{ schluessel: "verbessern", name: "Verbessern", bilanz: "zu verbessern", grund: "pflicht",
merk: true, still: false,
frage: "Was genau soll verbessert werden?",
platzhalter: "z. B. Fehlt noch das Impressum unten auf der Seite." },
];
/** Welche Skala gilt fuer die Liste DIESER Person?
*
* Nach der Rolle dessen, UM DEN es geht -- nicht nach der Rolle
* dessen, der zusieht. Genau so entscheidet schon `gruppenFuer`,
* welche Punkte in der Liste stehen; stuenden hier zwei verschiedene
* Fragen, koennte ein Katalog aus dem einen Haus mit den Stufen des
* anderen bewertet werden.
*/
export function stufenFuer(zielRolle) {
const katalog = TEAM_DOGI_ROLLEN.has(zielRolle) ? STUFEN_CREW : STUFEN_AGENTUR;
/* Nur, was die Datenbank auch annimmt -- siehe
stufenSchrankeNachziehen(). Im Normalfall ist das der ganze
Katalog; solange niemand nachgesehen hat (`null`), ebenfalls. */
if (!stufenInDatenbank) return katalog;
return katalog.filter((s) => stufenInDatenbank.has(s.schluessel));
}
/* "offen" steht in keinem der beiden Kataloge und ist trotzdem in
beiden gueltig: Es ist keine Stufe, sondern das Zuruecknehmen einer
Stufe -- der Datensatz wird dabei geloescht. Waere es ein Eintrag im
Katalog, stuende in der Oberflaeche ein Knopf "Offen" neben den
anderen, und niemand wuesste, was er aussagt. */
const ZURUECK = "offen";
/* =====================================================================
WAS DIE DATENBANK ZULASSEN MUSS -- ABGELEITET, NIE ABGESCHRIEBEN
Die Spalte `stufe` traegt beide Haeuser; die Schranke in der
Datenbank muss deshalb die Vereinigung beider Kataloge kennen. Wer
sie als feste Liste hinschreibt, schreibt eine Liste, die beim
naechsten Wunsch veraltet -- und zwar still: Die Oberflaeche zeigt
den neuen Knopf, der Server nimmt ihn an, und SQLite lehnt ab. Der
Fehler landet dann in einem 503, der nach Ausfall aussieht.
Am 11.09.2026 hat genau diese Bauart -- eine von Hand gepflegte
Spaltenliste -- drei Spalten samt Inhalt gekostet. Die Lehre stand
danach als Kommentar daneben und hat den naechsten Verlust nicht
verhindert. Hier ist sie deshalb kein Kommentar, sondern eine
Ableitung: Die Liste KANN nicht veralten, weil niemand sie pflegt.
===================================================================== */
const ALLE_STUFEN = [...new Set([
ZURUECK,
...STUFEN_AGENTUR.map((s) => s.schluessel),
...STUFEN_CREW.map((s) => s.schluessel),
])];
const STUFEN_CHECK = ALLE_STUFEN.map((s) => `'${s}'`).join(",");
/* ---------------------------------------------------------------------
Die Listen, gruppiert und beschriftet.
@@ -161,18 +306,82 @@ function gruppenFuer(bereich, fuerModi) {
.filter((g) => g.punkte.length);
}
/* BEIDE SAETZE sind gueltige Schluessel. Stuenden hier nur die
Creator-Punkte, liesse sich der Stand eines Modi-Punktes nicht
setzen -- die Liste kaeme an, und jeder Klick darauf brachte einen
404. Genau die Sorte Fehler, die man erst beim Benutzen merkt. */
const GUELTIG = {};
for (const [bereich, liste] of Object.entries(LISTEN)) {
GUELTIG[bereich] = new Set(liste.gruppen.flatMap((g) => g.punkte.map((p) => p.schluessel)));
for (const punkte of Object.values(MODI_PUNKTE[bereich] || {})) {
for (const p of punkte) GUELTIG[bereich].add(p.schluessel);
/* =====================================================================
GUELTIGE SCHLUESSEL -- JE SATZ GETRENNT (getrennt am 24.09.2026)
Hier stand EINE Menge je Bereich, in der beide Saetze zusammenlagen:
die Creator-Punkte und die des Teams. Das war gut gemeint (sonst
haette ein Modi auf jeden Klick eine 404 bekommen) und es war die
Stelle, an der die beiden Haeuser sich beruehrten.
GEMESSEN, WAS DAS BEDEUTET: Ein Scout konnte bei einem Creator den
Stand von "m-ton-von-anfang-an" setzen -- einem Punkt aus dem
Teamkatalog. Der Server nahm ihn an, die Zeile lag in der Datenbank,
und zu sehen war sie nie: Die Liste des Creators kennt diesen
Schluessel nicht. Kein Fehler, keine Meldung, nur eine Zeile, die es
nicht geben duerfte -- und beim naechsten Zaehlen taucht sie in
einer Summe auf, die niemand erklaeren kann.
JETZT ZWEI MENGEN, und gefragt wird die des ZIELS: Wessen Liste ist
es? Dessen Katalog gilt. Genau dieselbe Frage entscheidet schon,
welche Punkte ausgeliefert werden (gruppenFuer) und welche Stufen
erlaubt sind (stufenFuer) -- drei Stellen, eine Frage.
===================================================================== */
const GUELTIG = { creator: {}, team: {} };
for (const bereich of Object.keys(LISTEN)) {
for (const [satz, fuerModi] of [["creator", false], ["team", true]]) {
GUELTIG[satz][bereich] = new Set(
(gruppenFuer(bereich, fuerModi) || []).flatMap((g) => g.punkte.map((p) => p.schluessel)));
}
}
/** Gibt es diesen Punkt im Katalog DER PERSON, um die es geht? */
function gueltigerPunkt(bereich, schluessel, zielRolle) {
const satz = TEAM_DOGI_ROLLEN.has(zielRolle) ? "team" : "creator";
return !!GUELTIG[satz][bereich]?.has(schluessel);
}
/* =====================================================================
WER UEBERHAUPT EINE LISTE HAT -- UND IN WELCHEM HAUS SIE STEHT
(24.09.2026)
Filipe: *"alle auf dieser app getrennt von denen auf der team dogi
website bitte, sehr wichtig."*
ER HAT ES AUF SEINEM BILDSCHIRM GESEHEN, nicht vermutet: Auf
workspace.dogfather-universe.com stand unter "Vor der Sendung" die
Liste eines MODIS ("Die Ankündigung kam rechtzeitig", darueber der
Satz "Was du vor und beim Start gesehen hast"). Nachgemessen am
echten Bestand: Die Auswahl "Person" fuellte sich aus allen Creatorn
PLUS allen Modis, sortiert nach Namen -- und der erste Name im Haus
ist "Diene", eine Modi. Ohne ausdrueckliche Wahl nimmt die Seite den
ersten. DogFather bekam also auf der Agenturadresse zuverlaessig das
Teamhaus zu sehen, und bewerten konnte er dort nichts, weil ein
Modi-Bericht nur dem Modi selbst gehoert.
DREI LAGEN UND NICHT ZWEI -- dieselbe Einteilung wie bei den
Aufgaben (workspace-aufgaben.js):
crew -> nur Rollen des Teamhauses
agentur -> nur Rollen des Agenturhauses
keine Adresse (localhost, Pruefungen) -> wie bisher, ungefiltert.
Der dritte Ausgang ist kein Schlupfloch, sondern die Bedingung
dafuer, dass die Pruefungen ueberhaupt noch etwas messen koennen --
crew-adresse.js warnt genau davor (Falle 2).
HAT_LISTE IST DIE ZWEITE HAELFTE und sie fehlte bisher ganz:
`darfCreator` sagt fuer DogFather bei JEDER Personennummer ja. Er
konnte damit einen Stand an einer Managerin, einem Scout oder an
sich selbst setzen -- fuer Punkte, die dort nie erscheinen. Eine
Liste haben genau die, fuer die ein Katalog existiert.
===================================================================== */
const HAT_LISTE = new Set(["creator", ...TEAM_DOGI_ROLLEN]);
function imSelbenHaus(person, zielRolle) {
const haus = person?.haus;
if (haus !== "crew" && haus !== "agentur") return true;
return hausVonRolle(zielRolle) === haus;
}
let bereit = false;
/* AUSGEGEBEN, seit die Eingang-Seite dieselben Tabellen liest
(10.09.2026).
@@ -201,7 +410,7 @@ function tabellen() {
bereich TEXT NOT NULL,
schluessel TEXT NOT NULL,
creator_id INTEGER NOT NULL REFERENCES personen(id) ON DELETE CASCADE,
stufe TEXT NOT NULL CHECK (stufe IN ('offen','gut','verbessern')),
stufe TEXT NOT NULL CHECK (stufe IN (${STUFEN_CHECK})),
begruendung TEXT,
von INTEGER REFERENCES personen(id) ON DELETE SET NULL,
am TEXT NOT NULL,
@@ -254,9 +463,93 @@ function tabellen() {
console.error(`[workspace] Spalte '${spalte}':`, fehler?.message);
}
}
stufenSchrankeNachziehen();
bereit = true;
}
/* =====================================================================
DIE SCHRANKE IN DER DATENBANK AN DIE KATALOGE ANGLEICHEN (24.09.2026)
Eine CHECK-Regel laesst sich in SQLite nicht aendern. Wer eine Stufe
dazunimmt, muss die Tabelle neu bauen -- und genau dabei hat dieses
Haus am 11.09.2026 drei Spalten samt Inhalt verloren, ohne
Fehlermeldung und bei unveraenderter Zeilenzahl.
DIESEN GRIFF GIBT ES SCHON, UND ZWAR GENAU EINMAL:
`checkListeErweitern` in workspace.js hat ihn seit dem 09.09.2026,
weil er damals zum dritten Mal gebraucht wurde. Er bringt fuenf
Absicherungen mit -- eine Sicherung der ganzen Datenbank davor
(VACUUM INTO), die Zeilenzaehlung INNERHALB der Transaktion, die
Spaltenliste aus PRAGMA statt aus dem Gedaechtnis, die Indizes, und
`PRAGMA foreign_key_check` danach.
ICH HATTE IHN HIER ZUERST EIN ZWEITES MAL GESCHRIEBEN. Meine Fassung
hatte die Zeilenzaehlung und die Spaltenliste, aber weder die
Sicherung davor noch die Verweispruefung danach. Sie haette
funktioniert -- und waere die naechste Stelle gewesen, an der eine
Absicherung fehlt, die anderswo laengst steht. Das ist genau die
Bauart, vor der der Kommentar an jener Funktion warnt.
WAS DIE STELLE HIER NOCH SELBST TUT: nachsehen, was danach wirklich
erlaubt ist. `checkListeErweitern` bricht bei jedem Zweifel ab und
sagt es laut -- die Tabelle bleibt dann unveraendert und voellig
brauchbar, nur mit den alten Stufen. Die Oberflaeche soll in dem Fall
ZWEI Knoepfe zeigen statt vier und keinen, der beim Druecken
scheitert. Deshalb wird die Schranke danach gelesen, nicht
vorausgesetzt. */
let stufenInDatenbank = null; /* null = noch nicht nachgesehen */
/** Welche Werte laesst `punkt_stand.stufe` gerade zu? Aus dem Bauplan
* der Tabelle gelesen -- nicht aus einer Fassungsnummer. Eine
* Fassungsnummer sagt, was gemeint war; der Bauplan sagt, was gilt. */
function erlaubteWerteLesen() {
const bauplan = db().prepare(
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'punkt_stand'").get()?.sql;
if (!bauplan) return null;
const stelle = /CHECK\s*\(\s*stufe\s+IN\s*\(([^)]*)\)/i.exec(bauplan);
if (!stelle) {
/* Keine CHECK-Regel heisst: Die Spalte ist offen, es gibt nichts
einzuschraenken. Steht "CHECK" aber darin und wir finden die
Stelle trotzdem nicht, stimmt unsere Annahme ueber den Bauplan
nicht -- dann waere Schweigen das Falsche. */
if (/CHECK/i.test(bauplan)) {
console.error("[workspace] punkt_stand: CHECK gefunden, aber die Stufenliste nicht. "
+ "Bauplan:", bauplan.replace(/\s+/g, " ").slice(0, 300));
}
return null;
}
return new Set(stelle[1].split(",").map((w) => w.trim().replace(/^'|'$/g, "")));
}
function stufenSchrankeNachziehen() {
stufenInDatenbank = erlaubteWerteLesen();
if (!stufenInDatenbank) return;
const fehlt = ALLE_STUFEN.filter((s) => !stufenInDatenbank.has(s));
if (!fehlt.length) return;
/* DER MARKER IST DIE ERSTE FEHLENDE STUFE und keine hingeschriebene.
`checkListeErweitern` erkennt daran, ob schon umgestellt wurde --
eine feste Angabe waere an dem Tag falsch, an dem eine weitere
Stufe dazukommt und die alte schon dasteht. Uebergeben wird in
jedem Fall die VOLLSTAENDIGE Liste; ein Durchgang holt alles nach. */
const stempel = new Date().toISOString().slice(0, 19).replace(/[-:T]/g, "");
checkListeErweitern(db(), "punkt_stand", "stufe", fehlt[0], ALLE_STUFEN, stempel);
/* NACHSEHEN STATT ANNEHMEN. Die Umstellung bricht bei jedem Zweifel
ab (fehlgeschlagene Sicherung, unerwarteter Bauplan, abweichende
Zeilenzahl) und sagt es auf der Protokollzeile. Wer ihr Gelingen
einfach voraussetzt, liefert danach Knoepfe aus, die der Server
annimmt und SQLite ablehnt. */
stufenInDatenbank = erlaubteWerteLesen();
const jetztFehlt = ALLE_STUFEN.filter((s) => !stufenInDatenbank?.has(s));
if (jetztFehlt.length) {
console.error("[workspace] punkt_stand: Die Stufen "
+ `${jetztFehlt.join(", ")} sind weiterhin nicht erlaubt. `
+ "Bis das behoben ist, werden sie auch nicht angeboten.");
}
}
function angemeldet(req, res, next) {
const person = sitzungLesen(req);
if (!person) return res.status(401).json({ fehler: "nicht_angemeldet" });
@@ -305,7 +598,14 @@ function creatorAus(req) {
Aus der MENGE gelesen und nicht als zwei Vergleiche hingeschrieben
-- sonst steht hier beim naechsten Mal einer zu wenig. */
if (req.person.rolle === "creator" || TEAM_DOGI_ROLLEN.has(req.person.rolle)) {
return req.person.id;
/* AUCH DIE EIGENE LISTE GEHOERT IN IHR HAUS (24.09.2026). Die
Zugangswand laesst einen Modi ohnehin nicht auf die
Agenturadresse und umgekehrt -- diese Zeile ist deshalb nicht
die erste Schranke, sondern die letzte. Zwei Sicherungen fuer
dieselbe Sache sind hier richtig: Faellt die aeussere einmal aus
(eine neue Adresse, eine vergessene Liste), stuende sonst ein
ganzes Haus offen, ohne dass irgendwo etwas rot wird. */
return imSelbenHaus(req.person, req.person.rolle) ? req.person.id : -1;
}
const id = Number(req.body?.creator_id || req.query?.creator_id) || 0;
if (!id) return 0;
@@ -320,9 +620,27 @@ function creatorAus(req) {
* Spicy Media aber nichts an; das ist die Regel des ganzen Hauses,
* und sie darf nicht ausgerechnet hier eine Ausnahme haben.
*/
/** Die Rolle einer Person -- oder `null`, wenn es sie nicht gibt.
*
* Vier Stellen brauchten dieselbe Zeile; als vierte Abschrift waere
* sie die gewesen, die beim naechsten Umbau nicht mitgeht.
*/
function rolleVon(id) {
return db().prepare("SELECT rolle FROM personen WHERE id = ?").get(Number(id))?.rolle ?? null;
}
function darfPerson(person, zielId) {
const ziel = db().prepare("SELECT id, rolle FROM personen WHERE id = ?").get(Number(zielId));
if (!ziel) return false;
/* NUR WER EINE LISTE HAT (24.09.2026). Ohne diese Zeile sagte
`darfCreator` fuer DogFather bei JEDER Nummer ja -- er konnte
einen Stand an einer Managerin, einem Scout oder an sich selbst
setzen. Die Zeile lag danach in der Datenbank und war nirgends zu
sehen, weil keine dieser Rollen eine Liste oeffnet. */
if (!HAT_LISTE.has(ziel.rolle)) return false;
/* UND NUR IM EIGENEN HAUS. Die Begruendung steht oben bei
imSelbenHaus(); hier ist die Stelle, an der sie greift. */
if (!imSelbenHaus(person, ziel.rolle)) return false;
/* Fuer die rechte Hand gilt dasselbe wie fuer einen Modi: Ihre Liste
geht Spicy Media und die Manager nichts an. Aus derselben Menge --
zwei Vergleiche waeren zwei Gelegenheiten, einen zu vergessen. */
@@ -371,10 +689,28 @@ checklisteRouter.get("/workspace/api/checkliste/:bereich", (req, res) => {
for (const z of db().prepare(
"SELECT id FROM personen WHERE rolle = 'modi' AND aktiv = 1").all()) ids.push(z.id);
}
creatoren = ids.length
? db().prepare(`SELECT id, name FROM personen
/* ==== EIN SIEB, NICHT DREI BEDINGUNGEN (24.09.2026) ===========
Oben werden Nummern aus drei Quellen zusammengetragen: alle
Creator, die betreuten, alle Modis. Die Haustrennung an jede
dieser Stellen einzeln zu schreiben waere die Bauart, die in
diesem Haus schon viermal Daten gekostet hat -- beim naechsten
Zweig fehlt sie dann an einer Stelle, und genau dort faellt es
niemandem auf.
Deshalb EIN Sieb dahinter, durch das jede Nummer muss. Es
fragt dieselbe Frage wie darfPerson(): Hat diese Person
ueberhaupt eine Liste, und steht sie in diesem Haus?
DIE ROLLE KOMMT NUR ZUM SIEBEN MIT und wird nicht
ausgeliefert -- die Auswahl selbst sieht danach aus wie
vorher, nur mit den richtigen Namen darin. */
creatoren = (ids.length
? db().prepare(`SELECT id, name, rolle FROM personen
WHERE id IN (${ids.map(() => "?").join(",")}) ORDER BY name`).all(...ids)
: [];
: [])
.filter((z) => HAT_LISTE.has(z.rolle) && imSelbenHaus(req.person, z.rolle))
.map((z) => ({ id: z.id, name: z.name }));
/* Ohne ausdrueckliche Wahl den ERSTEN nehmen. Sonst sieht ein
Betreuer beim Oeffnen eine Liste ohne Bewertungsknoepfe und
@@ -387,11 +723,25 @@ checklisteRouter.get("/workspace/api/checkliste/:bereich", (req, res) => {
const stand = {};
const nachrichten = {};
if (creatorId > 0) {
/* WER ES GESETZT HAT -- MIT ROLLE (24.09.2026).
Filipe: "die creator sollen sehen was bei ihnen passt oder
nicht mit der notiz vom manager oder scout."
Bis hierher stand am Satz nur der Name. Ob "Patrick" der
eigene Scout, die Managerin oder DogFather ist, konnte ein
Creator nur wissen, wenn er die Namen ohnehin alle kennt --
und beim ersten Monat kennt er sie nicht. Der Rollenname kommt
aus ROLLEN_NAME und nicht aus dem Browser: Eine Tabelle im
ausgelieferten Skript waere die zweite Wahrheit, die beim
naechsten Rollenwechsel auseinanderlaeuft. */
for (const z of db().prepare(`
SELECT s.*, p.name AS von_name FROM punkt_stand s
SELECT s.*, p.name AS von_name, p.rolle AS von_rolle FROM punkt_stand s
LEFT JOIN personen p ON p.id = s.von
WHERE s.bereich = ? AND s.creator_id = ?`).all(bereich, creatorId)) {
stand[z.schluessel] = z;
stand[z.schluessel] = {
...z,
von_rolle_name: z.von_rolle ? (ROLLEN_NAME[z.von_rolle] ?? null) : null,
};
delete stand[z.schluessel].von_rolle;
}
for (const z of db().prepare(`
SELECT schluessel, COUNT(*) AS n FROM punkt_nachricht
@@ -403,9 +753,7 @@ checklisteRouter.get("/workspace/api/checkliste/:bereich", (req, res) => {
/* WELCHER PUNKTESATZ? Der der Person, um die es geht -- nicht der
der Person, die zusieht. DogFather waehlt einen Modi aus und
bekommt dessen Liste, nicht die eines Creators. */
const zielRolle = creatorId > 0
? db().prepare("SELECT rolle FROM personen WHERE id = ?").get(creatorId)?.rolle
: req.person.rolle;
const zielRolle = creatorId > 0 ? rolleVon(creatorId) : req.person.rolle;
/* WELCHER KATALOG? (11.09.2026 erweitert)
Es gibt zwei Punktsaetze: den fuer Creator ("Ton geprueft") und
@@ -421,11 +769,55 @@ checklisteRouter.get("/workspace/api/checkliste/:bereich", (req, res) => {
Eingang". Beides stimmte. */
const gruppen = gruppenFuer(bereich, TEAM_DOGI_ROLLEN.has(zielRolle));
/* EINMAL AUSGERECHNET, ZWEIMAL GEBRAUCHT: fuer den Knopf und fuer
den Satz darueber. Als zweiter Ausdruck weiter unten waere es
die Sorte Abschrift, die beim naechsten Rollenzuschnitt
auseinanderlaeuft -- dann stuende in der Einleitung "markiere",
und es gaebe nichts zu druecken.
Die ausfuehrliche Begruendung steht unten bei `darf_bewerten`. */
const darfBewerten = TEAM_DOGI_ROLLEN.has(zielRolle)
? req.person.id === creatorId
: (req.person.rolle !== "creator" && !TEAM_DOGI_ROLLEN.has(req.person.rolle));
res.json({
bereich, name: liste.name,
gruppen,
stand, nachrichten,
creatoren, creator_id: creatorId > 0 ? creatorId : null,
/* =============================================================
DIE SKALA KOMMT MIT (24.09.2026)
Vier Stufen im Agenturhaus, zwei im Teamhaus -- und der
Browser baut die Knoepfe daraus, statt sie zu kennen. Stuenden
sie dort noch einmal, muesste er ausserdem wissen, WANN
welche gilt; das waere ein Rollenvergleich im ausgelieferten
Skript und damit die zweite Wahrheit ueber die Haustrennung.
Auch ein Creator bekommt sie, obwohl er nichts druecken darf:
Er braucht die Worte und die Toene, um die Marke an seinem
Punkt und die Zaehlkacheln oben zu beschriften. */
stufen: stufenFuer(zielRolle),
/* =============================================================
DER SATZ UNTER DER ÜBERSCHRIFT -- JE HAUS EIN EIGENER
(24.09.2026)
Er stand im Browser und sprach in beiden Häusern vom
"Creator": Ein Modi, der seinen eigenen Bericht schreibt, las
dort "markiere, was der Creator verbessern sollte". Auf der
Teamadresse gibt es keine Creator und wird es nie welche
geben.
DIE TEAMFASSUNG BLEIBT WORTGLEICH WIE BISHER. Das ist
Absicht: Ab dem 24.09.2026 wird jeder Umbau je Haus getrennt
geführt, und dieser hier ist der Umbau des Agenturhauses. Den
Satz des anderen Hauses nebenbei mitzuändern -- und sei es
zum Besseren -- wäre genau die Kopplung, die weg soll. Er
gehört in einen eigenen Durchgang.
Die Agenturfassung nennt dagegen die vier Stufen beim Namen,
weil ein Knopf "Trifft nicht zu" ohne ein Wort dazu wie ein
Ausweichen aussieht und nicht wie eine Antwort. */
einleitung: einleitungFuer(zielRolle, darfBewerten),
/* WIE DIE AUSWAHL HEISST. Fuer einen Manager oder Scout stehen
dort nur Creator -- "Creator" ist dann richtig. Bei der
DogFather-Rolle stehen seit dem 10.09.2026 auch Modis darin,
@@ -458,9 +850,7 @@ checklisteRouter.get("/workspace/api/checkliste/:bereich", (req, res) => {
DogFather und VanVan LESEN ihn und handeln im Eingang: Aus
"Verbessern" wird dort mit einem Klick eine Aufgabe -- oder eine
begruendete Absage, die beim Verfasser ankommt. */
darf_bewerten: TEAM_DOGI_ROLLEN.has(zielRolle)
? req.person.id === creatorId
: (req.person.rolle !== "creator" && !TEAM_DOGI_ROLLEN.has(req.person.rolle)),
darf_bewerten: darfBewerten,
ich: req.person.id,
});
} catch (fehler) {
@@ -469,6 +859,28 @@ checklisteRouter.get("/workspace/api/checkliste/:bereich", (req, res) => {
}
});
/** Der Satz unter "Feste Punkte" -- siehe die Begruendung an der
* Aufrufstelle. Vier Faelle: zwei Haeuser mal "darf druecken".
*/
function einleitungFuer(zielRolle, darf) {
if (TEAM_DOGI_ROLLEN.has(zielRolle)) {
return darf
? "Diese Punkte gelten für alle. Markiere, was gut läuft und was der "
+ "Creator noch verbessern sollte – er sieht es sofort."
: "Diese Punkte gelten für alle. Deine Betreuung markiert hier, was gut "
+ "läuft und was du noch verbessern solltest. Antworten kannst du an "
+ "jedem Punkt.";
}
return darf
? "Diese Punkte gelten für alle. Setze je Punkt, ob er passt, ob sich "
+ "etwas verbessern lässt, ob er so nicht passt – oder ob er bei "
+ "diesem Creator gar nicht vorkommt. Er sieht es sofort, samt "
+ "deiner Notiz."
: "Diese Punkte gelten für alle. Deine Betreuung setzt hier, was passt, "
+ "was sich verbessern lässt und was so nicht passt – mit einer Notiz "
+ "dazu. Antworten kannst du an jedem Punkt.";
}
/* ---------- Bewerten (NUR die Betreuung) ----------------------------------- */
checklisteRouter.put("/workspace/api/checkliste/:bereich/:schluessel", gleicheHerkunft,
@@ -479,9 +891,7 @@ checklisteRouter.put("/workspace/api/checkliste/:bereich/:schluessel", gleicheHe
/* Wessen Liste ist es? Danach entscheidet sich, wer druecken
darf -- siehe die Begruendung beim Lesen weiter oben. */
const zielId = creatorAus(req);
const zielRolle = zielId > 0
? db().prepare("SELECT rolle FROM personen WHERE id = ?").get(zielId)?.rolle
: null;
const zielRolle = zielId > 0 ? rolleVon(zielId) : null;
/* "Der eigene Bericht" heisst jetzt: eine Liste aus dem Team,
und ich bin die Person, um die es geht. Das trifft auf einen
Modi zu und seit dem 11.09.2026 ebenso auf die rechte Hand. */
@@ -513,28 +923,47 @@ checklisteRouter.put("/workspace/api/checkliste/:bereich/:schluessel", gleicheHe
}
const bereich = String(req.params.bereich);
const schluessel = String(req.params.schluessel);
if (!GUELTIG[bereich]?.has(schluessel)) {
/* DER KATALOG DES ZIELS, nicht die Vereinigung beider Haeuser
(24.09.2026) -- Begruendung oben bei GUELTIG. Ein Scout kann
damit bei einem Creator keinen Punkt mehr setzen, den nur die
Modis kennen. */
if (!gueltigerPunkt(bereich, schluessel, zielRolle)) {
return res.status(404).json({ fehler: "nicht_gefunden" });
}
const creatorId = creatorAus(req);
if (creatorId <= 0) return res.status(404).json({ fehler: "nicht_gefunden" });
/* WELCHE STUFEN HIER GELTEN, entscheidet dieselbe Frage wie beim
Lesen: Wessen Liste ist es? Im Agenturhaus vier, im Teamhaus
zwei. "Passt nicht" bei einem Modi abzulehnen ist kein
Formfehler -- dort gaebe es fuer diese Stufe keinen Empfaenger
(siehe die Begruendung bei STUFEN_CREW). */
const stufe = String(req.body.stufe || "");
if (!STUFEN.has(stufe)) return res.status(400).json({ fehler: "Unbekannte Stufe." });
const erlaubteStufen = stufenFuer(zielRolle);
const gewaehlt = erlaubteStufen.find((s) => s.schluessel === stufe);
if (stufe !== ZURUECK && !gewaehlt) {
return res.status(400).json({
fehler: `Hier gibt es diese Stufe nicht. Möglich sind: `
+ `${erlaubteStufen.map((s) => s.name).join(", ")}.`,
});
}
const grund = String(req.body.begruendung ?? "").trim().slice(0, GRUND_MAX);
/* "verbessern" ohne Grund ist fuer den Creator nicht umsetzbar --
nur entmutigend. */
if (stufe === "verbessern" && grund.length < 5) {
/* Ein Urteil ohne Satz ist fuer den, der es liest, nicht
umsetzbar -- nur entmutigend. WELCHE Stufen einen Satz
brauchen, steht im Katalog und nicht hier: Stuende es hier,
waere die naechste Stufe die, bei der es jemand vergisst. */
if (gewaehlt?.grund === "pflicht" && grund.length < GRUND_MIN) {
return res.status(400).json({
fehler: "Bitte kurz schreiben, was verbessert werden soll – sonst kann er nichts damit anfangen.",
fehler: `${gewaehlt.frage} Ohne diesen Satz kann der andere `
+ "nichts damit anfangen.",
});
}
/* "offen" heisst: zurueck auf Anfang. Dann wird der Stand
geloescht statt auf "offen" gesetzt -- ein Datensatz, der nichts
aussagt, ist Ballast. */
if (stufe === "offen") {
if (stufe === ZURUECK) {
/* Auch der Vermerk faellt mit -- eine neu gesetzte Stufe ist
eine neue Meldung, keine schon behandelte. */
db().prepare("DELETE FROM punkt_stand WHERE bereich = ? AND schluessel = ? AND creator_id = ?")
@@ -576,9 +1005,14 @@ checklisteRouter.get("/workspace/api/checkliste/:bereich/:schluessel/nachrichten
try {
const bereich = String(req.params.bereich);
const schluessel = String(req.params.schluessel);
if (!GUELTIG[bereich]?.has(schluessel)) return res.status(404).json({ fehler: "nicht_gefunden" });
/* ERST WESSEN LISTE, DANN OB ES DEN PUNKT DARIN GIBT. Die
Reihenfolge ist keine Kosmetik: Der gueltige Schluessel haengt
am Katalog der Person, um die es geht. */
const creatorId = creatorAus(req);
if (creatorId <= 0) return res.status(404).json({ fehler: "nicht_gefunden" });
if (!gueltigerPunkt(bereich, schluessel, rolleVon(creatorId))) {
return res.status(404).json({ fehler: "nicht_gefunden" });
}
const nachrichten = db().prepare(`
SELECT n.*, p.name AS von_name, p.rolle AS von_rolle
@@ -597,9 +1031,11 @@ checklisteRouter.post("/workspace/api/checkliste/:bereich/:schluessel/nachrichte
try {
const bereich = String(req.params.bereich);
const schluessel = String(req.params.schluessel);
if (!GUELTIG[bereich]?.has(schluessel)) return res.status(404).json({ fehler: "nicht_gefunden" });
const creatorId = creatorAus(req);
if (creatorId <= 0) return res.status(404).json({ fehler: "nicht_gefunden" });
if (!gueltigerPunkt(bereich, schluessel, rolleVon(creatorId))) {
return res.status(404).json({ fehler: "nicht_gefunden" });
}
const text = String(req.body.text ?? "").trim();
if (text.length < 2) return res.status(400).json({ fehler: "Die Nachricht ist leer." });
@@ -630,11 +1066,18 @@ checklisteRouter.delete("/workspace/api/checkliste/nachricht/:id(\\d+)", gleiche
const n = db().prepare("SELECT * FROM punkt_nachricht WHERE id = ?").get(Number(req.params.id));
if (!n) return res.status(404).json({ fehler: "nicht_gefunden" });
/* Erst pruefen, ob die Person den Creator ueberhaupt sehen darf --
sonst verraet die Antwort, dass es die Nachricht gibt. */
const erlaubt = req.person.rolle === "creator"
? n.creator_id === req.person.id
: darfCreator(req.person, n.creator_id);
if (!erlaubt) return res.status(404).json({ fehler: "nicht_gefunden" });
sonst verraet die Antwort, dass es die Nachricht gibt.
SEIT 24.09.2026 UEBER darfPerson() und nicht mehr ueber
darfCreator(). Der Unterschied ist die Haustrennung: Hier
stand ein Sonderfall fuer die Creator-Rolle und darunter die
allgemeine Regel, die fuer DogFather bei JEDER Nummer ja sagt
-- auf der Agenturadresse also auch fuer eine Nachricht aus
dem Teamhaus. darfPerson beantwortet beides an einer Stelle,
den Creator-Fall eingeschlossen. */
if (!darfPerson(req.person, n.creator_id)) {
return res.status(404).json({ fehler: "nicht_gefunden" });
}
if (n.von !== req.person.id) {
return res.status(403).json({
fehler: "Fremde Nachrichten bleiben stehen. Schreib eine neue, wenn etwas richtigzustellen ist.",
+18 -2
View File
@@ -32,6 +32,7 @@ import { sichtbar as sichtbarAufgaben } from "./workspace-aufgaben.js";
import { sichtbar as sichtbarTermine } from "./workspace-kalender.js";
import { sichtbar as sichtbarDateien } from "./workspace-dateien.js";
import { sichtbar as sichtbarEintraege } from "./workspace-bereiche.js";
import { stufenFuer } from "./workspace-checkliste.js";
export const hinweisRouter = express.Router();
@@ -248,6 +249,9 @@ hinweisRouter.get("/workspace/api/hinweise", (req, res) => {
gemeint sind. Ein Sammelhinweis "6 markierte Punkte" liesse offen,
wo man nachsehen soll. */
if (person.rolle === "creator") {
/* Aus dem Katalog des Agenturhauses abgeleitet -- ein Creator
wohnt dort und nirgends sonst. */
const MARKIERT = stufenFuer("creator").filter((s) => s.merk).map((s) => s.schluessel);
const BEREICHE = [
["live", "LIVE-Analyse", "bereich.html?b=live"],
["content", "Content-Ideen", "content.html"],
@@ -260,9 +264,21 @@ hinweisRouter.get("/workspace/api/hinweise", (req, res) => {
/* zaehle() faengt Fehler ab -- gibt es die Tabelle noch nicht
(niemand hat je eine Checkliste geoeffnet), steht hier 0
statt eines Ausfalls der ganzen Uebersicht. */
/* WELCHE STUFEN HIER ZAEHLEN, sagt der Katalog und nicht
diese Zeile (24.09.2026). Hier stand `stufe = 'verbessern'`
-- eine abgeschriebene Liste mit genau einem Eintrag.
Am Tag, an dem "Passt nicht" dazukam, waere die staerkste
Rueckmeldung, die es gibt, als Einzige NICHT auf der
Startseite erschienen: Der Creator saehe ein ruhiges
Kaestchen, waehrend sein Scout auf etwas wartet. Genau
die Sorte Luecke, die nicht falsch aussieht, sondern
gar nicht aussieht.
`merk` traegt dieselbe Bedeutung wie am Punkt selbst und
am Gruppenkopf: "hier wartet etwas auf dich". */
zaehle(`SELECT COUNT(*) n FROM punkt_stand
WHERE bereich = ? AND creator_id = ? AND stufe = 'verbessern'`,
[schluessel, person.id]));
WHERE bereich = ? AND creator_id = ? AND stufe IN (${MARKIERT.map(() => "?").join(",")})`,
[schluessel, person.id, ...MARKIERT]));
}
}
+9 -1
View File
@@ -2850,7 +2850,15 @@ let _dbFehler = null;
@param marker Die Rolle, an der erkannt wird, ob schon umgestellt ist.
@param rollen Die vollstaendige neue Liste erlaubter Rollen.
===================================================================== */
function checkListeErweitern(d, tabelle, spalte, marker, werte, jetztStempel) {
/* AUSGEGEBEN SEIT DEM 24.09.2026. Die Checkliste brauchte denselben
Griff fuer `punkt_stand.stufe`, und ich hatte ihn dort schon ein
zweites Mal hingeschrieben -- mit der Zeilenzaehlung und der
Spaltenliste aus PRAGMA, aber OHNE die Sicherung davor, ohne die
Indizes und ohne die Pruefung auf verwaiste Verweise danach. Drei
von fuenf Absicherungen fehlten, und keine davon haette gefehlt,
wenn ich die vorhandene Funktion benutzt haette.
Genau davor warnt der Absatz "WARUM ALS FUNKTION" oben. */
export function checkListeErweitern(d, tabelle, spalte, marker, werte, jetztStempel) {
const rollenPlan = d.prepare(
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?").get(tabelle)?.sql || "";
/* DOPPELTE BACKSLASHES, und das ist kein Schoenheitsfehler:
+5 -5
View File
@@ -16,15 +16,15 @@
verdeckt. Gefunden hat es pruef-struktur.
Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. -->
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
<!-- Ohne diese drei nimmt ein iPhone einen Bildschirmausschnitt als
Symbol, Android zeichnet die Leiste weiss, und die Seite oeffnet
ausserhalb der App -- auf einer Seite, die genau erklaeren soll,
WARUM das Telefon nicht klingelt, ist das besonders unpassend. -->
<link rel="manifest" href="/workspace/crew.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<style>
/* Bewusst in der Seite und nicht in einer eigenen Datei: Diese Seite
soll auch dann noch etwas anzeigen, wenn genau das schiefgeht,
@@ -126,7 +126,7 @@
<script src="assets/js/anruf-probe.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/anruf-probe.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
</body>
</html>
+4 -4
View File
@@ -23,25 +23,25 @@
},
"icons": [
{
"src": "/assets/img/app-symbole/workspace-192.png?v=202609242039",
"src": "/assets/img/app-symbole/workspace-192.png?v=202609242347",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/workspace-512.png?v=202609242039",
"src": "/assets/img/app-symbole/workspace-512.png?v=202609242347",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609242039",
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609242347",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609242039",
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609242347",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
+53 -15
View File
@@ -3375,9 +3375,22 @@ body.start #protokoll {
linear-gradient(180deg, color-mix(in srgb, var(--b-ton) 9%, transparent), transparent 60%),
var(--flaeche);
}
.bilanz-zahl[data-stufe="gut"] { --b-ton: #4dab77; }
.bilanz-zahl[data-stufe="verbessern"] { --b-ton: #e0a33c; }
.bilanz-zahl[data-stufe="offen"] { --b-ton: #6f89a8; }
.bilanz-zahl[data-stufe="gut"] { --b-ton: #4dab77; }
.bilanz-zahl[data-stufe="verbessern"] { --b-ton: #e0a33c; }
/* "Passt nicht" (24.09.2026, nur im Agenturhaus). Gerechnet und nicht
gegriffen: relative Helligkeit 0,317 -- genau so hell wie das Gruen
daneben (0,320) und deutlich heller als das Blaugrau von "offen"
(0,241), das den Barrierefreiheits-Lauf bereits bestanden hat. Ein
knalliges Rot waere lauter, aber nicht lesbarer; die Bedeutung
traegt ohnehin das Wort auf der Marke und die Raute daneben, nicht
der Farbton. */
.bilanz-zahl[data-stufe="passt_nicht"] { --b-ton: #d97f87; }
/* "Trifft nicht zu" soll RUHIGER wirken als "offen" und trotzdem
lesbar sein -- das ist ein Widerspruch, solange man nur abdunkelt.
Geloest ueber die Saettigung: fast neutral (0,274), aber heller als
"offen". Es faellt damit nicht auf und verschwindet nicht. */
.bilanz-zahl[data-stufe="entfaellt"] { --b-ton: #8a8f9b; }
.bilanz-zahl[data-stufe="offen"] { --b-ton: #6f89a8; }
.bilanz-zahl__n {
font-size: 1.6rem; font-weight: 700; line-height: 1;
color: var(--b-ton); font-variant-numeric: tabular-nums;
@@ -3581,11 +3594,18 @@ body.start #protokoll {
background: linear-gradient(180deg, var(--p-ton),
color-mix(in srgb, var(--p-ton) 30%, transparent));
}
.fest-punkt[data-stufe="gut"] { --p-ton: #4dab77; }
.fest-punkt[data-stufe="gut"] { --p-ton: #4dab77; }
/* Warnend, nicht rot: Es ist eine Aufgabe, kein Fehler. Rot waere eine
Beschuldigung. */
.fest-punkt[data-stufe="verbessern"] { --p-ton: #e0a33c; }
.fest-punkt[data-stufe="offen"] { --p-ton: #6f89a8; }
.fest-punkt[data-stufe="verbessern"] { --p-ton: #e0a33c; }
/* UND "Passt nicht"? Auch kein Rot -- aus demselben Grund, nur eine
Stufe deutlicher. Ein gedaempftes Rosé sagt "das gehoert geaendert",
ein Signalrot sagt "du hast versagt". Der Unterschied zwischen den
beiden Saetzen ist der ganze Grund, warum es diese Stufe gibt.
Der Farbwert ist gerechnet, siehe .bilanz-zahl weiter oben. */
.fest-punkt[data-stufe="passt_nicht"] { --p-ton: #d97f87; }
.fest-punkt[data-stufe="entfaellt"] { --p-ton: #8a8f9b; }
.fest-punkt[data-stufe="offen"] { --p-ton: #6f89a8; }
.fest-punkt__kopf {
display: flex; align-items: flex-start; justify-content: space-between;
@@ -3658,15 +3678,33 @@ body.start #protokoll {
font: inherit; font-size: .8rem; cursor: pointer;
transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.stufe-knopf[data-stufe="gut"]:hover,
.stufe-knopf[data-stufe="gut"][data-an="ja"] {
border-color: rgba(77, 171, 119, .5); color: #6fbd95;
background: rgba(77, 171, 119, .13);
}
.stufe-knopf[data-stufe="verbessern"]:hover,
.stufe-knopf[data-stufe="verbessern"][data-an="ja"] {
border-color: rgba(224, 163, 60, .5); color: #e0b45c;
background: rgba(224, 163, 60, .13);
/* ---------- Die Stufenknoepfe ------------------------------------------
EINE ZEILE JE STUFE STATT DREI (24.09.2026).
Hier standen je Stufe drei ausgerechnete Farbwerte -- Rand, Schrift,
Flaeche. Bei zwei Stufen ging das; bei vier waeren es zwoelf Werte,
und beim naechsten Knopf haette jemand einen davon vergessen. Genau
diese Bauart hat in diesem Haus schon mehrfach zu einer Stelle
gefuehrt, die nicht mitgewachsen ist, ohne dass etwas auffaellt.
Jetzt nennt jede Stufe nur noch IHREN Ton; die drei Werte rechnet
der Browser daraus. Eine Stufe, die es morgen gibt und die hier
fehlt, sieht dadurch neutral aus statt kaputt -- die Rueckfallwerte
stehen im gemeinsamen Block.
AUSDRUECKLICH AUF [data-stufe] EINGEGRENZT: Dieselbe Klasse
.stufe-knopf benutzt auch die Ampel an den Eintraegen, dort aber mit
[data-wert]. Ein Regelsatz ohne diese Eingrenzung faerbte sie mit
und niemand saehe einen Zusammenhang. */
.stufe-knopf[data-stufe="gut"] { --s-ton: #4dab77; }
.stufe-knopf[data-stufe="verbessern"] { --s-ton: #e0a33c; }
.stufe-knopf[data-stufe="passt_nicht"] { --s-ton: #d97f87; }
.stufe-knopf[data-stufe="entfaellt"] { --s-ton: #8a8f9b; }
.stufe-knopf[data-stufe]:hover,
.stufe-knopf[data-stufe][data-an="ja"] {
border-color: color-mix(in srgb, var(--s-ton, var(--text-still)) 50%, transparent);
color: color-mix(in srgb, var(--s-ton, var(--text-still)) 79%, #ffffff);
background: color-mix(in srgb, var(--s-ton, var(--text-still)) 13%, transparent);
}
.fest-punkt__fuss .schritt { margin-left: auto; }
+115 -43
View File
@@ -10,10 +10,19 @@
Jetzt: dieselben Punkte für alle, gruppiert. Was sich unterscheidet,
ist der STAND je Creator -- und den setzt die Betreuung.
Drei Zustände, drei Farben:
offen noch nicht angesehen
gut passt so
verbessern mit dem Satz, WAS zu verbessern ist
WIE VIELE ZUSTÄNDE ES GIBT, WEISS DIESE DATEI NICHT (24.09.2026).
Sie standen hier als feste Liste: offen, gut, verbessern. Seit im
Agenturhaus vier Stufen gelten und im Teamhaus zwei, wäre jede feste
Liste hier die zweite Wahrheit -- und sie müsste zusätzlich wissen,
WANN welche gilt. Das wäre ein Rollenvergleich in einer Datei, die
jeder herunterladen kann, und beim nächsten Rollenzuschnitt liefe er
auseinander.
Deshalb kommen die Stufen mit der Antwort (`daten.stufen`): Wort,
Farbton, ob ein Satz Pflicht ist, ob sie in die Bilanz zählt. Diese
Datei baut daraus Knöpfe, Marken und Kacheln -- und kennt keine
einzige davon beim Namen.
Der Creator sieht alles, kann aber nichts davon setzen. Antworten
kann er -- über die Nachrichten an jedem Punkt.
@@ -123,13 +132,14 @@
dass ein neuer Block begonnen hat.
Jetzt: h1 Seite -> h2 "Feste Punkte" -> h3 Gruppe -> h4 Punkt. */
t.append(el('h2', 'feldschild', 'Feste Punkte'));
t.append(el('p', 'liste-fest__unter',
daten.darf_bewerten
? 'Diese Punkte gelten für alle. Markiere, was gut läuft und was der '
+ 'Creator noch verbessern sollte – er sieht es sofort.'
: 'Diese Punkte gelten für alle. Deine Betreuung markiert hier, was gut '
+ 'läuft und was du noch verbessern solltest. Antworten kannst du an '
+ 'jedem Punkt.'));
/* DER SATZ KOMMT VOM SERVER (24.09.2026). Er stand hier und sprach
in beiden Häusern vom "Creator" -- auf der Teamadresse gibt es
aber keine. Die vier Fassungen (zwei Häuser mal "darf drücken")
stehen jetzt dort, wo auch die Stufen stehen. Fehlt das Feld,
bleibt die Zeile leer statt falsch. */
if (daten.einleitung) {
t.append(el('p', 'liste-fest__unter', daten.einleitung));
}
kopf.append(t);
if (daten.darf_bewerten && daten.creatoren.length) {
@@ -168,16 +178,34 @@
block.append(kopf);
/* ---- Fortschritt in einer Zeile ----
Wie viele Punkte sind angesehen, wie viele stehen auf "noch
verbessern"? Das ist die Frage, die beide zuerst haben. */
Wie viele Punkte passen, wie viele warten auf etwas, wie viele
hat noch niemand angesehen? Das ist die Frage, die beide zuerst
haben -- deshalb steht sie vor der Liste.
EINE KACHEL JE STUFE, aus `daten.stufen` gebaut. Eine Stufe mit
`still` erscheint erst, wenn sie vorkommt: "0 trifft nicht zu"
über jeder Liste wäre eine Auskunft, die niemand gesucht hat.
FEHLT `daten.stufen`, wird hier NICHTS erfunden. Eine
hilfsweise eigene Liste wäre genau die zweite Wahrheit, gegen
die diese Umstellung gebaut ist -- und sie zeigte Knöpfe, die
der Server danach mit 400 abweist. Dann lieber keine Knöpfe:
Die Punkte und die Rückmeldungen stehen weiterhin da. */
const stufen = Array.isArray(daten.stufen) ? daten.stufen : [];
const alle = daten.gruppen.flatMap((g) => g.punkte);
const zuTun = alle.filter((p) => daten.stand[p.schluessel]?.stufe === 'verbessern').length;
const gut = alle.filter((p) => daten.stand[p.schluessel]?.stufe === 'gut').length;
const standVon = (p) => daten.stand[p.schluessel]?.stufe || 'offen';
const MERK = new Set(stufen.filter((s) => s.merk).map((s) => s.schluessel));
const zuTun = alle.filter((p) => MERK.has(standVon(p))).length;
const bewertet = alle.filter(
(p) => stufen.some((s) => s.schluessel === standVon(p))).length;
if (daten.creator_id || !daten.darf_bewerten) {
const bilanz = el('div', 'liste-fest__bilanz');
bilanz.append(zahl(gut, 'passt so', 'gut'));
bilanz.append(zahl(zuTun, 'zu verbessern', 'verbessern'));
bilanz.append(zahl(alle.length - gut - zuTun, 'noch offen', 'offen'));
for (const s of stufen) {
const n = alle.filter((p) => standVon(p) === s.schluessel).length;
if (s.still && !n) continue;
bilanz.append(zahl(n, s.bilanz, s.schluessel));
}
bilanz.append(zahl(alle.length - bewertet, 'noch offen', 'offen'));
block.append(bilanz);
}
@@ -223,8 +251,12 @@
for (const g of daten.gruppen) {
const abschnitt = el('section', 'fest-gruppe');
const offenZahl = g.punkte
.filter((p) => daten.stand[p.schluessel]?.stufe === 'verbessern').length;
/* Was am Gruppenkopf als Raute erscheint: alle Stufen, die der
Server als `merk` liefert. Bis zum 24.09.2026 stand hier fest
'verbessern' -- ein "Passt nicht" wäre damit hinter einer
zugeklappten Gruppe unsichtbar geblieben, und zwar
ausgerechnet die stärkste Rückmeldung, die es gibt. */
const offenZahl = g.punkte.filter((p) => MERK.has(standVon(p))).length;
if (offenZahl) markierte.push(g.schluessel);
/* Der Kopf ist ein KNOPF, nicht eine Überschrift mit einem Knopf
@@ -263,7 +295,7 @@
? g.punkte.filter((p) => p.stufe === gefiltert)
: g.punkte;
for (const p of sichtbar) {
liste.append(punktBauen(p, daten, bereich, behaelter));
liste.append(punktBauen(p, daten, bereich, behaelter, stufen, MERK));
}
/* Eine Gruppe, in der der Filter nichts uebrig laesst, sagt das --
statt leer dazustehen. Ein leerer Kasten liest sich wie ein
@@ -291,7 +323,14 @@
/* Die Zahl "zu verbessern" wird zum Weg dorthin. Eine Zahl, die einen
auf etwas hinweist, das man dann selbst suchen muss, ist eine
halbe Auskunft. */
const bilanzKnopf = block.querySelector('.bilanz-zahl[data-stufe="verbessern"]');
/* Der Sprung hängt an der ERSTEN markierten Stufe, die es hier
gibt -- im Agenturhaus "zu verbessern", und wenn es sie einmal
nicht gäbe, eben an der nächsten. Ein fest verdrahtetes
'verbessern' wäre im Teamhaus richtig und beim nächsten Katalog
ein toter Selektor, ohne dass etwas rot wird. */
const sprungStufe = stufen.find((s) => s.merk)?.schluessel;
const bilanzKnopf = sprungStufe
? block.querySelector(`.bilanz-zahl[data-stufe="${sprungStufe}"]`) : null;
if (bilanzKnopf && zuTun > 0 && markierte.length) {
bilanzKnopf.dataset.klickbar = 'ja';
bilanzKnopf.setAttribute('role', 'button');
@@ -359,9 +398,13 @@
return k;
}
function punktBauen(p, daten, bereich, behaelter) {
function punktBauen(p, daten, bereich, behaelter, stufen, MERK) {
const stand = daten.stand[p.schluessel];
const stufe = stand?.stufe || 'offen';
/* Die Beschreibung der gesetzten Stufe -- oder nichts, wenn der
Punkt offen ist. Beides kommt vom Server; hier steht kein
einziger Stufenname. */
const gesetzt = stufen.find((s) => s.schluessel === stufe) || null;
const k = el('article', 'fest-punkt');
k.dataset.stufe = stufe;
@@ -408,10 +451,8 @@
gesehen hat, erkennt hier wieder, was gemeint war -- ohne den Text
lesen zu müssen. */
const rechts = el('div', 'fest-punkt__stufe');
if (stufe === 'verbessern') rechts.append(window.Bereiche.merkzeichenBauen(0, 'merk'));
rechts.append(el('span', 'fest-punkt__marke-stufe',
stufe === 'gut' ? 'Passt so'
: stufe === 'verbessern' ? 'Verbessern' : 'Offen'));
if (MERK.has(stufe)) rechts.append(window.Bereiche.merkzeichenBauen(0, 'merk'));
rechts.append(el('span', 'fest-punkt__marke-stufe', gesetzt ? gesetzt.name : 'Offen'));
kopf.append(rechts);
k.append(kopf);
@@ -420,8 +461,16 @@
if (stand?.begruendung) {
const g = el('div', 'fest-punkt__grund');
g.append(el('p', null, stand.begruendung));
/* WER ES GESAGT HAT, MIT ROLLE (24.09.2026). Filipe: "die
creator sollen sehen was bei ihnen passt oder nicht mit der
notiz vom manager oder scout." Bis hierher stand dort nur ein
Vorname. Ob "Patrick" der eigene Scout ist, die Managerin oder
DogFather, weiß nur, wer die Namen ohnehin alle kennt -- und im
ersten Monat kennt man sie nicht. Der Rollenname kommt vom
Server; hier steht keine Rollentabelle. */
const wer = [stand.von_name, stand.von_rolle_name].filter(Boolean).join(', ');
g.append(el('span', 'fest-punkt__von',
`${stand.von_name || ''} · ${wann(stand.am)}`));
`${wer}${wer ? ' · ' : ''}${wann(stand.am)}`));
k.append(g);
}
@@ -429,28 +478,51 @@
const fuss = el('div', 'fest-punkt__fuss');
if (daten.darf_bewerten && daten.creator_id) {
for (const [wert, name] of [['gut', 'Passt so'], ['verbessern', 'Verbessern']]) {
const b = el('button', 'stufe-knopf', name);
for (const s of stufen) {
const b = el('button', 'stufe-knopf', s.name);
b.type = 'button';
b.dataset.stufe = wert;
if (stufe === wert) b.dataset.an = 'ja';
b.dataset.stufe = s.schluessel;
const an = stufe === s.schluessel;
if (an) b.dataset.an = 'ja';
/* EINE GEDRÜCKTE GRUPPE, KEIN NAMENLOSER KNOPF (24.09.2026).
Mit zwei Knöpfen konnte man die Farbe noch als Auskunft
durchgehen lassen; mit vieren nicht mehr. `aria-pressed`
sagt einem Vorleseprogramm, dass hier EINE von mehreren
Möglichkeiten gewählt ist -- und welche. Ohne das hört man
viermal "Knopf" und erfährt nie, was gerade gilt.
Der Titel nennt zusätzlich die Rücknahme: Dass ein zweiter
Klick auf dieselbe Stufe sie aufhebt, sieht man ihr sonst
nicht an. */
b.setAttribute('aria-pressed', an ? 'true' : 'false');
if (an) b.title = `Noch einmal drücken nimmt „${s.name}“ zurück.`;
b.addEventListener('click', async () => {
/* Ein zweiter Klick auf dieselbe Stufe nimmt sie zurück --
sonst gäbe es keinen Weg zurück auf "offen". */
const neu = stufe === wert ? 'offen' : wert;
let grund = stand?.begruendung || '';
if (neu === 'verbessern') {
const neu = an ? 'offen' : s.schluessel;
let grund = '';
/* GEFRAGT WIRD, WENN DIE STUFE EINE FRAGE MITBRINGT. Welche
das sind, entscheidet der Server (siehe `frage` im
Katalog): alles, was der andere verstehen oder tun muss.
"Passt" bringt keine mit und wird mit einem Klick gesetzt
-- es ist der häufigste Klick einer Betreuung, die vierzig
Punkte durchgeht. */
if (neu !== 'offen' && s.frage) {
const pflicht = s.grund === 'pflicht';
const ag = await frageNach({
titel: `„${p.titel}" – noch verbessern`,
was: 'Dein Satz steht danach an diesem Punkt.',
bleibt: 'Der Punkt bleibt offen und kann jederzeit wieder '
+ 'auf „in Ordnung" gesetzt werden.',
ja: 'Zurückgeben',
grund: 'Was genau soll verbessert werden?', grundPflicht: true,
platzhalter: 'z. B. Fehlt noch das Impressum unten auf der Seite.',
titel: `„${p.titel}“ – ${s.name}`,
was: pflicht
? 'Dein Satz steht danach an diesem Punkt. Er ist das, '
+ 'womit weitergearbeitet wird.'
: 'Dein Satz steht danach an diesem Punkt. Du kannst ihn '
+ 'auch weglassen.',
bleibt: 'Die Bewertung lässt sich jederzeit ändern oder '
+ 'ganz zurücknehmen.',
ja: s.name,
grund: s.frage, grundPflicht: pflicht, grundMin: 5,
platzhalter: s.platzhalter || '',
});
if (!ag) return;
grund = ag.grund;
grund = ag.grund || '';
}
b.disabled = true;
try {
+19 -19
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -391,22 +391,22 @@
<!-- TEXTFORM ZUERST (21.09.2026): Die Seite fragt beim Zeichnen nach
`window.Textform`. Kaeme sie spaeter, waere der erste Eintrag ohne
Gestaltung. Kein `defer`, damit sie wirklich vorher dasteht. -->
<script src="assets/js/textform.js?v=202609242039"></script>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/hochladen.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/textform.js?v=202609242347"></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/hochladen.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/zuteilung.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/zuteilung.js?v=202609242347" defer></script>
<!-- Der Vorlagenkatalog stand bis zum 23.09.2026 mitten in
aufgaben.js. Er bedient jetzt zwei Seiten und hat deshalb eine
eigene Datei; hier zeigt er den Creator-Katalog.
Vor aufgaben.js, weil die Seite ihn beim Start einrichtet. -->
<script src="assets/js/vorlagenbrett.js?v=202609242039" defer></script>
<script src="assets/js/aufgaben.js?v=202609242039" defer></script>
<script src="assets/js/vorlagenbrett.js?v=202609242347" defer></script>
<script src="assets/js/aufgaben.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/automation.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/automation.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -168,15 +168,15 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/automation.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/automation.js?v=202609242347" defer></script>
</body>
</html>
+17 -17
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -197,16 +197,16 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/befinden.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<script src="assets/js/befinden.js?v=202609242347" defer></script>
</body>
</html>
+22 -22
View File
@@ -12,24 +12,24 @@
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609242347" />
<!-- Wegen des Blocks „Willst du dazugehoeren?" auf dem Brett
„Mitmachen". Eine eigene Kopie der Regel hier waere die zweite
Stelle, an der dieselbe Sache anders aussieht. -->
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -304,19 +304,19 @@
<!-- TEXTFORM ZUERST (21.09.2026): Die Seite fragt beim Zeichnen nach
`window.Textform`. Kaeme sie spaeter, waere der erste Eintrag ohne
Gestaltung. Kein `defer`, damit sie wirklich vorher dasteht. -->
<script src="assets/js/textform.js?v=202609242039"></script>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/textform.js?v=202609242347"></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/checkliste.js?v=202609242039" defer></script>
<script src="assets/js/ampel.js?v=202609242039" defer></script>
<script src="assets/js/schulung.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/bereich.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/checkliste.js?v=202609242347" defer></script>
<script src="assets/js/ampel.js?v=202609242347" defer></script>
<script src="assets/js/schulung.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<script src="assets/js/bereich.js?v=202609242347" defer></script>
</body>
</html>
+19 -19
View File
@@ -7,17 +7,17 @@
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -108,15 +108,15 @@
</main>
<!-- Der Fuß gehört zu jeder Seite - siehe pruef-css-klassen. -->
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/auskunft.js?v=202609242039" defer></script>
<script src="assets/js/bewerben.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/auskunft.js?v=202609242347" defer></script>
<script src="assets/js/bewerben.js?v=202609242347" defer></script>
</body>
</html>
+18 -18
View File
@@ -7,16 +7,16 @@
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -80,16 +80,16 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/auskunft.js?v=202609242039" defer></script>
<script src="assets/js/bewerbungen.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/auskunft.js?v=202609242347" defer></script>
<script src="assets/js/bewerbungen.js?v=202609242347" defer></script>
</body>
</html>
+17 -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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/calls.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/calls.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -89,15 +89,15 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/ki.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/calls.js?v=202609242039" defer></script>
<script src="assets/js/ki.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/calls.js?v=202609242347" defer></script>
</body>
</html>
+19 -19
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/chat.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/chat.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -619,25 +619,25 @@
</form>
</dialog>
<script src="assets/js/bereiche.js?v=202609242039"></script>
<script src="assets/js/bereiche.js?v=202609242347"></script>
<!-- TEXTFORM VOR ALLEM ANDEREN (21.09.2026): chat.js und bereich.js
fragen beim Zeichnen nach `window.Textform`. Kaeme sie spaeter,
waere die erste gezeichnete Nachricht ohne Gestaltung -- und das
faellt nur dem auf, der genau hinsieht. KEIN `defer`, damit sie
wirklich vor den anderen dasteht. -->
<script src="assets/js/textform.js?v=202609242039"></script>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/hochladen.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039"></script>
<script src="assets/js/glocke.js?v=202609242039"></script>
<script src="assets/js/textform.js?v=202609242347"></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/hochladen.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347"></script>
<script src="assets/js/glocke.js?v=202609242347"></script>
<!-- ANRUF VOR CHAT (18.09.2026): anruf.js stellt `window.anrufStarten`
bereit, und chat.js baut die Knoepfe nur, wenn es das gibt.
Andersherum waere die Reihenfolge eine stille Abhaengigkeit --
die Knoepfe fehlten, und niemand wuesste warum. -->
<script src="assets/js/anruf.js?v=202609242039"></script>
<script src="assets/js/chat.js?v=202609242039"></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/anruf.js?v=202609242347"></script>
<script src="assets/js/chat.js?v=202609242347"></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
</body>
</html>
+17 -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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/content.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/content.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -179,15 +179,15 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/checkliste.js?v=202609242039" defer></script>
<script src="assets/js/content.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/checkliste.js?v=202609242347" defer></script>
<script src="assets/js/content.js?v=202609242347" defer></script>
</body>
</html>
+6 -6
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/crew-haus.css?v=202609242347" />
</head>
<body class="gate gate--crew">
@@ -459,7 +459,7 @@
<script src="assets/js/gate.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/gate.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
</body>
</html>
+4 -4
View File
@@ -23,25 +23,25 @@
},
"icons": [
{
"src": "/assets/img/app-symbole/crew-192.png?v=202609242039",
"src": "/assets/img/app-symbole/crew-192.png?v=202609242347",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/crew-512.png?v=202609242039",
"src": "/assets/img/app-symbole/crew-512.png?v=202609242347",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609242039",
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609242347",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609242039",
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609242347",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
+17 -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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/dateien.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/dateien.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -108,15 +108,15 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/hochladen.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/hochladen.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/dateien.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/dateien.js?v=202609242347" defer></script>
</body>
</html>
+18 -18
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -297,20 +297,20 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<!-- VOR entwicklung.js: Die Seite richtet den Katalog beim Start ein,
also muss es ihn zu dem Zeitpunkt geben. Mit "defer" laufen beide
in Dokumentreihenfolge. -->
<script src="assets/js/vorlagenbrett.js?v=202609242039" defer></script>
<script src="assets/js/entwicklung.js?v=202609242039" defer></script>
<script src="assets/js/vorlagenbrett.js?v=202609242347" defer></script>
<script src="assets/js/entwicklung.js?v=202609242347" defer></script>
</body>
</html>
+15 -15
View File
@@ -7,13 +7,13 @@
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/hilfe.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/hilfe.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -146,14 +146,14 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/hilfe.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/hilfe.js?v=202609242347" defer></script>
</body>
</html>
+5 -5
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
</head>
<body class="gate">
@@ -427,7 +427,7 @@
<script src="assets/js/gate.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/gate.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
</body>
</html>
+17 -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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/kalender.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/kalender.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -383,15 +383,15 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/kalender.js?v=202609242039" defer></script>
<script src="assets/js/kalender-abo.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/kalender.js?v=202609242347" defer></script>
<script src="assets/js/kalender-abo.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/leistung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/leistung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -444,13 +444,13 @@
</form>
</dialog>
<script src="assets/js/meldung.js?v=202609242039"></script>
<script src="assets/js/nachfrage.js?v=202609242039"></script>
<script src="assets/js/wahl.js?v=202609242039"></script>
<script src="assets/js/bereiche.js?v=202609242039"></script>
<script src="assets/js/kopf.js?v=202609242039"></script>
<script src="assets/js/glocke.js?v=202609242039"></script>
<script src="assets/js/leistung.js?v=202609242039"></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347"></script>
<script src="assets/js/nachfrage.js?v=202609242347"></script>
<script src="assets/js/wahl.js?v=202609242347"></script>
<script src="assets/js/bereiche.js?v=202609242347"></script>
<script src="assets/js/kopf.js?v=202609242347"></script>
<script src="assets/js/glocke.js?v=202609242347"></script>
<script src="assets/js/leistung.js?v=202609242347"></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
View File
@@ -12,13 +12,13 @@
vergessen wird. -->
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/material.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/material.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start" data-ton="42" data-buehne="studio">
@@ -138,14 +138,14 @@
<p class="m-laedt" id="laedt">Einen Moment …</p>
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/hochladen.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/material.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/hochladen.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/material.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/personen.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/personen.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -453,14 +453,14 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/personen.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/personen.js?v=202609242347" defer></script>
</body>
</html>
+18 -18
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -214,16 +214,16 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/hochladen.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/hochladen.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/steckbrief.js?v=202609242039" defer></script>
<script src="assets/js/profil.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/steckbrief.js?v=202609242347" defer></script>
<script src="assets/js/profil.js?v=202609242347" defer></script>
</body>
</html>
+17 -17
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -134,14 +134,14 @@
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/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/rechte.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<script src="assets/js/rechte.js?v=202609242347" defer></script>
</body>
</html>
+18 -18
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/report.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/report.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -106,17 +106,17 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/ki.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/report.js?v=202609242039" defer></script>
<script src="assets/js/ki.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<script src="assets/js/report.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/scouting.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/scouting.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -173,14 +173,14 @@
</div>
</div>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/scouting.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/scouting.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/heim.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -684,16 +684,16 @@
</p>
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/live.js?v=202609242039" defer></script>
<script src="assets/js/start.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/live.js?v=202609242347" defer></script>
<script src="assets/js/start.js?v=202609242347" defer></script>
</body>
</html>
+17 -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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -85,16 +85,16 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/ki.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/startcheck.js?v=202609242039" defer></script>
<script src="assets/js/ki.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/startcheck.js?v=202609242347" defer></script>
</body>
</html>
+18 -18
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -150,16 +150,16 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/hochladen.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/hochladen.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/auskunft.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/steckbrief.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/auskunft.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/steckbrief.js?v=202609242347" defer></script>
</body>
</html>
+14 -14
View File
@@ -7,13 +7,13 @@
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/support.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/support.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -123,16 +123,16 @@
(reading 'LEITUNG')" ab -- gemessen am 24.09.2026, als diese
Zeile beim Anlegen der Seite fehlte. Die Kopfleiste kam
trotzdem, deshalb sah man es nur in der Browserkonsole. -->
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<!-- wahl.js gehoert zu kopf.js: Der Sicht-Umschalter in der
Kopfleiste baut daraus seine Liste. pruef-css-klassen setzt das
seit dem 07.09.2026 durch -- damals fehlte es auf chat.html und
uebersicht.html, und heute hier. -->
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/support.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/support.js?v=202609242347" defer></script>
</body>
</html>
+18 -18
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242347" />
<!-- Wegen des Kastens „Anfragen“ ueber der Liste. Eine eigene Kopie
der Regel hier waere die zweite Stelle, an der dieselbe Sache
anders aussieht. -->
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -111,15 +111,15 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/talente.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<script src="assets/js/talente.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/team.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/team.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -110,15 +110,15 @@
</main>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/team.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<script src="assets/js/team.js?v=202609242347" defer></script>
</body>
</html>
+17 -17
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/team.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/team.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<!-- `data-buehne` steht hier fest und nicht im Skript: Die Kachel zu
@@ -84,15 +84,15 @@
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/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/teamlage.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<script src="assets/js/teamlage.js?v=202609242347" defer></script>
</body>
</html>
+15 -15
View File
@@ -7,13 +7,13 @@
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -112,15 +112,15 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/teilen.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/teilen.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -126,14 +126,14 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/treff-moderation.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/treff-moderation.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- haus.css MUSS die letzte Stilvorlage sein. Auf der Adresse des
Rudels 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -248,14 +248,14 @@
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/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/auskunft.js?v=202609242039" defer></script>
<script src="assets/js/treff-regeln.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/auskunft.js?v=202609242347" defer></script>
<script src="assets/js/treff-regeln.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<!-- Formular- und Dialogstile: seit dem 07.09.2026 steht hier der
Dialog "Creator anlegen". -->
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -149,16 +149,16 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/uebersicht.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/uebersicht.js?v=202609242347" defer></script>
</body>
</html>
+15 -15
View File
@@ -7,13 +7,13 @@
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/unsere-seiten.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/unsere-seiten.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -335,14 +335,14 @@
</main>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/live.js?v=202609242039" defer></script>
<script src="assets/js/unsere-seiten.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/live.js?v=202609242347" defer></script>
<script src="assets/js/unsere-seiten.js?v=202609242347" defer></script>
</body>
</html>
+15 -15
View File
@@ -7,13 +7,13 @@
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/unterstuetzen.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/unterstuetzen.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -106,13 +106,13 @@
<!-- bereiche.js VOR kopf.js: Dort steht `window.Bereiche`, und kopf.js
liest daraus die Leitungsrollen. Ohne sie stürzt jede Seite mit
„Cannot read properties of undefined (reading 'LEITUNG')" ab. -->
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/holen.js?v=202609242039" defer></script>
<script src="assets/js/unterstuetzen.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/holen.js?v=202609242347" defer></script>
<script src="assets/js/unterstuetzen.js?v=202609242347" defer></script>
</body>
</html>
+16 -16
View File
@@ -7,15 +7,15 @@
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/werdegang.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/werdegang.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -144,14 +144,14 @@
</main>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/werdegang.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/werdegang.js?v=202609242347" defer></script>
</body>
</html>
+15 -15
View File
@@ -12,13 +12,13 @@
vergessen wird. -->
<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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/willkommen.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/willkommen.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<!-- KOERPERKLASSE "start", NICHT "gate" (berichtigt 21.09.2026).
`body.gate` ist die Anmeldewand: `display:flex; align-items:center`,
@@ -75,13 +75,13 @@
<p class="fehler" id="fehler" hidden></p>
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/willkommen.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/willkommen.js?v=202609242347" defer></script>
</body>
</html>
+17 -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=202609242039" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242039" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/wissen.css?v=202609242039" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242039" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609242347" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609242347" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/start.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/wissen.css?v=202609242347" />
<link rel="stylesheet" href="assets/css/module.css?v=202609242347" />
<!-- 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=202609242039" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609242347" />
</head>
<body class="start">
@@ -190,15 +190,15 @@
</main>
<script src="assets/js/meldung.js?v=202609242039" defer></script>
<script src="assets/js/hochladen.js?v=202609242039" defer></script>
<script src="assets/js/nachfrage.js?v=202609242039" defer></script>
<script src="assets/js/meldung.js?v=202609242347" defer></script>
<script src="assets/js/hochladen.js?v=202609242347" defer></script>
<script src="assets/js/nachfrage.js?v=202609242347" defer></script>
<script src="assets/js/wahl.js?v=202609242039" defer></script>
<script src="assets/js/bereiche.js?v=202609242039" defer></script>
<script src="assets/js/installieren.js?v=202609242039" defer></script>
<script src="assets/js/kopf.js?v=202609242039" defer></script>
<script src="assets/js/glocke.js?v=202609242039" defer></script>
<script src="assets/js/wissen.js?v=202609242039" defer></script>
<script src="assets/js/wahl.js?v=202609242347" defer></script>
<script src="assets/js/bereiche.js?v=202609242347" defer></script>
<script src="assets/js/installieren.js?v=202609242347" defer></script>
<script src="assets/js/kopf.js?v=202609242347" defer></script>
<script src="assets/js/glocke.js?v=202609242347" defer></script>
<script src="assets/js/wissen.js?v=202609242347" defer></script>
</body>
</html>