Aus der Probe wird ein Zugang - und die Seite sagt nicht mehr "Agentur"

Die drei offenen Punkte aus Abschnitt 9 des Plans, plus Filipes zweite
Ansage: "auf dieser seite soll nichts stehen von agentur, diese seite
hier ist nur fuer mich meine modis und meine community."

1. PROBE -> ZUGANG (ein Knopf statt eines Satzes)

Auf der Stufe "Probe" stand bisher "Zugang in Personen & Zugaenge
anlegen, Rolle Modi" - und wer das vergass, hatte eine Karte auf "Im
Team" und keinen Menschen darin. Jetzt haengt das Anlegen am Schritt
selbst.

Ueber DENSELBEN Weg wie in "Personen & Zugaenge", nicht ueber einen
zweiten: POST /workspace/api/verwaltung/personen, mit ihrer
Rechtepruefung, ihrem Protokolleintrag und ihrem genau einmal
angezeigten Code. Der Talente-Server legt selbst keinen einzigen Zugang
an, und die Pruefung zaehlt nach, dass es bei einem Weg bleibt.

Der Code steht im gleichen Kasten wie dort - die Gestaltung ist aus
personen.css nach start.css umgezogen, weil talente.html sie sonst nicht
laedt. Ein Geheimnis sieht im ganzen Haus gleich aus. Er steht
ausserhalb der Liste, sonst waere er in dem Moment weg, in dem er
entsteht: wenn die Karte auf "Im Team" springt.

Die rechte Hand bekommt an dieser Stelle KEINEN Knopf, sondern einen
Satz. Ein Knopf, der ihr jedes Mal "darfst du nicht" antwortet, waere
schlechter als gar keiner - er verspricht etwas.

2. DIE EIGENE KARTE (Abschnitt "Deine Karte")

Wer beschrieben wird, darf es lesen - aber erst, wenn ALLE gesetzt
haben (sonst waere die erste Einschaetzung eine Vorgabe fuer die
zweite), und ohne Namen und ohne Anlasstext. Gemessen in beide
Richtungen: vorher nicht sichtbar, nachher sichtbar.

3. DER VORLAGENTEXT

Gebaut aus den angeklickten Merkmalen, in einem Feld zum Aendern, nicht
zum Abschicken. Ohne Merkmale steht auch keines drin.

4. "GILT FUER" SAGT DER SERVER

In bereich.js stand woertlich "Agentur" - richtig auf der
Agenturadresse, falsch auf jeder anderen. Jetzt liefert der Server
`gehoert` ("Der Treff" / "Team Dogi" / "Agentur"); gemessen mit einem
einzigen Menschen auf zwei Adressen.

PRUEFUNGEN: treff 58 -> 66, nachwuchs 69 -> 109, neue-seiten 70 -> 93.
Die Katalogseiten werden jetzt auch mit den Augen der rechten Hand
angesehen - ohne das waere "Deine Karte" nie auf einem Bildschirm
gewesen. Und pruef-neue-seiten wartet nicht mehr 900 ms, sondern bis
sich der Text nicht mehr aendert: Die Karte stand da und wurde
trotzdem als fehlend gemeldet, weil zu frueh gelesen wurde.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-11 23:13:50 +02:00
co-authored by Claude Opus 5
parent 44e5ace109
commit bba3642664
41 changed files with 1447 additions and 420 deletions
+194 -1
View File
@@ -20,7 +20,7 @@
Aufrufen mit: node server/pruef-nachwuchs.mjs
===================================================================== */
import { mkdtempSync, rmSync } from "node:fs";
import { mkdtempSync, rmSync, readFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { request as httpAnfrage } from "node:http";
@@ -454,6 +454,199 @@ melde("=== 8. Standzeit ===");
`einen Tag vor der Frist noch nicht (${r2.kandidaten[0].tage} Tage)`);
}
/* =======================================================================
9. DER VORLAGENTEXT
Er ist der Unterschied zwischen "Ansprechen" als Aufgabe und
"Ansprechen" als erledigter Sache. Geprueft wird deshalb nicht, DASS
ein Text kommt, sondern dass er aus den angeklickten Merkmalen
gebaut ist -- sonst waere es eine Floskel mit eingesetztem Namen.
======================================================================= */
melde("");
melde("=== 9. Der Vorlagentext ===");
{
const zwei = [tal.TALENT_ALLE[0], tal.TALENT_ALLE[1]];
const text = tal.ansprechtext("Kessi aus dem Chat", zwei.map((m) => m.schluessel));
ok(text.startsWith("Hey Kessi,"),
"die Anrede nimmt nur den ersten Namensteil, nicht den ganzen Eintragstitel");
ok(zwei.every((m) => text.includes(m.du)),
"beide angeklickten Merkmale stehen woertlich im Text");
ok(/kein Druck|nein/.test(text),
"und der Ausstieg steht drin -- ein Angebot ohne Nein ist keines");
/* GEGENPROBE: ohne ein einziges Merkmal darf KEINES drinstehen --
sonst baut die Funktion sich etwas zusammen, das niemand beobachtet
hat. Das waere die schlimmste Sorte Vorlage. */
const leer = tal.ansprechtext("Kessi", []);
ok(!tal.TALENT_ALLE.some((m) => leer.includes(m.du)),
"ohne angeklickte Merkmale steht auch keines im Text");
ok(leer.length > 100, `aber ein vollstaendiger Text bleibt es (${leer.length} Zeichen)`);
ok(leer !== text, "und er ist ein anderer als der mit Merkmalen");
/* HAUSREGEL: In Text, den ein Mensch liest, stehen echte Umlaute.
"Haettest du Lust" war genau der Fehler, den diese Zeile findet. */
const beide = text + " " + leer;
ok(!/\b(fuer|koenn|haett|muess|ueber|waer|moecht)/i.test(beide),
"keine ASCII-Ersatzumlaute in einem Text, den ein Mensch liest");
ok(/\b(fuer)/i.test("das ist fuer dich"), "und der Sucher findet so einen auch wirklich");
/* UND ER KOMMT UEBER DIE LEITUNG AN, nicht nur aus dem Modul. */
const lage = json(await roh("/workspace/api/talente/lage", HAUS, { cookie: kDogi }));
const k = (lage.kandidaten || [])[0];
ok(typeof k?.ansprechtext === "string" && k.ansprechtext.length > 100,
"die Karte bringt ihren Text mit");
const gesetzt = (k?.merkmale || []).map((s) => tal.TALENT_NACH_SCHLUESSEL.get(s)?.du).filter(Boolean);
ok(gesetzt.length > 0 && gesetzt.every((d) => k.ansprechtext.includes(d)),
`und zwar aus ihren ${gesetzt.length} gesetzten Merkmalen`);
}
/* =======================================================================
10. DIE EIGENE KARTE
Sie ist die Gegenprobe zur ganzen Kategorie: Ueber Menschen wird hier
aufgeschrieben, und wer beschrieben wird, darf es lesen. Aber erst,
wenn ALLE gesetzt haben -- sonst waere die erste Einschaetzung eine
Vorgabe fuer die zweite -- und ohne Namen und ohne Anlasstext.
======================================================================= */
melde("");
melde("=== 10. Die eigene Karte ===");
{
const meine = json(await roh("/workspace/api/entwicklung/meine-karte", CREW, { cookie: kModi }));
ok(meine.hat_karte === true, "der Modi hat eine eigene Karte");
ok(meine.beurteiler === 2,
`zwei Augenpaare urteilen ueber ihn (${meine.beurteiler}) -- er selbst zaehlt nicht mit`);
const punkte = (meine.bloecke || []).flatMap((b) => b.punkte || []);
ok(punkte.length > 0, `${punkte.length} Punkte in seiner Karte`);
/* Aus Abschnitt 4: DIESEN Punkt haben beide gesetzt (laeuft/waechst). */
const beide = punkte.find((p) => p.schluessel === kat.ENTWICKLUNG_FREMD[0].schluessel);
ok(beide && beide.offen === false, "ein Punkt, den beide gesetzt haben, ist offen");
ok(beide?.antworten?.length === 2,
`mit beiden Antworten nebeneinander (${(beide?.antworten || []).map((a) => a.name).join(" / ")})`);
ok(beide?.einig === false, "und dem ehrlichen Hinweis, dass sie sich uneinig sind");
/* GEGENPROBE 1 -- und ohne sie beweist die Zeile darueber nichts:
Einen Punkt, den erst EINER gesetzt hat, bekommt er NICHT. */
const einer = punkte.find((p) => p.schluessel === kat.ENTWICKLUNG_FREMD[1].schluessel);
ok(einer && einer.offen === true,
"einen Punkt, den erst einer gesetzt hat, sieht er noch nicht");
ok(einer && einer.antworten === undefined,
"und die Antwort des einen reist dabei auch nicht heimlich mit");
/* GEGENPROBE 2: sobald die zweite dazukommt, oeffnet er sich. */
const nach = await roh(`/workspace/api/entwicklung/person/${idModi}/${kat.ENTWICKLUNG_FREMD[1].schluessel}`,
CREW, { cookie: kHand }, { stufe: "hakt", anlass: "Zweimal zu spaet zur Schicht." }, "PUT");
ok(nach.code === 200, `die rechte Hand setzt denselben Punkt (${nach.code})`);
const meine2 = await roh("/workspace/api/entwicklung/meine-karte", CREW, { cookie: kModi });
const jetztOffen = (json(meine2).bloecke || []).flatMap((b) => b.punkte || [])
.find((p) => p.schluessel === kat.ENTWICKLUNG_FREMD[1].schluessel);
ok(jetztOffen?.offen === false && jetztOffen?.antworten?.length >= 1,
"danach steht er in seiner Karte");
/* KEINE NAMEN UND KEIN ANLASS. Beides steht in der Karte, die
DogFather sieht -- und beides waere hier ein Vertrauensbruch:
"wer hat das ueber mich gesagt" macht aus einer Entwicklung eine
Abrechnung. */
const roh2 = meine2.text;
ok(!/Filipe|Rieke/.test(roh2), "kein Name eines Beurteilers in der ganzen Antwort");
ok(!/zu spaet zur Schicht|Am Samstag/.test(roh2), "und kein einziger Anlasstext");
ok(/hakt|laeuft|waechst/.test(roh2),
"die Antworten selbst kommen aber an -- sonst waere die Zeile darueber trivial");
/* Block 5 gehoert der Person -- er steht in IHRER Selbstauskunft,
nicht in der Fremdkarte. Waere er hier, stuenden Antworten
anderer auf Fragen, die nur sie sich stellt. */
const selbst = kat.ENTWICKLUNG_SELBST.map((p) => p.schluessel);
ok(!punkte.some((p) => selbst.includes(p.schluessel)),
"Block 5 taucht in der eigenen Karte nicht als Fremdurteil auf");
/* Wer gar nicht beurteilt wird, bekommt auch keine leere Karte
vorgesetzt -- eine Karte ohne Inhalt liest sich wie ein Versaeumnis. */
/* UND DIE RECHTE HAND HAT AUCH EINE. Ueber sie urteilt nur DogFather
-- sie selbst zaehlt nicht mit, sonst waere ihre Karte erst dann
vollstaendig, wenn sie sich selbst eingeschaetzt hat. */
const ihre = json(await roh("/workspace/api/entwicklung/meine-karte", CREW, { cookie: kHand }));
ok(ihre.hat_karte === true, `auch die rechte Hand hat eine eigene Karte (${JSON.stringify(ihre).slice(0, 90)})`);
ok(ihre.beurteiler === 1, `ueber sie urteilt genau einer (${ihre.beurteiler})`);
const chef = json(await roh("/workspace/api/entwicklung/meine-karte", HAUS, { cookie: kDogi }));
ok(chef.hat_karte === false, "DogFather selbst hat keine -- ueber ihn urteilt hier niemand");
}
/* =======================================================================
11. AUS DER PROBE WIRD EIN ZUGANG
Der letzte Schritt des Trichters ist kein Schritt, sondern eine
Entscheidung. Bis heute stand dort ein Satz ("Zugang in Personen &
Zugaenge anlegen"), und wer ihn vergass, hatte eine Karte auf "Im
Team" und keinen Menschen darin.
GEPRUEFT WIRD VOR ALLEM EINES: dass es dafuer keinen ZWEITEN Weg
gibt. Ein Zugang entsteht im ganzen Haus an genau einer Stelle.
======================================================================= */
melde("");
melde("=== 11. Probe → Zugang ===");
{
const letzte = tal.TALENT_STUFEN.at(-1);
ok(!/Personen/.test(letzte.schritt || ""),
"die letzte Stufe schickt niemanden mehr von Hand in die Personenverwaltung");
/* EIN EINZIGER WEG, und es ist der vorhandene. */
const js = readFileSync(new URL("../workspace/assets/js/talente.js", import.meta.url), "utf8");
/* OHNE DIE KOMMENTARE gezaehlt: Der Weg wird daneben auch erklaert,
und eine Erklaerung ist kein zweiter Weg. */
const jsCode = js.replace(/\/\*[\s\S]*?\*\//g, "");
const wege = jsCode.split("/workspace/api/verwaltung/personen").length - 1;
ok(wege === 1, `talente.js kennt genau einen Weg zum Anlegen (${wege})`);
ok(js.split("/workspace/api/verwaltung/personen").length - 1 > wege,
"und der Kommentar daneben nennt ihn beim Namen -- sonst zaehlt die Zeile darueber nichts weg");
const eigen = readFileSync(new URL("../server/workspace-entwicklung.js", import.meta.url), "utf8");
ok(!/personAnlegen|INSERT INTO personen/.test(eigen),
"und der Talente-Server legt selbst keinen einzigen Zugang an");
/* DIE RECHTE HAND SIEHT DEN TRICHTER, VERGIBT ABER KEINE ZUGAENGE. */
const hand = await roh("/workspace/api/verwaltung/personen", CREW, { cookie: kHand },
{ name: "Heimlich", rolle: "modi" });
ok(hand.code === 404, `die rechte Hand kommt am Anlegen nicht vorbei (${hand.code})`);
const einModi = await roh("/workspace/api/verwaltung/personen", CREW, { cookie: kModi },
{ name: "Heimlich", rolle: "modi" });
ok(einModi.code === 404, `ein Modi erst recht nicht (${einModi.code})`);
/* GEGENPROBE: DogFather kann es -- sonst waere "404" oben auch dann
gruen, wenn der Weg gar nicht existiert. */
const neu = await roh("/workspace/api/verwaltung/personen", HAUS, { cookie: kDogi },
{ name: "Kessi", rolle: "modi" });
ok(neu.code === 201, `DogFather legt den Zugang an (${neu.code})`);
const person = json(neu);
ok(person.rolle === "modi", `und zwar als Modi (${person.rolle})`);
ok(typeof person.code === "string" && person.code.length > 8,
"der Zugangscode kommt genau einmal zurueck");
/* UND DANACH IST ER WEG. Nirgends abrufbar -- auch nicht fuer den,
der ihn angelegt hat. */
const liste = await roh("/workspace/api/verwaltung/personen", HAUS, { cookie: kDogi });
ok(liste.code === 200 && !liste.text.includes(person.code),
"danach steht er in keiner Liste mehr");
/* Erst jetzt wandert die Karte -- in derselben Reihenfolge wie in der
Oberflaeche: erst der Mensch, dann der Haken. */
const stufe = await roh(`/workspace/api/talente/${idTalent}/stufe`, HAUS,
{ cookie: kDogi }, { stufe: "imteam" }, "PUT");
ok(stufe.code === 200, `und die Karte geht auf "Im Team" (${stufe.code})`);
const lage = json(await roh("/workspace/api/talente/lage", HAUS, { cookie: kDogi }));
const k = (lage.kandidaten || []).find((x) => x.id === idTalent);
ok(k?.stufe === "imteam" && k?.knopf === null,
"dahinter kommt kein weiterer Knopf -- der Trichter ist zu Ende");
/* Der neue Mensch ist wirklich da, mit allem, was daran haengt. */
const dd = new DatabaseSync(process.env.WORKSPACE_DB);
const z = dd.prepare("SELECT rolle, aktiv FROM personen WHERE name = 'Kessi'").get();
dd.close();
ok(z?.rolle === "modi" && z?.aktiv === 1, "und er steht als aktiver Modi in der Datenbank");
}
/* ------------------------------------------------------------------- */
melde("");
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
+191 -21
View File
@@ -121,19 +121,72 @@ await roh("/workspace/api/treff/massnahme", { cookie: kDogi },
/* ETWAS AUF DEN KATALOGSEITEN. Ohne eine Person im Team ist die
Entwicklungsseite leer, ohne einen Kandidaten der Trichter -- und
eine leere Seite erfuellt jede Bedingung, ohne etwas zu zeigen. */
eine leere Seite erfuellt jede Bedingung, ohne etwas zu zeigen.
UND ZWAR AUF MEHREREN STUFEN. Der Trichter zeigt je Stufe einen
ANDEREN naechsten Schritt; steht nur ein Kandidat auf der ersten,
bleiben die Knoepfe der anderen vier ungesehen. Genau dort sitzen
seit dem 11.09. die zwei neuen: der Vorlagentext auf "Beobachtet"
und "Ins Team holen · Zugang anlegen" auf "Probe". */
/* EINMAL ANKLOPFEN, DAMIT ES DIE TABELLEN GIBT. Sie entstehen beim
ersten angemeldeten Aufruf des Bereichs, nicht beim Start -- ein
INSERT davor liefe gegen eine Tabelle, die es noch nicht gibt. */
await roh("/workspace/api/talente/lage", { cookie: kDogi });
const kat = await import("./workspace-entwicklungs-punkte.js");
const talKat = await import("./workspace-talent-punkte.js");
const dd = new DatabaseSync(process.env.WORKSPACE_DB);
let idHand = null;
{
const salt = randomBytes(16).toString("hex");
const hash = scryptSync("CODE-MODI-0001", salt, 64,
{ N: 32768, r: 8, p: 1, maxmem: 96 * 1024 * 1024 }).toString("hex");
dd.prepare("INSERT INTO personen (name, rolle, code_hash, code_salt, code_n, code_kennung, aktiv, erstellt)"
+ " VALUES ('Frida','modi',?,?,?,?,1,?)")
.run(hash, salt, 32768,
createHmac("sha256", schluessel).update("CODE-MODI-0001").digest("hex"), jetzt);
dd.prepare("INSERT INTO eintraege (bereich, art, titel, text, datum, erstellt, erstellt_von, einsatz)"
+ " VALUES ('talente','ruhig','Kessi aus dem Chat','Faellt seit Wochen auf.',?,?,?,?)")
.run(jetzt.slice(0, 10), jetzt, idDogi, "Im Stream am Dienstag");
const person = (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");
dd.prepare("INSERT INTO personen (name, rolle, code_hash, code_salt, code_n, code_kennung, aktiv, erstellt)"
+ " VALUES (?,?,?,?,?,?,1,?)")
.run(name, rolle, hash, salt, 32768,
createHmac("sha256", schluessel).update(code).digest("hex"), jetzt);
return dd.prepare("SELECT last_insert_rowid() AS id").get().id;
};
person("Frida", "modi", "CODE-MODI-0001");
idHand = person("Rieke", "hand", "CODE-HAND-0001");
const talent = (titel, text) => {
dd.prepare("INSERT INTO eintraege (bereich, art, titel, text, datum, erstellt, erstellt_von, einsatz)"
+ " VALUES ('talente','ruhig',?,?,?,?,?,?)")
.run(titel, text, jetzt.slice(0, 10), jetzt, idDogi, "Im Stream am Dienstag");
return dd.prepare("SELECT last_insert_rowid() AS id").get().id;
};
talent("Kessi aus dem Chat", "Faellt seit Wochen auf.");
const idBeobachtet = talent("Malin aus dem Chat", "Haelt den Chat ruhig.");
const idProbe = talent("Tino aus dem Chat", "Laeuft seit vier Wochen mit.");
const stufe = dd.prepare(
"INSERT INTO talent_stufe (eintrag_id, stufe, seit, von_id) VALUES (?,?,?,?)");
stufe.run(idBeobachtet, "beobachtet", jetzt, idDogi);
stufe.run(idProbe, "probe", jetzt, idDogi);
/* MERKMALE fuer den Vorlagentext -- er wird daraus gebaut. Ohne sie
stuende dort der Satz fuer "noch nichts beobachtet", und die neue
Gestaltung waere zwar sichtbar, aber nicht in ihrer laengsten
Fassung. Gemessen werden soll die laengste. */
const merk = dd.prepare(
"INSERT INTO talent_merkmal (eintrag_id, schluessel, von_id, am) VALUES (?,?,?,?)");
for (const m of talKat.TALENT_ALLE.slice(0, 3)) {
merk.run(idBeobachtet, m.schluessel, idDogi, jetzt);
}
/* DIE EIGENE KARTE DER RECHTEN HAND. Sie oeffnet sich erst, wenn
jeder Beurteiler gesetzt hat -- ueber sie urteilt nur DogFather,
also reicht eine Zeile je Punkt. Sechs gesetzte und der Rest offen:
So stehen beide Zustaende nebeneinander auf dem Bildschirm. */
const stand = dd.prepare(
"INSERT INTO entwicklung_stand (person_id, schluessel, von_id, stufe, anlass, am)"
+ " VALUES (?,?,?,?,?,?)");
const stufen = ["laeuft", "waechst", "laeuft", "hakt", "laeuft", "waechst"];
kat.ENTWICKLUNG_FREMD.slice(0, 6).forEach((p, i) => {
stand.run(idHand, p.schluessel, idDogi, stufen[i],
stufen[i] === "hakt" ? "Zweimal zu spaet zur Schicht." : null, jetzt);
});
}
dd.close();
@@ -299,7 +352,16 @@ const UEBERBREIT = `(() => {
return { schiebt, raus };
})()`;
async function ansehen(name, pfad, code, breite, hoehe) {
/* MIT EINEM FERTIGEN KEKS STATT ueber die Anmeldemaske (11.09.2026).
Die rechte Hand meldet sich an der CREW-WAND an, und die haengt am
Host-Kopf -- den kann ein Browser bei einer Navigation nicht setzen.
Ueber die Maske auf 127.0.0.1 kommt sie also gar nicht herein.
Das ist kein Umgehen einer Sicherung: Angemeldet wird ueber denselben
Weg wie sonst (/api/anmelden), nur die Maske bleibt aussen vor. Was
die Seite danach zeigt, entscheidet weiterhin der Server. */
async function ansehen(name, pfad, code, breite, hoehe, keks = null) {
const kontext = await browser.newContext({ viewport: { width: breite, height: hoehe } });
const seite = await kontext.newPage();
const konsole = [];
@@ -308,14 +370,39 @@ async function ansehen(name, pfad, code, breite, hoehe) {
});
seite.on("pageerror", (e) => konsole.push("Absturz: " + e.message));
await seite.goto(`${BASIS}/workspace/`, { waitUntil: "domcontentloaded" });
await seite.click(`.rolle[data-rolle="admin"]`);
await seite.fill("#code", code);
await seite.click("button[type=submit]");
await seite.waitForURL("**/start.html", { timeout: 15000 });
if (keks) {
await kontext.addCookies(keks.split("; ").filter(Boolean).map((teil) => {
const i = teil.indexOf("=");
return { name: teil.slice(0, i), value: teil.slice(i + 1), domain: "127.0.0.1", path: "/" };
}));
} else {
await seite.goto(`${BASIS}/workspace/`, { waitUntil: "domcontentloaded" });
await seite.click(`.rolle[data-rolle="admin"]`);
await seite.fill("#code", code);
await seite.click("button[type=submit]");
await seite.waitForURL("**/start.html", { timeout: 15000 });
}
await seite.goto(`${BASIS}/workspace/${pfad}`, { waitUntil: "networkidle" });
await seite.waitForTimeout(900);
/* WARTEN, BIS SICH NICHTS MEHR AENDERT -- NICHT 900 MILLISEKUNDEN.
Gemessen am 11.09.2026: Die eigene Karte der rechten Hand stand
nachweislich auf dem Bildschirm (versteckt: false, Antwort 200),
aber der Text war schon vorher gelesen. Die Pruefung meldete
"steht nicht da" fuer etwas, das dastand -- der schlimmste
Fehlalarm, weil man danach am richtigen Code sucht.
Eine groessere Zahl waere derselbe Fehler mit einer anderen Zahl.
Die Seite laedt ihre Abschnitte nacheinander; wie lange das
dauert, haengt an ihrer Anzahl. Deshalb eine Regel statt einer
Rechnung: gelesen wird, wenn der Text dreimal hintereinander
derselbe war. Die Frist darueber ist nur die Notbremse. */
await seite.waitForFunction(() => {
const t = document.querySelector("main")?.innerText || "";
if (window.__standStill === t) { window.__ruhig = (window.__ruhig || 0) + 1; }
else { window.__standStill = t; window.__ruhig = 0; }
return (window.__ruhig || 0) >= 3;
}, null, { timeout: 12000, polling: 200 }).catch(() => {});
const text = await seite.evaluate(() => (document.querySelector("main")?.innerText || "").trim());
const punkte = await seite.evaluate(() => (document.querySelector("main")?.innerText || "")
@@ -323,12 +410,32 @@ async function ansehen(name, pfad, code, breite, hoehe) {
const kontrast = await seite.evaluate(KONTRAST);
const ueberlapp = await seite.evaluate(UEBERLAPP);
const breit = await seite.evaluate(UEBERBREIT);
/* DIE EIGENE KARTE IST DER EINZIGE ABSCHNITT, DER SICH SELBST
AUFDECKT. Bleibt er zu, sieht die Seite vollkommen normal aus --
deshalb wird hier nicht nur gelesen, was dasteht, sondern gefragt,
was der Server dazu sagt. */
const karte = await seite.evaluate(async () => {
const e = document.getElementById("karte-block");
if (!e) return { da: false };
let antwort = null;
try {
const a = await fetch("/workspace/api/entwicklung/meine-karte", { credentials: "same-origin" });
antwort = { status: a.status, hat: (await a.json()).hat_karte };
} catch (f) { antwort = { status: -1, fehler: String(f) }; }
return { da: true, versteckt: e.hidden, antwort };
});
await seite.screenshot({ path: join(BILDER, `${name}-${breite}.png`), fullPage: true });
await kontext.close();
return { text, punkte, kontrast, ueberlapp, breit, konsole };
return { text, punkte, kontrast, ueberlapp, breit, konsole, karte };
}
for (const [name, pfad] of [
const gesehen = {}; // was auf jedem Bildschirm tatsaechlich stand
const anm3 = await roh("/workspace/api/anmelden", {}, { rolle: "hand", code: "CODE-HAND-0001" });
const kHand = [].concat(anm3.kopf?.["set-cookie"] || []).map((c) => c.split(";")[0]).join("; ");
ok(!!kHand, "die rechte Hand ist angemeldet -- ohne sie bliebe ihre eigene Karte ungesehen");
for (const [name, pfad, keks] of [
["regeln", "treff-regeln.html"],
["rechte", "rechte.html"],
["moderation", "treff-moderation.html"],
@@ -338,11 +445,17 @@ for (const [name, pfad] of [
findet andere Fehler. */
["entwicklung", "entwicklung.html"],
["talente", "talente.html"],
/* UND EINMAL DIESELBE SEITE MIT ANDEREN AUGEN. "Deine Karte" gibt es
nur fuer die, ueber die geurteilt wird -- DogFather sieht sie nie.
Ohne diese Zeile waere der ganze Abschnitt nie auf einem Bildschirm
gewesen. */
["entwicklung-hand", "entwicklung.html", kHand],
]) {
melde("");
melde(`=== ${pfad} ===`);
for (const [breite, hoehe] of [[1440, 1000], [390, 844]]) {
const r = await ansehen(name, pfad, "CODE-DOGI-0001", breite, hoehe);
const r = await ansehen(name, pfad, "CODE-DOGI-0001", breite, hoehe, keks);
if (breite === 1440) { gesehen[name] = r.text; gesehen[name + ":karte"] = r.karte; }
const wo = `${breite} px`;
ok(r.text.length > 400, `${wo}: die Seite ist gefüllt (${r.text.length} Zeichen)`);
@@ -374,6 +487,63 @@ for (const [name, pfad] of [
}
}
/* =======================================================================
WAR DAS NEUE UEBERHAUPT AUF DEM BILDSCHIRM?
Die Messungen darueber sagen "nichts liegt uebereinander" und "alles
lesbar" -- und beides ist auch dann wahr, wenn das Gesuchte gar nicht
da war. Eine leere Seite erfuellt jede dieser Bedingungen.
Deshalb hier die Gegenfrage, und zwar in beide Richtungen: Das Neue
MUSS dort stehen, wo es hingehoert, und darf NICHT dort stehen, wo
es nicht hingehoert. Nur die zweite Haelfte beweist, dass die erste
etwas heisst.
======================================================================= */
melde("");
melde("=== Stand das Neue auch wirklich da? ===");
{
const t = gesehen.talente || "";
ok(/Vorlagentext/.test(t),
"Talente: der Knopf fuer den Vorlagentext stand auf der Stufe „Beobachtet“");
ok(/Ins Team holen/.test(t),
"Talente: „Ins Team holen · Zugang anlegen“ stand auf der Stufe „Probe“");
/* GEGENPROBE: Der Vorlagentext gehoert auf GENAU EINE Stufe. Stuende
er auf jeder, waere er auf vier von fuenf eine Ablenkung -- und die
Zeile darueber waere trotzdem gruen. */
/* ZEILENWEISE gezaehlt und nicht als Wort: "Der Vorlagentext liegt
bereit" ist der Satz des naechsten Schritts, der Knopf steht
allein auf seiner Zeile. Als Wort gezaehlt waeren es zwei, und die
Zeile haette einen Fehler gemeldet, den es nicht gibt. */
const knoepfe = (wort) => t.split("\n").filter((z) => z.trim() === wort).length;
ok(knoepfe("Vorlagentext") === 1,
`und zwar genau einmal, nicht bei jedem Kandidaten (${knoepfe("Vorlagentext")})`);
ok(t.split("Ins Team holen").length - 1 === 1,
`der Zugangsknopf ebenso (${t.split("Ins Team holen").length - 1})`);
const hand = gesehen["entwicklung-hand"] || "";
const dogi = gesehen.entwicklung || "";
/* WENN ES SCHIEFGEHT, SOLL DIE MELDUNG SAGEN, WAS STATTDESSEN DA WAR.
"nicht gefunden" allein laesst offen, ob die Karte fehlt oder die
ganze Seite eine andere war. */
const obenLinks = (hand.split("\n").map((z) => z.trim()).filter(Boolean)[0] || "(leer)");
/* OHNE RUECKSICHT AUF GROSS UND KLEIN: innerText liefert, was der
Browser ZEIGT -- und .e-abschnitt ist in Grossbuchstaben gesetzt.
Im Quelltext steht "Deine Karte", auf dem Bildschirm "DEINE
KARTE". Eine Suche mit Ruecksicht darauf meldet "steht nicht da"
fuer etwas, das dasteht. */
ok(/Deine Karte/i.test(hand),
`Entwicklung: die rechte Hand sieht ihre eigene Karte (${JSON.stringify(gesehen["entwicklung-hand:karte"])} / oben: ${obenLinks})`);
ok(!/Deine Karte/i.test(dogi),
"und DogFather sieht sie nicht -- ueber ihn urteilt hier niemand");
ok(hand !== dogi && hand.length > 400,
`zwei verschiedene Bildschirme (${dogi.length} / ${hand.length} Zeichen) -- der Keks hat also gewirkt`);
/* UND KEIN NAME EINES BEURTEILERS. Was der Server nicht ausliefert,
kann die Seite nicht zeigen -- aber genau das ist die Behauptung,
und Behauptungen gehoeren gemessen. */
ok(!/Filipe/.test(hand),
"und in ihrer Karte steht kein Name dessen, der geurteilt hat");
}
await browser.close();
melde("");
melde(`Bilder liegen in ${BILDER}`);
+61 -1
View File
@@ -37,7 +37,7 @@
dann an die falsche Wand und scheiterte, ohne dass man saehe warum.
Dieselbe Falle wie am 10.09. bei den Kategorie-Kanaelen.
===================================================================== */
import { mkdtempSync, rmSync } from "node:fs";
import { mkdtempSync, rmSync, readFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { request as httpAnfrage } from "node:http";
@@ -618,6 +618,66 @@ melde("=== 6. Schreiben ===");
ok(a.code !== 200 && a.code !== 201, `aber nicht in ein Brett des Hauses (${a.code})`);
}
/* =======================================================================
7. WEM EIN EINTRAG GILT, SAGT DER SERVER -- NICHT DIE OBERFLAECHE
Filipe, 11.09.2026: "auf dieser seite soll nichts stehen von agentur,
diese seite hier ist nur fuer mich meine modis und meine community."
Er hatte recht, und der Fehler war ein fest eingetragenes Wort: In
bereich.js stand woertlich "Agentur" -- richtig auf der
Agenturadresse, falsch auf jeder anderen.
GEPRUEFT WIRD MIT EINEM EINZIGEN MENSCHEN AUF ZWEI ADRESSEN. Dieselbe
Person, dasselbe Brett, zwei Waende: Wandert das Wort mit, kommt es
vom Haus. Waere es an der Rolle festgemacht, stuende hier zweimal
dasselbe -- und das ist genau der Fehler, den es zu finden gilt.
======================================================================= */
melde("");
melde("=== 7. Das Wort für „Gilt für“ kommt vom Server ===");
{
const kCrew = (await anmelden("admin", "CODE-DOGI-0001", CREW)).keks;
const kHaus = (await anmelden("admin", "CODE-DOGI-0001", HAUS)).keks;
ok(!!kCrew && !!kHaus, "DogFather ist an beiden Waenden angemeldet");
const lies = async (brett, host, keks) => {
const a = await roh(`/workspace/api/bereich/${brett}`, host, { cookie: keks });
let g = null;
try { g = JSON.parse(a.text).gehoert; } catch { /* bleibt null */ }
return { code: a.code, gehoert: g };
};
const treff = await lies("treff", CREW, kCrew);
ok(treff.code === 200 && treff.gehoert === "Der Treff",
`ein Treff-Brett gehoert dem Treff (${treff.gehoert})`);
const crew = await lies("ideen", CREW, kCrew);
ok(crew.code === 200 && crew.gehoert === "Team Dogi",
`dasselbe Haus-Brett auf crew. gehoert Team Dogi (${crew.gehoert})`);
/* GEGENPROBE, und ohne sie beweist die Zeile darueber nichts: Auf der
Agenturadresse MUSS weiterhin "Agentur" stehen. Ein Wort, das
ueberall dasselbe sagt, sagt nichts. */
const haus = await lies("ideen", HAUS, kHaus);
ok(haus.code === 200 && haus.gehoert === "Agentur",
`und auf workspace. weiterhin Agentur (${haus.gehoert})`);
ok(crew.gehoert !== haus.gehoert,
"dieselbe Person, dasselbe Brett, zwei Woerter -- es haengt am Haus");
/* UND DIE OBERFLAECHE SCHREIBT ES NICHT MEHR SELBST HIN. */
const js = readFileSync(new URL("../workspace/assets/js/bereich.js", import.meta.url), "utf8");
const ohneKommentare = js.replace(/\/\*[\s\S]*?\*\//g, "");
ok(!/['"`]Agentur/.test(ohneKommentare),
"in bereich.js steht das Wort „Agentur“ in keinem Text mehr");
ok(/gehoert/.test(ohneKommentare),
"stattdessen fragt sie den Server danach");
/* Gegenprobe zum Sucher selbst: Er MUSS ein hingeschriebenes
"Agentur" auch wirklich finden, sonst ist die Zeile darueber nur
gruen, weil sie blind ist. */
ok(/['"`]Agentur/.test("const x = 'Agentur-Eintraege';"),
"und der Sucher findet so ein Wort auch wirklich");
}
melde("");
console.log(`${geprueft} Pruefungen, ${fehler} Fehler`);
console.log(fehler === 0 ? "ALLES IN ORDNUNG" : "NICHT IN ORDNUNG");
+19 -1
View File
@@ -1093,8 +1093,26 @@ bereicheRouter.get("/workspace/api/bereich/:bereich", (req, res) => {
es gaebe eine zweite Wahrheit darueber, welche es sind. So gibt
es weiterhin genau eine (TREFF_BRETTER), und der Browser fragt
sie, statt sie zu kennen. */
/* WEM GEHOERT EIN EINTRAG AUF DIESEM BRETT? (11.09.2026)
Filipe, mit Bildschirmfoto des Feldes "Gilt für: Agentur":
"auf dieser seite soll nichts stehen von agentur, diese seite
hier ist nur für mich meine modis und meine community."
Er hatte recht, und der Fehler war ein fest eingetragenes Wort:
In bereich.js stand woertlich "Agentur" -- richtig auf der
Agenturadresse, falsch auf jeder anderen. Ein Wort in der
Oberflaeche, das eine Tatsache ueber den Server behauptet, ist
genau die Sorte Zweitschrift, die auseinanderlaeuft.
Jetzt sagt der Server es. Er weiss beides: welches Brett es ist
und in welchem Haus die Person gerade steht. */
const gehoert = treffBrett ? "Der Treff"
: (req.sicht || req.person)?.haus === "crew" ? "Team Dogi"
: "Agentur";
res.json({
bereich, einstellung, treff: treffBrett,
bereich, einstellung, treff: treffBrett, gehoert,
eintraege: treffBrett ? eintraege.map(mitRollenname) : eintraege,
});
} catch (fehler) {
+96 -1
View File
@@ -69,7 +69,7 @@ import {
} from "./workspace-entwicklungs-punkte.js";
import {
TALENT_STUFEN, TALENT_GRUPPEN, TALENT_MERKMALE, TALENT_WARNZEICHEN,
TALENT_NACH_SCHLUESSEL, talentStufe, talentNaechste,
TALENT_NACH_SCHLUESSEL, talentStufe, talentNaechste, ansprechtext,
} from "./workspace-talent-punkte.js";
export const entwicklungRouter = express.Router();
@@ -437,6 +437,96 @@ entwicklungRouter.put("/workspace/api/entwicklung/mich/:schluessel", gleicheHerk
}
});
/* ---------- Die eigene Karte ------------------------------------------
Filipes Frage aus dem Plan, Punkt 2: "Sieht die Person ihre eigene
Entwicklungskarte?" -- und die Antwort war ja, aber unter zwei
Bedingungen. Beide sind hier gebaut, und beide sind der Grund, warum
es ueberhaupt geht:
ERST, WENN ALLE GESETZT HABEN. Eine halbe Karte ist schlimmer als
keine: Wer sieht, dass einer "da hakt es" gesetzt hat und der andere
noch nichts, liest daraus einen Streit, den es nicht gibt.
WER "ALLE" IST, wird gerechnet, nicht angenommen: alle aktiven
Personen, die das Team fuehren -- OHNE die Person selbst. Sonst
muesste die rechte Hand sich erst selbst beurteilen, um zu sehen,
was DogFather ueber sie denkt.
OHNE NAMEN UND OHNE ANLASS. Sie sieht "2x Laeuft" oder "1x Laeuft,
1x Waechst gerade" -- nicht, wer was gesetzt hat, und nicht, was
danebengeschrieben steht. Der Anlass ist fuer ein Gespraech
aufgeschrieben, nicht zum Lesen ohne den Menschen dazu. Genau
deshalb steht auf der Seite der Satz, dass man danach fragen soll.
UND WER GAR KEINE KARTE HAT, bekommt das gesagt. DogFather steht
nicht in KARTEN_ROLLEN -- eine leere Seite waere fuer ihn ein
Fehler, ein Satz ist eine Auskunft.
------------------------------------------------------------------- */
entwicklungRouter.get("/workspace/api/entwicklung/meine-karte", (req, res) => {
try {
if (!KARTEN_ROLLEN.includes(req.person.rolle)) {
return res.json({ hat_karte: false });
}
/* Wer ueber diese Person urteilt -- alle ausser ihr selbst. */
const beurteiler = db().prepare(
"SELECT id FROM personen WHERE rolle IN ('admin','hand') AND aktiv = 1 AND id <> ?")
.all(req.person.id).map((z) => z.id);
const staende = db().prepare(
"SELECT schluessel, von_id, stufe, am FROM entwicklung_stand WHERE person_id = ?")
.all(req.person.id).filter((z) => beurteiler.includes(z.von_id));
const nachPunkt = new Map();
for (const z of staende) {
if (!nachPunkt.has(z.schluessel)) nachPunkt.set(z.schluessel, []);
nachPunkt.get(z.schluessel).push(z);
}
const bloecke = ENTWICKLUNG_BLOECKE
.filter((b) => !b.nurSelbst)
.map((b) => ({
schluessel: b.schluessel, name: b.name, text: b.text,
punkte: (ENTWICKLUNG_PUNKTE[b.schluessel] || []).map((pt) => {
const liste = nachPunkt.get(pt.schluessel) || [];
/* VOLLSTAENDIG heisst: jeder Beurteiler hat gesetzt. */
const fertig = beurteiler.length > 0 && liste.length >= beurteiler.length;
if (!fertig) {
return { schluessel: pt.schluessel, titel: pt.titel, stufe: pt.stufe, offen: true };
}
const zaehler = {};
for (const z of liste) zaehler[z.stufe] = (zaehler[z.stufe] || 0) + 1;
return {
schluessel: pt.schluessel, titel: pt.titel, stufe: pt.stufe, offen: false,
/* Nach der Reihenfolge des Katalogs, nicht nach Haeufigkeit
-- sonst stuende bei einer Abweichung mal das eine, mal
das andere zuerst, und das liest sich wie eine Wertung. */
antworten: ENTWICKLUNG_STUFEN
.filter((x) => zaehler[x.schluessel])
.map((x) => ({ stufe: x.schluessel, name: x.name, anzahl: zaehler[x.schluessel] })),
einig: new Set(liste.map((z) => z.stufe)).size === 1,
am: liste.map((z) => z.am).sort().at(-1) || null,
};
}),
}));
const alle = bloecke.flatMap((b) => b.punkte);
res.json({
hat_karte: true,
beurteiler: beurteiler.length,
fertig: alle.filter((x) => !x.offen).length,
gesamt: alle.length,
stufen: ENTWICKLUNG_STUFEN,
erwartung: ENTWICKLUNG_ERWARTUNG,
bloecke,
});
} catch (f) {
console.error("[entwicklung] Meine Karte:", f?.message);
res.status(503).json({ fehler: "nicht_verfuegbar" });
}
});
/* ---------- Die Ampel ohne Namen -------------------------------------- */
/* WAS HIER HERAUSKOMMT UND WAS NICHT.
@@ -541,6 +631,11 @@ function talentKarte(e, merkmale) {
merkmale: gesetzt.filter((s) => !TALENT_NACH_SCHLUESSEL.get(s)?.warnung),
warnzeichen: warn,
notiz: stand?.notiz || null,
/* DER VORLAGENTEXT -- gebaut aus den Merkmalen, die wirklich
angeklickt wurden. Er kommt MIT der Karte und nicht ueber einen
eigenen Weg: Er aendert sich mit jedem Klick, und ein Text, den
man extra abrufen muss, ist beim Abrufen schon veraltet. */
ansprechtext: ansprechtext(e.titel, gesetzt),
};
}
+119 -23
View File
@@ -73,13 +73,13 @@ export const TALENT_STUFEN = [
{
schluessel: "probe", name: "Probe", rang: 4, frist: 30,
bedeutet: "Echte Schicht, kleiner Rahmen, fester Buddy – 30 Tage, beidseitig ausgesprochen.",
schritt: "Nach 30 Tagen: übernehmen oder sauber beenden.",
schritt: "Nach 30 Tagen: übernehmen – der Zugang entsteht dabei – oder sauber beenden.",
knopf: "Ins Team",
},
{
schluessel: "imteam", name: "Im Team", rang: 5, frist: null,
bedeutet: "Zugang steht. Ab hier zählt die Entwicklungskarte, nicht mehr diese.",
schritt: "Zugang in „Personen & Zugänge“ anlegen, Rolle Modi.",
schritt: "Nichts mehr zu tun – der Zugang steht, ab hier zählt die Entwicklungskarte.",
knopf: null,
},
];
@@ -116,58 +116,79 @@ export const TALENT_GRUPPEN = [
export const TALENT_MERKMALE = {
ruhe: [
{ schluessel: "t-ruhe-streit", titel: "Bleibt ruhig, wenn im Chat gestritten wird",
{ schluessel: "t-ruhe-streit", du: "auch dann ruhig bleibst, wenn es im Chat hitzig wird",
titel: "Bleibt ruhig, wenn im Chat gestritten wird",
text: "Der Normalfall, an dem sich alles zeigt." },
{ schluessel: "t-ruhe-provokation", titel: "Geht auf Provokation nicht ein",
{ schluessel: "t-ruhe-provokation", du: "auf Provokation nicht anspringst",
titel: "Geht auf Provokation nicht ein",
text: "Nicht ignorieren – nicht mitgehen. Zwei verschiedene Dinge." },
{ schluessel: "t-ruhe-widerspricht", titel: "Widerspricht, ohne auszuteilen",
{ schluessel: "t-ruhe-widerspricht", du: "widersprichst, ohne auszuteilen",
titel: "Widerspricht, ohne auszuteilen",
text: "Wer nie widerspricht, ist nicht ruhig, sondern still. Das ist etwas anderes." },
{ schluessel: "t-ruhe-gegen-sich", titel: "Hat sich auch dann im Griff, wenn es gegen ihn selbst geht",
{ schluessel: "t-ruhe-gegen-sich", du: "dich sogar dann im Griff hast, wenn es gegen dich selbst geht",
titel: "Hat sich auch dann im Griff, wenn es gegen ihn selbst geht",
text: "Der härteste der vier – und der aussagekräftigste." },
],
hilft: [
{ schluessel: "t-hilft-vor-team", titel: "Beantwortet Fragen anderer, bevor jemand vom Team da ist",
{ schluessel: "t-hilft-vor-team", du: "Fragen von anderen beantwortest, bevor jemand von uns da ist",
titel: "Beantwortet Fragen anderer, bevor jemand vom Team da ist",
text: "Tut die Arbeit schon, ohne den Titel zu haben." },
{ schluessel: "t-hilft-erklaert-neuen", titel: "Erklärt Neuen, wie es hier läuft",
{ schluessel: "t-hilft-erklaert-neuen", du: "Neuen erklärst, wie es hier läuft",
titel: "Erklärt Neuen, wie es hier läuft",
text: "Setzt voraus, dass er es selbst verstanden hat." },
{ schluessel: "t-hilft-meldet-statt-moderiert", titel: "Meldet etwas, statt selbst zu moderieren",
{ schluessel: "t-hilft-meldet-statt-moderiert", du: "Sachen meldest, statt selbst durchzugreifen",
titel: "Meldet etwas, statt selbst zu moderieren",
text: "Genau die richtige Grenze zu kennen, ist das eigentliche Signal – "
+ "wer ohne Rolle durchgreift, wird es mit Rolle erst recht." },
{ schluessel: "t-hilft-unbeobachtet", titel: "Hilft auch dann, wenn es niemand sieht",
{ schluessel: "t-hilft-unbeobachtet", du: "auch dann hilfst, wenn gerade niemand hinsieht",
titel: "Hilft auch dann, wenn es niemand sieht",
text: "Schwer zu beobachten, deshalb selten angeklickt – und wenn, dann zählt es." },
],
haus: [
{ schluessel: "t-haus-regeln", titel: "Kennt die Regeln, ohne sie nachzulesen",
{ schluessel: "t-haus-regeln", du: "die Regeln hier kennst, ohne nachzulesen",
titel: "Kennt die Regeln, ohne sie nachzulesen",
text: "Und wendet sie im Gespräch an, nicht als Zitat." },
{ schluessel: "t-haus-leute", titel: "Kennt die Leute – weiß, wer wer ist",
{ schluessel: "t-haus-leute", du: "die Leute kennst und weißt, wer wer ist",
titel: "Kennt die Leute – weiß, wer wer ist",
text: "Ein halbes Jahr Einarbeitung, die schon passiert ist." },
{ schluessel: "t-haus-witze", titel: "Versteht die Witze, die nur hier funktionieren",
{ schluessel: "t-haus-witze", du: "die Witze verstehst, die nur hier funktionieren",
titel: "Versteht die Witze, die nur hier funktionieren",
text: "Klingt nebensächlich und ist der Unterschied zwischen Gast und Zuhause." },
{ schluessel: "t-haus-frueh-dabei", titel: "War schon da, als es kleiner war",
{ schluessel: "t-haus-frueh-dabei", du: "schon dabei warst, als es hier noch kleiner war",
titel: "War schon da, als es kleiner war",
text: "Nicht mehr wert – aber belastbarer, weil länger beobachtet." },
],
da: [
{ schluessel: "t-da-regelmaessig", titel: "Über Wochen regelmäßig, nicht nur bei den großen Streams",
{ schluessel: "t-da-regelmaessig", du: "über Wochen regelmäßig da bist, nicht nur bei den großen Streams",
titel: "Über Wochen regelmäßig, nicht nur bei den großen Streams",
text: "Regelmäßigkeit ist planbar, Begeisterung nicht." },
{ schluessel: "t-da-auch-wenig-los", titel: "Auch dann, wenn wenig los ist",
{ schluessel: "t-da-auch-wenig-los", du: "auch dann kommst, wenn wenig los ist",
titel: "Auch dann, wenn wenig los ist",
text: "Die kleinen Streams sind der ehrlichere Test." },
{ schluessel: "t-da-luecke", titel: "Zu Zeiten, zu denen wir niemanden haben",
{ schluessel: "t-da-luecke", du: "oft genau dann da bist, wenn wir sonst niemanden haben",
titel: "Zu Zeiten, zu denen wir niemanden haben",
text: "Operativ der entscheidendste Punkt der ganzen Liste: Ein guter Kandidat "
+ "zur falschen Zeit löst kein einziges Problem." },
{ schluessel: "t-da-kommt-wieder", titel: "Kommt nach einer Pause von selbst wieder",
{ schluessel: "t-da-kommt-wieder", du: "nach einer Pause von selbst wieder auftauchst",
titel: "Kommt nach einer Pause von selbst wieder",
text: "Pausen sind normal. Wiederkommen ist das Signal." },
],
empfohlen: [
{ schluessel: "t-emp-vom-team", titel: "Von jemandem aus dem Team vorgeschlagen",
{ schluessel: "t-emp-vom-team", du: "jemandem aus dem Team aufgefallen bist",
titel: "Von jemandem aus dem Team vorgeschlagen",
text: "Ein Augenpaar, das den Alltag kennt." },
{ schluessel: "t-emp-mehrfach", titel: "Mehr als eine Person hat unabhängig denselben Namen genannt",
{ schluessel: "t-emp-mehrfach", du: "gleich mehreren aus dem Team unabhängig voneinander aufgefallen bist",
titel: "Mehr als eine Person hat unabhängig denselben Namen genannt",
text: "Der stärkste Einzelbefund im ganzen Katalog. Zwei unabhängige Nennungen "
+ "schlagen jede einzelne Beobachtung." },
{ schluessel: "t-emp-schicht-tauschen", titel: "Jemand aus dem Team würde eine Schicht mit ihm tauschen",
{ schluessel: "t-emp-schicht-tauschen", du: "jemand aus dem Team gern eine Schicht mit dir tauschen würde",
titel: "Jemand aus dem Team würde eine Schicht mit ihm tauschen",
text: "Die ehrlichste Frage, die man dem Team stellen kann." },
{ schluessel: "t-emp-schon-ausgeholfen", titel: "Hat schon mal ausgeholfen, ohne Rolle",
{ schluessel: "t-emp-schon-ausgeholfen", du: "schon mal ausgeholfen hast, ohne dass du musstest",
titel: "Hat schon mal ausgeholfen, ohne Rolle",
text: "Der beste verfügbare Beweis – er hat es getan." },
{ schluessel: "t-emp-von-zuschauer", titel: "Wurde von einem Zuschauer vorgeschlagen",
{ schluessel: "t-emp-von-zuschauer", du: "auch anderen Zuschauern aufgefallen bist",
titel: "Wurde von einem Zuschauer vorgeschlagen",
text: "Schwächer als eine Nennung aus dem Team, aber es zählt." },
],
};
@@ -217,6 +238,81 @@ export const TALENT_NACH_SCHLUESSEL = new Map([
export const talentStufe = (s) =>
TALENT_STUFEN.find((x) => x.schluessel === s) || null;
/* =====================================================================
DER VORLAGENTEXT ZUM ANSPRECHEN (11.09.2026)
=====================================================================
Auf Stufe 2 steht als naechster Schritt "Ansprechen". Bis heute stand
daneben "der Vorlagentext liegt bereit" -- und es gab keinen. Ein
Versprechen an eine Schublade.
ER WIRD GEBAUT, NICHT ABGESCHRIEBEN. Aus den Merkmalen, die wirklich
angeklickt wurden. Ein allgemeiner Text ("wir fanden dich toll")
klingt wie ein Serienbrief, weil er einer ist; drei konkrete
Beobachtungen klingen nach jemandem, der hingesehen hat -- und das
ist der Unterschied, ob jemand zusagt.
HOECHSTENS DREI. Wer fuenf Beobachtungen auflistet, klingt nach
Personalakte. Die drei kommen in der Reihenfolge des Katalogs, und
die faengt bei "Ruhe" an -- dem am besten belegten Merkmal.
DREI SAETZE, DIE IMMER DRINSTEHEN, und jeder hat einen Grund:
* "kein Druck, sag ruhig nein" -- wer sich gedraengt fuehlt, sagt
ja und hoert nach drei Wochen auf.
* "30 Tage, danach schauen wir beide" -- die Probezeit wird
BEIDSEITIG ausgesprochen. Wer weiss, dass er ohne Gesichtsverlust
wieder gehen kann, sagt eher ehrlich, wie es ihm damit geht.
* "du musst nichts koennen" -- die haeufigste Absage kommt nicht
aus Desinteresse, sondern aus der Annahme, man muesse etwas
mitbringen.
ER WIRD NICHT VERSCHICKT. Er steht da zum Kopieren. Eine Nachricht,
die ein Programm verschickt, liest sich wie eine Nachricht, die ein
Programm verschickt hat. */
export function ansprechtext(name, gesetzteMerkmale) {
/* NUR DAS ERSTE WORT. Im Brett steht selten ein Name allein --
"Kessi aus dem Chat" ist eine Notiz, keine Anrede. "Hey Kessi aus
dem Chat," liest sich wie ein Serienbrief, und genau das soll der
Text nicht sein.
Es ist eine VORLAGE zum Kopieren, keine Nachricht, die abgeschickt
wird -- wer den Namen anders schreiben will, tut das im Text. */
const sauber = String(name || "").trim().split(/[\s,(–-]+/)[0].trim() || "du";
const beobachtet = (gesetzteMerkmale || [])
.map((sch) => TALENT_ALLE.find((m) => m.schluessel === sch)?.du)
.filter(Boolean)
.slice(0, 3);
const mitte = beobachtet.length
? "Mir ist aufgefallen, dass du " + (beobachtet.length === 1
? beobachtet[0]
: beobachtet.slice(0, -1).join(", ") + " und " + beobachtet[beobachtet.length - 1]) + "."
: "Du bist mir hier schon öfter positiv aufgefallen.";
/* ECHTE UMLAUTE UND ECHTE STRICHE.
In Kommentaren schreibt dieses Haus ASCII; in TEXT, den jemand
liest, nicht. Der erste Entwurf stand voller "Haettest" und
"koennen" -- und dieser Text hier ist der einzige im ganzen
Bereich, den ein Fremder zu sehen bekommt. "Haettest du Lust" sieht
aus wie ein Fehler, weil es einer ist. Derselbe Befund stand schon
am 10.09. in workspace-personen.js. */
return [
`Hey ${sauber},`,
"",
mitte,
"",
"Deshalb die Frage: Hättest du Lust, bei uns im Mod-Team mitzumachen?",
"",
"Du musst dafür nichts können – alles, was es zu wissen gibt, zeigen wir dir. "
+ "Wir würden mit 30 Tagen anfangen, und danach schauen wir beide, ob es passt. "
+ "Wenn nicht, ist das völlig in Ordnung und ändert nichts.",
"",
"Und ganz wichtig: kein Druck. Sag ruhig nein oder „gerade nicht“ – "
+ "das nehme ich dir null übel.",
].join("\n");
}
/** Die naechste Stufe -- oder null am Ende des Trichters. */
export function talentNaechste(s) {
const i = TALENT_STUFEN.findIndex((x) => x.schluessel === s);
+4 -4
View File
@@ -13,25 +13,25 @@
"theme_color": "#06090f",
"icons": [
{
"src": "/assets/img/app-symbole/workspace-192.png?v=202609112230",
"src": "/assets/img/app-symbole/workspace-192.png?v=202609112313",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/workspace-512.png?v=202609112230",
"src": "/assets/img/app-symbole/workspace-512.png?v=202609112313",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609112230",
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609112313",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609112230",
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609112313",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
+64
View File
@@ -363,3 +363,67 @@
.t-karte__warn { margin-left: 0; }
.e-punkt__text, .e-block__satz { font-size: .88rem; }
}
/* =====================================================================
DER VORLAGENTEXT UND DIE EIGENE KARTE (11.09.2026)
===================================================================== */
.t-text {
margin: 14px 0 0; padding: 15px 17px;
background: rgba(0, 0, 0, .3);
border: 1px solid var(--rand-hell);
}
.t-text__titel { margin: 0 0 5px; font-size: .95rem; font-weight: 640; color: var(--text); }
.t-text__satz {
margin: 0 0 11px; max-width: 62ch;
font-size: .82rem; line-height: 1.6; color: var(--text-leise);
}
.t-text__feld {
display: block; width: 100%;
font: inherit; font-size: .86rem; line-height: 1.65;
padding: 11px 13px; resize: vertical;
color: var(--text);
background: rgba(0, 0, 0, .35);
border: 1px solid var(--rand);
}
.t-text__knoepfe { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 11px; }
/* Zwei, die seit dem Bau der Seite ohne eigene Regel dastanden: der
Knopf am naechsten Schritt und die Beschriftung eines Merkmals. Sie
sahen richtig aus, weil .schritt und .t-merkmal sie getragen haben --
aber wer eines davon umbaut, merkt es hier nicht. */
.t-schritt__knopf { margin-top: 2px; }
.t-schritt__text { margin-top: 2px; }
.t-merkmal__titel { text-align: left; line-height: 1.35; }
/* DIE EIGENE KARTE HAT KEINE KNOEPFE. Hier wird nichts gesetzt, hier
wird gelesen -- deshalb ein anderer Grund als auf der Karte, auf der
man klickt, und kein einziges anklickbares Feld darin. */
.e-meine {
margin: 30px 0 0; padding: 20px 22px;
border: 1px solid var(--rand);
background: color-mix(in srgb, var(--tinte) 94%, #ffffff 6%);
}
.e-meine__satz {
margin: 0 0 16px; max-width: 64ch;
font-size: .88rem; line-height: 1.65; color: var(--text-leise);
}
.e-punkt--meine { background: rgba(0, 0, 0, .2); }
.e-meine__antworten { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }
.e-meine__antwort {
font-size: .8rem; font-weight: 600; padding: 4px 11px; border-radius: 999px;
color: var(--text-leise);
border: 1px solid var(--rand-hell);
}
.e-meine__antwort[data-stufe="laeuft"] {
color: var(--text); border-color: color-mix(in srgb, #668e6e 55%, transparent);
}
.e-meine__antwort[data-stufe="waechst"] {
color: var(--text); border-color: color-mix(in srgb, #8ec9ff 50%, transparent);
}
.e-meine__antwort[data-stufe="hakt"] {
color: var(--text); border-color: color-mix(in srgb, #cc9451 55%, transparent);
}
/* „Darüber seid ihr euch nicht einig“ ist keine Warnung, sondern eine
Einladung zu fragen – deshalb leise und ohne Farbe. */
.e-meine__uneinig { font-size: .78rem; color: var(--text-still); font-style: italic; }
+6 -20
View File
@@ -41,27 +41,13 @@
.person__knoepfe { display: flex; gap: 7px; flex-wrap: wrap; justify-content: flex-end; }
/* ---------- Code-Anzeige ---------------------------------------------- */
/* ---------- Code-Anzeige ----------------------------------------------
.code-kasten {
margin: 0 0 26px; padding: 20px 22px;
background: linear-gradient(100deg, rgba(63, 189, 245, .12), rgba(138, 118, 255, .09));
border: 1px solid rgba(63, 189, 245, .5);
border-radius: var(--radius);
}
.code-kasten__schild {
margin: 0 0 8px; font-size: .78rem; font-weight: 600;
letter-spacing: .06em; text-transform: uppercase; color: var(--text-leise);
}
.code-kasten__code {
margin: 0 0 12px;
font-family: "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
font-size: clamp(1.3rem, 3.4vw, 1.9rem); font-weight: 700;
letter-spacing: .12em; color: #eaf4fd;
user-select: all; /* ein Klick markiert den ganzen Code */
word-break: break-all;
}
.code-kasten__hinweis { margin: 0 0 14px; font-size: .85rem; color: var(--text-leise); }
STEHT SEIT DEM 11.09.2026 IN start.css. Nicht aufgeraeumt, sondern
umgezogen: Seit dem Talente-Trichter entsteht ein Zugang an zwei
Stellen, und talente.html laedt diese Datei nicht. Der Kasten waere
dort unsichtbar gewesen -- ein Code in weisser Grundschrift, ohne
Rahmen, mitten im Text. Gesucht unter ".code-kasten" in start.css. */
/* ---------- Protokoll --------------------------------------------------- */
+33
View File
@@ -7845,3 +7845,36 @@ body.start .k-leiste .feldschild::after {
fill: none; stroke: currentColor; stroke-width: 1.8;
stroke-linecap: round; stroke-linejoin: round;
}
/* =====================================================================
DIE CODE-ANZEIGE (umgezogen aus personen.css, 11.09.2026)
Ein Zugangscode wird im ganzen Haus nur an zwei Stellen sichtbar:
in "Personen & Zugaenge" und am Ende des Talente-Trichters. Beide
zeigen ihn gleich -- gleiche Kante, gleiche Schrift, gleicher Satz
darunter. Zwei Gestaltungen fuer dasselbe Geheimnis waeren zwei
Gelegenheiten, eine davon zu vergessen.
Er steht hier und nicht in module.css: module.css beschreibt die
Form ALLER Karten, das hier ist ein einzelner Baustein.
===================================================================== */
.code-kasten {
margin: 0 0 26px; padding: 20px 22px;
background: linear-gradient(100deg, rgba(63, 189, 245, .12), rgba(138, 118, 255, .09));
border: 1px solid rgba(63, 189, 245, .5);
border-radius: var(--radius);
}
.code-kasten__schild {
margin: 0 0 8px; font-size: .78rem; font-weight: 600;
letter-spacing: .06em; text-transform: uppercase; color: var(--text-leise);
}
.code-kasten__code {
margin: 0 0 12px;
font-family: "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
font-size: clamp(1.3rem, 3.4vw, 1.9rem); font-weight: 700;
letter-spacing: .12em; color: #eaf4fd;
user-select: all; /* ein Klick markiert den ganzen Code */
word-break: break-all;
}
.code-kasten__hinweis { margin: 0 0 14px; font-size: .85rem; color: var(--text-leise); }
+17 -3
View File
@@ -861,14 +861,28 @@
NICHT aufgesetzt -- sie erlaubt getippte Namen, und genau das
soll es hier nicht geben. */
if (einstellung.ohneCreatorBezug) {
/* DAS WORT KOMMT VOM SERVER (11.09.2026).
Hier stand fest "Agentur" -- richtig auf der Agenturadresse,
falsch auf jeder anderen. Filipe, mit Bildschirmfoto: "auf
dieser seite soll nichts stehen von agentur, diese seite hier
ist nur für mich meine modis und meine community."
Der Server weiss, welches Brett es ist und in welchem Haus
die Person steht; er schickt das Wort mit (daten.gehoert).
Faellt die Angabe aus, bleibt das Feld LEER statt falsch --
ein fehlendes Wort sieht man, ein falsches nicht. */
const gehoert = daten?.gehoert || '';
$('schild-creator').textContent = 'Gilt für';
$('f-creator').textContent = '';
const o = document.createElement('option');
o.value = ''; o.textContent = 'Agentur';
o.value = ''; o.textContent = gehoert || '—';
$('f-creator').append(o);
const hinweis = $('hinweis-creator');
hinweis.textContent = 'Agentur-Einträge gehören allen – jeder im Workspace sieht sie.';
hinweis.hidden = false;
hinweis.textContent = gehoert
? `Gehört allen hier – wer ${gehoert} sieht, sieht auch diesen Eintrag.`
: '';
hinweis.hidden = !gehoert;
} else {
try {
const { personen } = await (await hole('/workspace/api/personen')).json();
+67
View File
@@ -244,6 +244,72 @@
return z;
}
/* ---- Deine eigene Karte -----------------------------------------------
WAS HIER STEHT UND WAS NICHT: die Antworten, nicht die Namen, und
nicht der Anlass. „2 × Läuft" oder „1 × Läuft, 1 × Wächst gerade".
Der Anlass ist für ein Gespräch aufgeschrieben, nicht zum Lesen
ohne den Menschen dazu — deshalb steht hier stattdessen der Satz,
dass man danach fragen soll. Ein Satz aus einer Notiz, aus dem
Zusammenhang gerissen, richtet mehr an, als er erklärt. */
async function meineKarte() {
let a;
try { a = await hole('/workspace/api/entwicklung/meine-karte'); } catch { return; }
if (!a.ok) return;
const r = await a.json();
if (!r.hat_karte) return; // DogFather hat keine
$('karte-block').hidden = false;
const satz = $('karte-satz');
const ziel = $('meine-karte');
ziel.textContent = '';
ziel.setAttribute('aria-busy', 'false');
if (!r.beurteiler) {
satz.textContent = 'Es gibt gerade niemanden, der sie führt. Sobald jemand '
+ 'da ist, steht hier etwas.';
return;
}
if (!r.fertig) {
satz.textContent = `Noch nichts fertig. Eine Beobachtung erscheint hier erst, `
+ `wenn alle ${r.beurteiler} sie gesetzt haben – eine halbe Karte ist `
+ `schlimmer als keine.`;
return;
}
satz.textContent = `${r.fertig} von ${r.gesamt} Beobachtungen sind durch. `
+ 'Du siehst die Antworten, nicht wer was gesetzt hat – und nicht, was '
+ 'danebengeschrieben steht. Das gehört ins Gespräch: frag danach.';
for (const b of r.bloecke) {
const fertige = b.punkte.filter((pt) => !pt.offen);
if (!fertige.length) continue;
const abschnitt = el('section', 'e-block');
abschnitt.append(el('h3', 'e-block__titel', b.name));
for (const pt of fertige) {
const zeile = el('article', 'e-punkt e-punkt--meine');
if (pt.einig) zeile.dataset.stufe = pt.antworten[0].stufe;
zeile.append(el('h4', 'e-punkt__titel', pt.titel));
const antw = el('div', 'e-meine__antworten');
for (const x of pt.antworten) {
const chip = el('span', 'e-meine__antwort', `${x.anzahl} × ${x.name}`);
chip.dataset.stufe = x.stufe;
antw.append(chip);
}
if (!pt.einig) {
const hin = el('span', 'e-meine__uneinig', 'darüber seid ihr euch nicht einig');
hin.title = 'Zwei Leute haben dasselbe verschieden gesehen. Das ist normal – '
+ 'und ein guter Anlass, danach zu fragen.';
antw.append(hin);
}
zeile.append(antw);
abschnitt.append(zeile);
}
ziel.append(abschnitt);
}
}
/* ---- Die eigenen sechs Fragen ---------------------------------------- */
async function meins() {
const a = await hole('/workspace/api/entwicklung/mich');
@@ -305,6 +371,7 @@
'Sechs Fragen über dich. Niemand aus dem Team sieht deine Antworten.';
}
await meineKarte();
await meins();
} catch { /* umgeleitet */ }
})();
+198 -4
View File
@@ -37,6 +37,7 @@
}
let lage = null;
let darfAnlegen = false; // darf ich hier einen Modi-Zugang anlegen?
const offen = new Set(); // welche Karten aufgeklappt sind
/* ---- Der Trichter oben ---------------------------------------------- */
@@ -86,23 +87,64 @@
ist, und nicht erst eine Entscheidung treffen müssen. */
const schritt = el('div', 't-schritt');
schritt.append(el('p', 't-schritt__satz', k.schritt));
if (k.knopf && k.naechste) {
const b = el('button', 'schritt t-schritt__knopf', k.knopf);
/* DER LETZTE SCHRITT IST KEIN SCHRITT, SONDERN EINE ENTSCHEIDUNG.
Aus einem Namen wird ein Mensch mit einem Zugang. Deshalb haengt
genau daran das Anlegen selbst -- und nicht ein Satz, den man
danach von Hand nachbaut. Bis heute stand hier "Zugang in
Personen & Zugaenge anlegen, Rolle Modi", und wer das vergass,
hatte eine Karte auf "Im Team" und keinen Menschen darin. */
const zugangNoetig = k.naechste === 'imteam';
if (k.knopf && k.naechste && (!zugangNoetig || darfAnlegen)) {
const b = el('button', 'schritt t-schritt__knopf',
zugangNoetig ? 'Ins Team holen · Zugang anlegen' : k.knopf);
b.type = 'button';
b.addEventListener('click', async () => {
b.disabled = true;
let zugang = null;
if (zugangNoetig) {
zugang = await zugangAnlegen(k);
if (!zugang) { b.disabled = false; return; }
}
const r = await hole(`/workspace/api/talente/${k.id}/stufe`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ stufe: k.naechste }),
});
b.disabled = false;
if (!r.ok) { melde('Ging nicht.'); return; }
if (!r.ok) {
/* ZWEI DINGE SIND PASSIERT, EINES DAVON HAT GEKLAPPT. Ein
blosses "ging nicht" waere hier die gefaehrlichste
Auskunft von allen -- der Zugang steht ja, und niemand
wuesste es. */
melde(zugang
? `Der Zugang für ${zugang.name} steht – der Code steht oben. Nur die Karte `
+ 'blieb auf „Probe“. Bitte den Schritt gleich noch einmal setzen.'
: 'Ging nicht.');
return;
}
offen.add(k.id);
await laden();
});
schritt.append(b);
} else if (zugangNoetig && k.knopf) {
/* KEIN KNOPF INS LEERE. Die rechte Hand sieht den Trichter
vollstaendig, aber Zugaenge vergibt nur DogFather. Ein Knopf,
der ihr jedes Mal "darfst du nicht" antwortet, waere schlechter
als gar keiner -- er verspricht etwas. */
schritt.append(el('p', 't-schritt__liegt',
'Den Zugang legt DogFather an – sag ihm Bescheid. Die Karte bleibt so '
+ 'lange auf „Probe“.'));
}
/* DER VORLAGENTEXT -- genau auf der Stufe, auf der er gebraucht
wird. Eine Schaltfläche „Text anzeigen" auf jeder Stufe wäre auf
vier von fünf davon eine Ablenkung. */
if (k.stufe === 'beobachtet' && k.ansprechtext) {
const b = el('button', 'schritt t-schritt__text', 'Vorlagentext');
b.type = 'button';
b.addEventListener('click', () => textZeigen(k));
schritt.append(b);
}
if (k.liegt) {
schritt.append(el('p', 't-schritt__liegt',
'Das liegt länger, als es sollte. Entweder weiter – oder bewusst beenden.'));
@@ -150,6 +192,139 @@
return a;
}
/* ---- Aus der Probe wird ein Zugang ---------------------------------
DERSELBE WEG WIE IN "PERSONEN & ZUGAENGE", nicht ein zweiter.
/workspace/api/verwaltung/personen ist die einzige Stelle im ganzen
Haus, an der ein Zugang entsteht -- mit ihrer Rechtepruefung, ihrer
Rollenpruefung, ihrem Protokolleintrag und ihrem genau einmal
angezeigten Code. Ein eigener Weg von hier waere eine zweite Tuer
zu genau dem, was am wenigsten zwei Tueren haben darf.
NICHT ueber hole(): Diese Adresse antwortet Nicht-DogFather mit
404, und hole() versteht ein 404 als "Seite gibt es nicht" und
schickt zur Startseite. Ein Rechtefehler wuerde die rechte Hand
also aus dem Trichter werfen. Hier wird deshalb selbst gelesen.
@returns {object|null} die angelegte Person, oder null bei Abbruch. */
async function zugangAnlegen(k) {
if (!darfAnlegen) { melde('Zugänge legt DogFather an.'); return null; }
const vorschlag = String(k.titel || '').split(/[\s,(–-]+/)[0] || '';
const name = prompt(
'Wie soll die Person im Workspace heißen?\n\n'
+ 'Das ist der Name, den euer Team sieht. Gleich danach bekommst du '
+ 'einmalig ihren Zugangscode – danach nie wieder.',
vorschlag);
if (name === null) return null; // abgebrochen
if (String(name).trim().length < 2) { melde('Der Name ist zu kurz.'); return null; }
let a;
try {
a = await fetch('/workspace/api/verwaltung/personen', {
credentials: 'same-origin',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: String(name).trim(), rolle: 'modi' }),
});
} catch { melde('Keine Verbindung – der Zugang wurde nicht angelegt.'); return null; }
if (a.status === 404 || a.status === 403) {
melde('Zugänge legt DogFather an – sag ihm Bescheid.');
return null;
}
if (!a.ok) {
const grund = (await a.json().catch(() => ({}))).fehler;
melde(grund || 'Der Zugang ließ sich nicht anlegen.');
return null;
}
const neu = await a.json();
codeZeigen(neu);
return neu;
}
/* Der Code steht in einem Kasten, den man SCHLIESSEN muss -- nicht in
einer Meldung, die von selbst verschwindet. Er ist das Einzige auf
dieser Seite, das es nur ein einziges Mal gibt. */
function codeZeigen(neu) {
$('code-name').textContent = `${neu.name} · Modi`;
$('code-wert').textContent = neu.code;
$('code-kasten').hidden = false;
$('code-kasten').scrollIntoView({ behavior: 'smooth', block: 'center' });
$('code-kopieren').focus();
}
$('code-kopieren')?.addEventListener('click', async () => {
const code = $('code-wert').textContent;
try { await navigator.clipboard.writeText(code); melde('Code kopiert.'); }
catch {
/* Ohne Zwischenablage-Recht: markieren, dann geht Strg+C. Der
Code steht ja da -- "ging nicht" waere hier unbrauchbar. */
getSelection()?.removeAllRanges();
const r = document.createRange();
r.selectNodeContents($('code-wert'));
getSelection()?.addRange(r);
melde('Markiert – mit Strg+C kopieren.');
}
});
$('code-schliessen')?.addEventListener('click', () => {
$('code-kasten').hidden = true;
$('code-wert').textContent = ''; // auch aus der Seite raus
melde('');
});
/* DER TEXT WIRD GEZEIGT, NICHT VERSCHICKT.
Eine Nachricht, die ein Programm abschickt, liest sich wie eine
Nachricht, die ein Programm abgeschickt hat — und genau das soll
dieser Text nicht sein. Er steht da zum Lesen, Ändern und
Kopieren, in einem Feld, das man bearbeiten kann. */
function textZeigen(k) {
const alt = document.getElementById('t-textfeld');
if (alt) alt.closest('.t-text')?.remove();
const kasten = el('div', 't-text');
kasten.append(el('h3', 't-text__titel', `Vorschlag für ${k.titel}`));
kasten.append(el('p', 't-text__satz',
'Gebaut aus den Merkmalen, die du angeklickt hast. Ändere ihn ruhig – '
+ 'er soll nach dir klingen, nicht nach einer Vorlage. Abgeschickt wird '
+ 'hier nichts.'));
const feld = el('textarea', 't-text__feld');
feld.id = 't-textfeld';
feld.rows = 14;
feld.value = k.ansprechtext;
kasten.append(feld);
const reihe = el('div', 't-text__knoepfe');
const kopieren = el('button', 'schritt', 'Kopieren');
kopieren.type = 'button';
kopieren.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(feld.value);
melde('Kopiert. Jetzt einfügen, wo du ihn ansprichst.');
} catch {
/* Ohne Zwischenablage-Recht: markieren, dann geht Strg+C.
Eine Fehlermeldung „ging nicht" wäre hier unbrauchbar — der
Text ist ja da. */
feld.select();
melde('Markiert – mit Strg+C kopieren.');
}
});
reihe.append(kopieren);
const zu = el('button', 'schritt', 'Schließen');
zu.type = 'button';
zu.addEventListener('click', () => kasten.remove());
reihe.append(zu);
kasten.append(reihe);
const karte = [...document.querySelectorAll('.t-karte')]
.find((x) => x.querySelector('.t-karte__titel')?.textContent === k.titel);
(karte || $('liste')).append(kasten);
feld.focus();
}
function merkmal(k, m, istWarnung) {
const gesetzt = (istWarnung ? k.warnzeichen : k.merkmale).includes(m.schluessel);
const b = el('button', 't-merkmal');
@@ -210,5 +385,24 @@
zeichne();
}
(async () => { try { await laden(); } catch { /* umgeleitet */ } })();
/* WER ZUGAENGE ANLEGEN DARF, SAGT DER SERVER -- dieselbe Auskunft,
aus der auch "Personen & Zugaenge" ihre Rollenknoepfe baut. Eine
eigene Rollenabfrage hier waere eine zweite Meinung darueber, und
die zweite ist die, die irgendwann mehr durchlaesst.
VOR dem ersten Zeichnen, nicht daneben: Sonst steht der Knopf
einen Wimpernschlag lang da und verschwindet wieder. */
async function ichHolen() {
try {
const a = await hole('/workspace/api/ich');
if (!a.ok) return;
const ich = await a.json();
window.werZeigen?.(ich);
darfAnlegen = Array.isArray(ich?.darf_anlegen) && ich.darf_anlegen.includes('modi');
} catch { /* umgeleitet */ }
}
(async () => {
try { await ichHolen(); await laden(); } catch { /* umgeleitet */ }
})();
})();
+12 -12
View File
@@ -12,19 +12,19 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -252,10 +252,10 @@
</form>
</dialog>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/aufgaben.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/aufgaben.js?v=202609112313" defer></script>
</body>
</html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/automation.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/automation.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -147,10 +147,10 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/automation.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/automation.js?v=202609112313" 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=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/bereich.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -181,14 +181,14 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/checkliste.js?v=202609112230" defer></script>
<script src="assets/js/ampel.js?v=202609112230" defer></script>
<script src="assets/js/schulung.js?v=202609112230" defer></script>
<script src="assets/js/vorlagen.js?v=202609112230" defer></script>
<script src="assets/js/bereich.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/checkliste.js?v=202609112313" defer></script>
<script src="assets/js/ampel.js?v=202609112313" defer></script>
<script src="assets/js/schulung.js?v=202609112313" defer></script>
<script src="assets/js/vorlagen.js?v=202609112313" defer></script>
<script src="assets/js/bereich.js?v=202609112313" defer></script>
</body>
</html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/calls.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/calls.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -89,11 +89,11 @@
</main>
<script src="assets/js/ki.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/calls.js?v=202609112230" defer></script>
<script src="assets/js/ki.js?v=202609112313" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/calls.js?v=202609112313" defer></script>
</body>
</html>
+13 -13
View File
@@ -12,26 +12,26 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/chat.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/chat.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -341,10 +341,10 @@
</form>
</dialog>
<script src="assets/js/bereiche.js?v=202609112230"></script>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230"></script>
<script src="assets/js/glocke.js?v=202609112230"></script>
<script src="assets/js/chat.js?v=202609112230"></script>
<script src="assets/js/bereiche.js?v=202609112313"></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313"></script>
<script src="assets/js/glocke.js?v=202609112313"></script>
<script src="assets/js/chat.js?v=202609112313"></script>
</body>
</html>
+15 -15
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/content.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/content.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -179,12 +179,12 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/checkliste.js?v=202609112230" defer></script>
<script src="assets/js/vorlagen.js?v=202609112230" defer></script>
<script src="assets/js/content.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/checkliste.js?v=202609112313" defer></script>
<script src="assets/js/vorlagen.js?v=202609112313" defer></script>
<script src="assets/js/content.js?v=202609112313" defer></script>
</body>
</html>
+5 -5
View File
@@ -36,15 +36,15 @@
<link rel="preload" as="image" href="assets/img/buehne/crew-gate-hoch-580.webp"
type="image/webp" media="(max-width: 899px)" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/crew-haus.css?v=202609112313" />
</head>
<body class="gate gate--crew">
@@ -319,6 +319,6 @@
</main>
</div>
<script src="assets/js/gate.js?v=202609112230" defer></script>
<script src="assets/js/gate.js?v=202609112313" defer></script>
</body>
</html>
+4 -4
View File
@@ -13,25 +13,25 @@
"theme_color": "#06090f",
"icons": [
{
"src": "/assets/img/app-symbole/crew-192.png?v=202609112230",
"src": "/assets/img/app-symbole/crew-192.png?v=202609112313",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/crew-512.png?v=202609112230",
"src": "/assets/img/app-symbole/crew-512.png?v=202609112313",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609112230",
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609112313",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609112230",
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609112313",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/dateien.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/dateien.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -108,10 +108,10 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/dateien.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/dateien.js?v=202609112313" defer></script>
</body>
</html>
+27 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -71,6 +71,21 @@
<section id="karte" class="e-karte" hidden></section>
<!-- DEINE EIGENE KARTE.
Sie steht ÜBER den sechs Fragen und UNTER der Liste der anderen:
Wer diese Seite als DogFather öffnet, kommt zuerst zu seiner
Arbeit; wer sie als Modi öffnet, sieht die Liste gar nicht und
landet direkt hier.
Sie erscheint erst, wenn alle gesetzt haben — eine halbe Karte
ist schlimmer als keine. -->
<section id="karte-block" class="e-meine" hidden>
<h2 class="e-abschnitt">Deine Karte</h2>
<p class="e-meine__satz" id="karte-satz">…</p>
<div id="meine-karte" aria-busy="true"></div>
</section>
<section id="meins-block" class="e-meins" hidden>
<h2 class="e-abschnitt" id="meins-titel">Wie geht es dir damit?</h2>
<p class="e-meins__satz" id="meins-satz">…</p>
@@ -79,9 +94,9 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/entwicklung.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/entwicklung.js?v=202609112313" defer></script>
</body>
</html>
+4 -4
View File
@@ -30,9 +30,9 @@
<link rel="preload" as="image" href="assets/img/buehne/gate-hoch-580.webp"
type="image/webp" media="(max-width: 899px)" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
</head>
<body class="gate">
@@ -401,6 +401,6 @@
</main>
</div>
<script src="assets/js/gate.js?v=202609112230" defer></script>
<script src="assets/js/gate.js?v=202609112313" defer></script>
</body>
</html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/kalender.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/kalender.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -377,11 +377,11 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/kalender.js?v=202609112230" defer></script>
<script src="assets/js/kalender-abo.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/kalender.js?v=202609112313" defer></script>
<script src="assets/js/kalender-abo.js?v=202609112313" defer></script>
</body>
</html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/leistung.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/leistung.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -382,10 +382,10 @@
</form>
</dialog>
<script src="assets/js/wahl.js?v=202609112230"></script>
<script src="assets/js/bereiche.js?v=202609112230"></script>
<script src="assets/js/kopf.js?v=202609112230"></script>
<script src="assets/js/glocke.js?v=202609112230"></script>
<script src="assets/js/leistung.js?v=202609112230"></script>
<script src="assets/js/wahl.js?v=202609112313"></script>
<script src="assets/js/bereiche.js?v=202609112313"></script>
<script src="assets/js/kopf.js?v=202609112313"></script>
<script src="assets/js/glocke.js?v=202609112313"></script>
<script src="assets/js/leistung.js?v=202609112313"></script>
</body>
</html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/personen.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/personen.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -423,10 +423,10 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/personen.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/personen.js?v=202609112313" defer></script>
</body>
</html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -214,11 +214,11 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/steckbrief.js?v=202609112230" defer></script>
<script src="assets/js/profil.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/steckbrief.js?v=202609112313" defer></script>
<script src="assets/js/profil.js?v=202609112313" defer></script>
</body>
</html>
+12 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -134,9 +134,9 @@
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
die seit dem 07.09. jede Seite danach absucht. -->
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/rechte.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/rechte.js?v=202609112313" defer></script>
</body>
</html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/report.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/report.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -106,11 +106,11 @@
</main>
<script src="assets/js/ki.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/report.js?v=202609112230" defer></script>
<script src="assets/js/ki.js?v=202609112313" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/report.js?v=202609112313" defer></script>
</body>
</html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/scouting.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/scouting.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -173,10 +173,10 @@
</div>
</div>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/scouting.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/scouting.js?v=202609112313" defer></script>
</body>
</html>
+12 -12
View File
@@ -12,21 +12,21 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/heim.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -674,10 +674,10 @@
</p>
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/start.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/start.js?v=202609112313" defer></script>
</body>
</html>
+14 -14
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/startcheck.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -85,11 +85,11 @@
</main>
<script src="assets/js/ki.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/startcheck.js?v=202609112230" defer></script>
<script src="assets/js/ki.js?v=202609112313" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/startcheck.js?v=202609112313" defer></script>
</body>
</html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/profil.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -126,10 +126,10 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/steckbrief.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/steckbrief.js?v=202609112313" defer></script>
</body>
</html>
+34 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -64,6 +64,28 @@
Öffentliches wird.
============================================================== -->
<!-- DER ZUGANGSCODE STEHT AUSSERHALB DER LISTE, und das ist kein
Schönheitsgrund. Die Liste wird nach jeder Änderung neu
gezeichnet – stünde der Kasten darin, wäre der Code in genau dem
Moment wieder weg, in dem er entsteht: wenn die Karte auf „Im
Team“ springt.
DERSELBEN KLASSEN WIE IN „PERSONEN & ZUGÄNGE“. Ein Geheimnis
sieht im ganzen Haus gleich aus – zwei Gestaltungen für dieselbe
Sache wären zwei Gelegenheiten, eine davon falsch zu machen. -->
<div class="code-kasten" id="code-kasten" hidden role="status" aria-live="polite">
<p class="code-kasten__schild">Zugangscode für <span id="code-name"></span></p>
<p class="code-kasten__code" id="code-wert"></p>
<p class="code-kasten__hinweis">
Dieser Code wird <strong>nur jetzt</strong> angezeigt und ist danach nicht mehr
abrufbar. Persönlich weitergeben und in Bitwarden ablegen.
</p>
<div class="t-text__knoepfe">
<button type="button" class="knopf knopf--klein" id="code-kopieren">Kopieren</button>
<button type="button" class="abmelden" id="code-schliessen">Verstanden, schließen</button>
</div>
</div>
<section id="trichter" class="t-trichter" aria-busy="true"></section>
<section id="liste" class="t-liste" aria-busy="true">
@@ -72,9 +94,9 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/talente.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/talente.js?v=202609112313" defer></script>
</body>
</html>
+13 -13
View File
@@ -7,20 +7,20 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/team.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/team.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -110,10 +110,10 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/team.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/team.js?v=202609112313" defer></script>
</body>
</html>
+12 -12
View File
@@ -7,20 +7,20 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/team.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/team.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<!-- `data-buehne` steht hier fest und nicht im Skript: Die Kachel zu
@@ -84,9 +84,9 @@
Kaputt ist dabei nichts -- er funktioniert. Genau deshalb faellt
es niemandem auf, und deshalb prueft pruef-css-klassen die
ABHAENGIGKEIT statt der Optik. Hier hat sie angeschlagen. -->
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/teamlage.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/teamlage.js?v=202609112313" defer></script>
</body>
</html>
+12 -12
View File
@@ -7,14 +7,14 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -110,9 +110,9 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/treff-moderation.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/treff-moderation.js?v=202609112313" defer></script>
</body>
</html>
+12 -12
View File
@@ -7,18 +7,18 @@
<meta name="robots" content="noindex, nofollow" />
<link rel="manifest" href="/workspace/app.webmanifest" />
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/treff.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- haus.css MUSS die letzte Stilvorlage sein. Auf der Adresse des
Treffs biegt der Server genau diesen Dateinamen auf crew-haus.css
um, und die Seite kommt schon beim ERSTEN Abruf in Lila und
Babyblau an -- ohne Umfaerben im Browser, ohne Flackern. -->
<link rel="stylesheet" href="assets/css/haus.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -190,9 +190,9 @@
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
die seit dem 07.09. jede Seite danach absucht. -->
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/treff-regeln.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/treff-regeln.js?v=202609112313" defer></script>
</body>
</html>
+13 -13
View File
@@ -12,22 +12,22 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<!-- Formular- und Dialogstile: seit dem 07.09.2026 steht hier der
Dialog "Creator anlegen". -->
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -149,11 +149,11 @@
</main>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/uebersicht.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/uebersicht.js?v=202609112313" defer></script>
</body>
</html>
+13 -13
View File
@@ -12,20 +12,20 @@
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
eine Flaeche sind statt zweier. -->
<meta name="theme-color" content="#06090f" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112230" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112230" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/wissen.css?v=202609112230" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112230" />
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202609112313" />
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202609112313" />
<link rel="stylesheet" href="assets/css/gate.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/start.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/wissen.css?v=202609112313" />
<link rel="stylesheet" href="assets/css/module.css?v=202609112313" />
<!-- 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=202609112230" />
<link rel="stylesheet" href="assets/css/haus.css?v=202609112313" />
</head>
<body class="start">
@@ -190,10 +190,10 @@
</main>
<script src="assets/js/wahl.js?v=202609112230" defer></script>
<script src="assets/js/bereiche.js?v=202609112230" defer></script>
<script src="assets/js/kopf.js?v=202609112230" defer></script>
<script src="assets/js/glocke.js?v=202609112230" defer></script>
<script src="assets/js/wissen.js?v=202609112230" defer></script>
<script src="assets/js/wahl.js?v=202609112313" defer></script>
<script src="assets/js/bereiche.js?v=202609112313" defer></script>
<script src="assets/js/kopf.js?v=202609112313" defer></script>
<script src="assets/js/glocke.js?v=202609112313" defer></script>
<script src="assets/js/wissen.js?v=202609112313" defer></script>
</body>
</html>