Agentur-Events: die Karte als Aushang, Aufgaben zum Abhaken
Filipe, mit einem Bildschirmfoto des Oktober-Events: "ich will das viel geiler viel perfekter. und auch wenn man die eintraegt und so soll viel mehr perfektioniert und uebersichtlicher sein." VORHER GEMESSEN (1280 px, eine einzige Eventkarte): Kartenhoehe 1196 px -- das Fenster ist 900 px davon Banner 638 px -- 53 %, ohne einen Buchstaben Titel steht bei 1482 px -- zweimal scrollen bis zum Namen Titelgroesse 15,36 px -- 1,4 px mehr als der Fliesstext Etikett 10,88 px -- unter der eigenen Grenze (11,5) Datum 3 x -- in drei Zeilen untereinander Knoepfe 4 x gleich -- "loeschen" wie "zur Aufgabe" NACHHER, dieselbe Messung: Karte 618 px, Buehne 203 px, Titel 75 px unter der Kartenkante und 24,8 px gross, Etikett 12 px, das Datum einmal, "loeschen" abgesetzt. DIE KARTE Das Banner ist nicht mehr ein Anhang ueber dem Titel, sondern die Buehne dahinter -- Hoehe gedeckelt, Titel darauf. Dazu die Frage, die bei einem Wettbewerb wirklich zaehlt und bisher nirgends beantwortet wurde: "noch 12 Tage", mit Zeitbalken. Ein Knopf "Banner ganz" holt das vollstaendige Bild zurueck, das beim Umbau sonst verloren gegangen waere -- bei Filipes Banner steht die Ansage IM Bild. DIE AUFGABEN Aus Fliesstext wird eine Liste, und jeder hakt fuer sich ab (neue Tabelle event_punkte, Schluessel aus dem Zeilentext). Umsortieren laesst den Haken, wo er ist; wird die Bedingung selbst umgeschrieben, faellt er -- beides nachgemessen. Die Leitung sieht, wer wie weit ist, eine Creatorin sieht diese Liste gar nicht erst. DAS FORMULAR Ein Feld je Zeile statt eines leeren Textfeldes. Im echten Event stand ".Jeden Tag Live gehen" neben ". 33k Diamanten erreichen" -- einmal mit Leerzeichen, einmal ohne. Das ist die zwangslaeufige Folge davon, dass die Aufzaehlungszeichen von Hand getippt werden; jetzt setzt sie das Formular. Dazu "Laeuft 14 Tage.", eine Warnung bei verdrehtem Zeitraum und eine Vorschau, die dieselbe Funktion benutzt wie die echte Karte. NEBENBEI GEFUNDEN UND BEHOBEN * Das Banner kam bei Creatorn mit 404 zurueck -- also an genau der Karte, die fuer sie gemacht ist. Die Regel "wer das Brett sieht, sieht das Bild" galt nur fuer die sieben Community-Bretter. Jetzt fragt der Bildweg dieselbe Regel wie das Brett (darfEintragSehen); die Gegenprobe zeigt, dass ein fremder Eintrag weiterhin 404 gibt. * Zwei Stellen setzten das Formular zurueck, die kuerzere liess Vorschau und Zeilen-Editor stehen -- beim naechsten "Neuer Eintrag" standen die Aufgaben des vorigen Events noch da. * Der Schriftgrund ragte auf dem Handy 6 px ueber die Karte (feste -20 px gegen 14 px Polsterung); jetzt an die Polsterung gekoppelt. GEPRUEFT pruef-eventkarte.mjs (neu): 77 Pruefungen, 0 Fehler -- mit Gegenproben zu jeder Zusage und einer Kontrastmessung am Bildpunkt auf einem weissen Banner (14,7:1; ohne den Schriftgrund 1,05:1). pruef-agentur.mjs auf die neuen Bausteine nachgezogen, Zahl unveraendert bei 62. pruef-eintrag-bild.mjs 24/0. OFFEN, NICHT AUS DIESEM UMBAU: Das Brett `agentur` ist auf der Crew-Adresse erreichbar. Zweimal gemessen, mit und ohne diese Aenderung -- gleiches Ergebnis. Gehoert zur Trennungsregel vom 24.09.2026 und wird getrennt entschieden. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
/* =====================================================================
|
||||||
|
EIN PNG SCHREIBEN (03.10.2026)
|
||||||
|
|
||||||
|
Das Gegenstueck zu helfer-png.mjs, das eines LIEST. Gebraucht fuer
|
||||||
|
die Eventkarten-Pruefung: Ob der Titel auf einer Buehne lesbar
|
||||||
|
bleibt, haengt davon ab, was fuer ein Banner darunter liegt -- und
|
||||||
|
der interessante Fall ist nicht das dunkle, sondern das HELLE, das
|
||||||
|
jemand spaeter hochlaedt. Ein solches Bild muss die Pruefung also
|
||||||
|
selbst herstellen koennen.
|
||||||
|
|
||||||
|
WARUM SELBST GESCHRIEBEN: Dieselbe Begruendung wie bei helfer-png.mjs
|
||||||
|
-- das Projekt hat kein Bildmodul, und fuer ein Testbild eines
|
||||||
|
nachzuinstallieren waere eine Abhaengigkeit, die jemand pflegen
|
||||||
|
muss. Node bringt zlib mit; ein unkomprimiertes RGB-PNG ist danach
|
||||||
|
nur noch Pruefsumme und Zeilenfilter.
|
||||||
|
===================================================================== */
|
||||||
|
import { deflateSync } from "node:zlib";
|
||||||
|
|
||||||
|
const tabelle = (() => {
|
||||||
|
const t = new Int32Array(256);
|
||||||
|
for (let n = 0; n < 256; n++) {
|
||||||
|
let c = n;
|
||||||
|
for (let k = 0; k < 8; k++) c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
|
||||||
|
t[n] = c;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
})();
|
||||||
|
function crc32(buf) {
|
||||||
|
let c = 0xffffffff;
|
||||||
|
for (let i = 0; i < buf.length; i++) c = tabelle[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
|
||||||
|
return (c ^ 0xffffffff) >>> 0;
|
||||||
|
}
|
||||||
|
function teil(name, inhalt) {
|
||||||
|
const kopf = Buffer.alloc(8);
|
||||||
|
kopf.writeUInt32BE(inhalt.length, 0);
|
||||||
|
kopf.write(name, 4, "ascii");
|
||||||
|
const pruef = Buffer.alloc(4);
|
||||||
|
pruef.writeUInt32BE(crc32(Buffer.concat([Buffer.from(name, "ascii"), inhalt])), 0);
|
||||||
|
return Buffer.concat([kopf, inhalt, pruef]);
|
||||||
|
}
|
||||||
|
/** male(x, y, b, h) -> [r,g,b] */
|
||||||
|
export function pngBauen(b, h, male) {
|
||||||
|
const roh = Buffer.alloc((b * 3 + 1) * h);
|
||||||
|
let p = 0;
|
||||||
|
for (let y = 0; y < h; y++) {
|
||||||
|
roh[p++] = 0;
|
||||||
|
for (let x = 0; x < b; x++) {
|
||||||
|
const f = male(x, y, b, h);
|
||||||
|
roh[p++] = f[0]; roh[p++] = f[1]; roh[p++] = f[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const ihdr = Buffer.alloc(13);
|
||||||
|
ihdr.writeUInt32BE(b, 0); ihdr.writeUInt32BE(h, 4);
|
||||||
|
ihdr[8] = 8; ihdr[9] = 2; ihdr[10] = 0; ihdr[11] = 0; ihdr[12] = 0;
|
||||||
|
return Buffer.concat([
|
||||||
|
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
|
||||||
|
teil("IHDR", ihdr),
|
||||||
|
teil("IDAT", deflateSync(roh, { level: 9 })),
|
||||||
|
teil("IEND", Buffer.alloc(0)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
@@ -697,33 +697,56 @@ melde("\n=== Die Kachel ===");
|
|||||||
Regeln koennen vollstaendig in der Antwort stehen und trotzdem
|
Regeln koennen vollstaendig in der Antwort stehen und trotzdem
|
||||||
nirgends gezeichnet werden -- ein vergessener Aufruf in karte()
|
nirgends gezeichnet werden -- ein vergessener Aufruf in karte()
|
||||||
reicht, und niemand merkt es, weil die Karte ja da ist. */
|
reicht, und niemand merkt es, weil die Karte ja da ist. */
|
||||||
|
/* ==== AUF DIE NEUE KARTE UMGESTELLT (03.10.2026) ================
|
||||||
|
|
||||||
|
Die Eventkarte wurde umgebaut (siehe pruef-eventkarte.mjs): Buehne
|
||||||
|
mit Titel auf dem Banner, Zeitraum einmal statt dreimal, Aufgaben
|
||||||
|
als Liste zum Abhaken. Dabei haben die Bausteine neue Namen
|
||||||
|
bekommen -- `.event-zeitraum__marke` heisst jetzt `.ev-noch`,
|
||||||
|
`.event-block__text` ist zu einer Liste aus `.ev-punkt__text`
|
||||||
|
geworden.
|
||||||
|
|
||||||
|
DIESE PRUEFUNG WURDE DESHALB NICHT GELOESCHT, SONDERN NACHGEZOGEN:
|
||||||
|
Sie sagt weiterhin dieselben FUENF Dinge zu, nur an der neuen
|
||||||
|
Stelle. Eine Pruefung wegzunehmen, weil sie nach einem Umbau rot
|
||||||
|
wird, senkt die Zahl und beweist danach nichts mehr
|
||||||
|
(Projektgedaechtnis, 28.08.2026: 789 statt 804 Pruefungen, und
|
||||||
|
acht davon fielen still weg).
|
||||||
|
|
||||||
|
WAS SICH INHALTLICH AENDERT: Der Zustand steht nicht mehr als
|
||||||
|
"laeuft bis TT.MM.JJJJ" da, sondern als "noch N Tage" -- dieselbe
|
||||||
|
Aussage, nur beantwortet sie jetzt die Frage, die man wirklich
|
||||||
|
hat. Geprueft wird deshalb auf ein WORT (nicht nur Farbe), nicht
|
||||||
|
mehr auf einen bestimmten Satz. */
|
||||||
const event = await seite.$$eval(".eintrag-karte", (karten) => {
|
const event = await seite.$$eval(".eintrag-karte", (karten) => {
|
||||||
const k = karten.find((x) => x.querySelector(".eintrag-titel")?.textContent.trim() === "Sommer-Aktion");
|
const k = karten.find((x) => x.querySelector(".eintrag-titel")?.textContent.trim() === "Sommer-Aktion");
|
||||||
if (!k) return null;
|
if (!k) return null;
|
||||||
return {
|
return {
|
||||||
stand: k.dataset.event,
|
stand: k.dataset.event,
|
||||||
marke: k.querySelector(".event-zeitraum__marke")?.textContent.trim(),
|
marke: k.querySelector(".ev-noch")?.textContent.trim(),
|
||||||
spanne: k.querySelector(".event-zeitraum__spanne")?.textContent.trim(),
|
spanne: k.querySelector(".ev-spanne")?.textContent.trim(),
|
||||||
schilder: [...k.querySelectorAll(".event-block__schild")].map((s) => s.textContent.trim()),
|
schilder: [...k.querySelectorAll(".ev-block__schild")].map((s) => s.textContent.trim()),
|
||||||
texte: [...k.querySelectorAll(".event-block__text")].map((s) => s.textContent.trim()),
|
texte: [...k.querySelectorAll(".ev-punkt__text")].map((s) => s.textContent.trim()),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
ok(!!event, "die Event-Karte Sommer-Aktion steht auf der Seite");
|
ok(!!event, "die Event-Karte Sommer-Aktion steht auf der Seite");
|
||||||
ok(event?.stand === "laeuft", `sie ist als laufend gekennzeichnet ("${event?.stand}")`);
|
ok(event?.stand === "laeuft", `sie ist als laufend gekennzeichnet ("${event?.stand}")`);
|
||||||
ok(/läuft bis/.test(event?.marke || ""),
|
/* Ein Wort, kein leerer Platzhalter -- und es muss zum Zustand
|
||||||
|
passen: "noch N Tage" bzw. "heute ist der letzte Tag". */
|
||||||
|
ok(/^(noch \d+ Tage?|heute ist der letzte Tag)$/.test(event?.marke || ""),
|
||||||
`der Zustand steht als WORT da, nicht nur als Farbe ("${event?.marke}")`);
|
`der Zustand steht als WORT da, nicht nur als Farbe ("${event?.marke}")`);
|
||||||
ok(/–/.test(event?.spanne || ""), `und der Zeitraum als Spanne ("${event?.spanne}")`);
|
ok(/–/.test(event?.spanne || ""), `und der Zeitraum als Spanne ("${event?.spanne}")`);
|
||||||
ok(event?.schilder.join(",") === "Aufgaben,Regeln",
|
ok(event?.schilder.join(",") === "Aufgaben,Regeln",
|
||||||
`beide Bloecke sind beschriftet (${event?.schilder.join(", ")})`);
|
`beide Bloecke sind beschriftet (${event?.schilder.join(", ")})`);
|
||||||
ok(event?.texte.includes("1 Punkt je Live-Stunde") && event?.texte.includes("Nur eigenes Konto"),
|
ok(event?.texte.includes("1 Punkt je Live-Stunde") && event?.texte.includes("Nur eigenes Konto"),
|
||||||
"und tragen wirklich ihren Inhalt");
|
`und tragen wirklich ihren Inhalt (${JSON.stringify(event?.texte)})`);
|
||||||
|
|
||||||
/* GEGENPROBE dazu: Eine Karte, die KEIN Event ist, darf nichts davon
|
/* GEGENPROBE dazu: Eine Karte, die KEIN Event ist, darf nichts davon
|
||||||
haben. Sonst bewiese der Block oben nur, dass die Elemente
|
haben. Sonst bewiese der Block oben nur, dass die Elemente
|
||||||
existieren -- nicht, dass sie zur richtigen Art gehoeren. */
|
existieren -- nicht, dass sie zur richtigen Art gehoeren. */
|
||||||
const schulung = await seite.$$eval(".eintrag-karte", (karten) => {
|
const schulung = await seite.$$eval(".eintrag-karte", (karten) => {
|
||||||
const k = karten.find((x) => x.querySelector(".eintrag-titel")?.textContent.trim() === "Test schulung");
|
const k = karten.find((x) => x.querySelector(".eintrag-titel")?.textContent.trim() === "Test schulung");
|
||||||
return k ? { event: k.dataset.event ?? null, bloecke: k.querySelectorAll(".event-block").length } : null;
|
return k ? { event: k.dataset.event ?? null, bloecke: k.querySelectorAll(".ev-block").length } : null;
|
||||||
});
|
});
|
||||||
ok(schulung && !schulung.event && schulung.bloecke === 0,
|
ok(schulung && !schulung.event && schulung.bloecke === 0,
|
||||||
`eine Schulung bekommt weder Zustand noch Event-Bloecke (${JSON.stringify(schulung)})`);
|
`eine Schulung bekommt weder Zustand noch Event-Bloecke (${JSON.stringify(schulung)})`);
|
||||||
|
|||||||
@@ -0,0 +1,900 @@
|
|||||||
|
/* =====================================================================
|
||||||
|
AGENTUR-EVENTS: KARTE, PUNKTE UND FORMULAR (03.10.2026)
|
||||||
|
|
||||||
|
Filipe, mit einem Bildschirmfoto des Oktober-Events: „ich will das
|
||||||
|
viel geiler viel perfekter. und auch wenn man die eintraegt und so
|
||||||
|
soll viel mehr perfektioniert und uebersichtlicher sein."
|
||||||
|
|
||||||
|
Umgebaut wurden drei Dinge, und alle drei werden hier nachgemessen:
|
||||||
|
|
||||||
|
1. DIE KARTE Buehne mit Titel auf dem Banner statt 638 px
|
||||||
|
leerem Bild darueber; Zeitraum einmal statt
|
||||||
|
dreimal; „noch 13 Tage" als Antwort.
|
||||||
|
2. DIE PUNKTE Aus Fliesstext wird eine Liste zum Abhaken,
|
||||||
|
jeder fuer sich. Neue Tabelle event_punkte.
|
||||||
|
3. DAS FORMULAR Ein Feld je Zeile statt eines leeren Textfeldes,
|
||||||
|
in das man Aufzaehlungszeichen selbst tippt.
|
||||||
|
|
||||||
|
WAS HIER AUSDRUECKLICH NICHT NUR BESTAETIGT WIRD:
|
||||||
|
|
||||||
|
Zu jeder Zusage gehoert eine Gegenprobe, die zeigt, dass die
|
||||||
|
Pruefung auch „nicht in Ordnung" sagen kann -- sonst bestaetigt sie
|
||||||
|
nichts (Projektgedaechtnis, 01.09.2026: `every()` auf einem leeren
|
||||||
|
Feld meldet `true`). Deshalb steht die Zahl der geprueften Dinge in
|
||||||
|
der BEDINGUNG, nicht nur im Meldetext.
|
||||||
|
|
||||||
|
KEINE WANDUHR ALS ANNAHME: Alle Daten sind relativ zu heute
|
||||||
|
gerechnet (`tag(-1)`, `tag(+12)`). Ein festes Datum waere eine
|
||||||
|
Zeitbombe -- gruen, bis der Kalender es einholt (Projektgedaechtnis,
|
||||||
|
06.09.2026, gate-oeffnung.mjs).
|
||||||
|
===================================================================== */
|
||||||
|
import { mkdtempSync, rmSync, appendFileSync } from "node:fs";
|
||||||
|
import { tmpdir } from "node:os";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
|
const ordner = mkdtempSync(join(tmpdir(), "ws-evk-"));
|
||||||
|
process.env.WORKSPACE_DB = join(ordner, "workspace.db");
|
||||||
|
|
||||||
|
import { notbremse } from "./helfer-notbremse.mjs";
|
||||||
|
const { eigenerPort } = await import("./helfer-port.mjs");
|
||||||
|
const PORT = await eigenerPort(import.meta, "die Eventkarten-Pruefung");
|
||||||
|
|
||||||
|
process.env.PORT = String(PORT);
|
||||||
|
process.env.SITE_ACCESS_SECRET = "lokaler-test";
|
||||||
|
process.env.SITE_ACCESS_CODE_DOGI = "DOGI-TEST-1";
|
||||||
|
process.env.SITE_PUBLIC_LAUNCH_AT = "2020-01-01T00:00:00+01:00";
|
||||||
|
|
||||||
|
const express = (await import("express")).default;
|
||||||
|
const ec = express.response.cookie;
|
||||||
|
express.response.cookie = function (n, w, o) { return ec.call(this, n, w, { ...(o || {}), secure: false }); };
|
||||||
|
await import("./index.js");
|
||||||
|
notbremse(300_000, "pruef-eventkarte");
|
||||||
|
await new Promise((r) => setTimeout(r, 1000));
|
||||||
|
const BASIS = "http://127.0.0.1:" + PORT;
|
||||||
|
|
||||||
|
const PROTOKOLL = join(process.cwd(), "pruef-eventkarte-lauf.txt");
|
||||||
|
try { rmSync(PROTOKOLL, { force: true }); } catch { /* gab es noch nicht */ }
|
||||||
|
const melde = (z) => {
|
||||||
|
console.log(z);
|
||||||
|
try { appendFileSync(PROTOKOLL, z + "\n"); } catch { /* Zugabe */ }
|
||||||
|
};
|
||||||
|
let fehler = 0, geprueft = 0;
|
||||||
|
const ok = (b, t) => { geprueft++; melde((b ? " ok " : " FEHL ") + t); if (!b) fehler++; };
|
||||||
|
|
||||||
|
/* ---- Bestand ---------------------------------------------------------- */
|
||||||
|
const { DatabaseSync } = await import("node:sqlite");
|
||||||
|
const { scryptSync, randomBytes } = await import("node:crypto");
|
||||||
|
await fetch(BASIS + "/workspace/api/anmelden", {
|
||||||
|
method: "POST", headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ rolle: "admin", code: "x" }) }).catch(() => {});
|
||||||
|
for (let i = 0; i < 60; i++) {
|
||||||
|
try {
|
||||||
|
const p = new DatabaseSync(process.env.WORKSPACE_DB);
|
||||||
|
try { p.prepare("SELECT 1 FROM personen LIMIT 1").get(); break; } finally { p.close(); }
|
||||||
|
} catch { await new Promise((r) => setTimeout(r, 250)); }
|
||||||
|
}
|
||||||
|
const d = new DatabaseSync(process.env.WORKSPACE_DB);
|
||||||
|
const jetzt = new Date().toISOString();
|
||||||
|
function anlegen(name, rolle, code) {
|
||||||
|
const salt = randomBytes(16).toString("hex");
|
||||||
|
const hash = scryptSync(code, salt, 64, { N: 32768, r: 8, p: 1, maxmem: 96 * 1024 * 1024 }).toString("hex");
|
||||||
|
d.prepare("INSERT INTO personen (name, rolle, code_hash, code_salt, code_n, aktiv, erstellt) VALUES (?,?,?,?,?,1,?)")
|
||||||
|
.run(name, rolle, hash, salt, 32768, jetzt);
|
||||||
|
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
|
||||||
|
}
|
||||||
|
const idDogi = anlegen("Dogfather", "admin", "CODE-DOGI-0001");
|
||||||
|
const idLuna = anlegen("Luna", "creator", "CODE-CREA-0001");
|
||||||
|
|
||||||
|
const heute = new Date();
|
||||||
|
const tag = (v) => new Date(heute.getTime() + v * 86400000).toISOString().slice(0, 10);
|
||||||
|
function evt(titel, von, bis, auf, reg) {
|
||||||
|
d.prepare("INSERT INTO eintraege (titel, text, bereich, art, status, datum, event_ende,"
|
||||||
|
+ " event_aufgaben, event_regeln, dringlichkeit, erstellt, erstellt_von)"
|
||||||
|
+ " VALUES (?,?,'agentur','kampagne','offen',?,?,?,?,'mittel',?,?)")
|
||||||
|
.run(titel, "Beschreibung zum Test.", von, bis, auf, reg, jetzt, idDogi);
|
||||||
|
return d.prepare("SELECT last_insert_rowid() AS id").get().id;
|
||||||
|
}
|
||||||
|
/* Die drei Zustaende, die eventStand kennt -- jeder einzeln, nicht als
|
||||||
|
Summe. Und die Aufgaben genau so krumm getippt wie im echten Event:
|
||||||
|
einmal ohne Leerzeichen hinter dem Punkt, einmal mit. */
|
||||||
|
const laufend = evt("Oktober Event", tag(-1), tag(12),
|
||||||
|
"·Jeden Tag Live gehen\n·22-Live-Stunden erreichen\n· 33k Diamanten erreichen",
|
||||||
|
"· Nur Streams auf dem eigenen Konto\n· Punkte zählen bis 23:59 am letzten Tag");
|
||||||
|
const kommend = evt("November Challenge", tag(20), tag(45),
|
||||||
|
"· 30 Live-Stunden", "· Nur eigene Konten");
|
||||||
|
const vorbei = evt("September Rückblick", tag(-40), tag(-12),
|
||||||
|
"· 20 Live-Stunden", "· Nur eigene Konten");
|
||||||
|
/* Ein gewoehnlicher Eintrag auf demselben Brett: Er darf sich NICHT
|
||||||
|
mitverwandeln. Ohne ihn wuerde "nur Events sind betroffen" hier gar
|
||||||
|
nicht geprueft. */
|
||||||
|
d.prepare("INSERT INTO eintraege (titel, text, bereich, art, status, datum, dringlichkeit, erstellt, erstellt_von)"
|
||||||
|
+ " VALUES (?,?,'agentur','schulung','offen',?, 'mittel', ?, ?)")
|
||||||
|
.run("Einarbeitung für neue Modis", "Kein Event.", tag(0), jetzt, idDogi);
|
||||||
|
/* EIN EINTRAG, DEN LUNA NICHT SEHEN DARF -- fuer die Gegenprobe zur
|
||||||
|
Bildweg-Reparatur weiter unten. `entwicklung` ist eine Aufzeichnung
|
||||||
|
UEBER eine Person; sie selbst sieht sie nicht. Ohne diesen Eintrag
|
||||||
|
waere "es wurden keine Rechte ausgeweitet" eine Behauptung ohne
|
||||||
|
Beleg. */
|
||||||
|
d.prepare("INSERT INTO eintraege (titel, text, bereich, art, status, datum, dringlichkeit, erstellt, erstellt_von, creator_id)"
|
||||||
|
+ " VALUES (?,?,'entwicklung','notiz','offen',?, 'mittel', ?, ?, ?)")
|
||||||
|
.run("Vertrauliche Aufzeichnung", "Nicht fuer Luna.", tag(0), jetzt, idDogi, idDogi);
|
||||||
|
const geheim = d.prepare("SELECT last_insert_rowid() AS id").get().id;
|
||||||
|
d.close();
|
||||||
|
|
||||||
|
/* Ein Banner fuer das laufende Event -- ohne Bild waere der Knopf
|
||||||
|
"Banner ganz" nicht pruefbar, und die Buehne mit Bild ist der Fall,
|
||||||
|
um den es Filipe ging. */
|
||||||
|
import { pngBauen } from "./helfer-png-bauen.mjs";
|
||||||
|
const bannerBild = pngBauen(1280, 720, (x, y, b, h) => {
|
||||||
|
const g = Math.max(0, 1 - Math.hypot(x / b - .5, y / h - .5) * 1.8);
|
||||||
|
return [Math.round(26 + g * 120), Math.round(10 + g * 30), Math.round(46 + g * 150)];
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ---- Zugang ----------------------------------------------------------- */
|
||||||
|
const { request } = await import("node:http");
|
||||||
|
const HOST = "workspace.dogfather-universe.com";
|
||||||
|
function roh(pfad, o = {}) {
|
||||||
|
return new Promise((f, s) => {
|
||||||
|
const daten = o.rumpf === undefined ? null
|
||||||
|
: (Buffer.isBuffer(o.rumpf) ? o.rumpf : Buffer.from(JSON.stringify(o.rumpf)));
|
||||||
|
const a = request({
|
||||||
|
host: "127.0.0.1", port: PORT, path: pfad,
|
||||||
|
method: o.methode || (daten ? "POST" : "GET"),
|
||||||
|
headers: {
|
||||||
|
Host: HOST, Origin: "https://" + HOST,
|
||||||
|
...(o.keks ? { Cookie: o.keks } : {}),
|
||||||
|
...(daten ? { "Content-Length": daten.length } : {}),
|
||||||
|
...(o.kopf || {}),
|
||||||
|
},
|
||||||
|
}, (r) => {
|
||||||
|
const t = [];
|
||||||
|
r.on("data", (x) => t.push(x));
|
||||||
|
r.on("end", () => f({ code: r.statusCode, kopf: r.headers, text: Buffer.concat(t).toString("utf8") }));
|
||||||
|
});
|
||||||
|
a.on("error", s);
|
||||||
|
if (daten) a.write(daten);
|
||||||
|
a.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function anmelden(rolle, code) {
|
||||||
|
const a = await roh("/workspace/api/anmelden", {
|
||||||
|
rumpf: { rolle, code }, kopf: { "Content-Type": "application/json" } });
|
||||||
|
if (a.code !== 200) { melde("ABBRUCH: Anmeldung " + rolle + " -> " + a.code); process.exit(3); }
|
||||||
|
return [].concat(a.kopf["set-cookie"] || []).map((c) => c.split(";")[0]).join("; ");
|
||||||
|
}
|
||||||
|
const keksDogi = await anmelden("admin", "CODE-DOGI-0001");
|
||||||
|
const keksLuna = await anmelden("creator", "CODE-CREA-0001");
|
||||||
|
|
||||||
|
const brett = async (keks) => JSON.parse((await roh("/workspace/api/bereich/agentur", { keks })).text);
|
||||||
|
|
||||||
|
let bannerId = null, geheimBildId = null;
|
||||||
|
{
|
||||||
|
const h = await roh("/workspace/api/bereich/agentur/" + laufend + "/bild", {
|
||||||
|
keks: keksDogi, rumpf: bannerBild, methode: "POST",
|
||||||
|
kopf: { "Content-Type": "image/png", "x-name": encodeURIComponent("banner.png") } });
|
||||||
|
if (h.code !== 201) {
|
||||||
|
melde("ABBRUCH: Banner liess sich nicht anhaengen (" + h.code + ") -- ohne es");
|
||||||
|
melde(" prueft diese Datei die Buehne MIT Bild gar nicht.");
|
||||||
|
process.exit(3);
|
||||||
|
}
|
||||||
|
bannerId = JSON.parse(h.text).id;
|
||||||
|
|
||||||
|
const g = await roh("/workspace/api/bereich/entwicklung/" + geheim + "/bild", {
|
||||||
|
keks: keksDogi, rumpf: bannerBild, methode: "POST",
|
||||||
|
kopf: { "Content-Type": "image/png", "x-name": encodeURIComponent("geheim.png") } });
|
||||||
|
if (g.code !== 201) {
|
||||||
|
melde("ABBRUCH: das Bild fuer die Gegenprobe ging nicht durch (" + g.code + ").");
|
||||||
|
melde(" Ohne es wuerde unten eine Rechtefrage geprueft, die gar nicht stattfindet.");
|
||||||
|
process.exit(3);
|
||||||
|
}
|
||||||
|
geheimBildId = JSON.parse(g.text).id;
|
||||||
|
}
|
||||||
|
|
||||||
|
melde("\n=== 0. Der Bildweg: wer den Eintrag sieht, sieht sein Bild ===");
|
||||||
|
{
|
||||||
|
/* GEMESSEN AM 03.10.2026, und es war ein echter Mangel: Das Banner
|
||||||
|
eines Agentur-Events kam bei einer Creatorin mit 404 zurueck --
|
||||||
|
an genau der Karte, die fuer sie gemacht ist. Grund: Die Regel
|
||||||
|
"wer das Brett sieht, sieht das Bild" galt nur fuer die sieben
|
||||||
|
Community-Bretter, und danach griff die Ablage-Regel, die an
|
||||||
|
Creator-Zuordnungen haengt. Ein Agentur-Event hat keine. */
|
||||||
|
const alsDogi = await roh("/workspace/api/dateien/" + bannerId + "/bild", { keks: keksDogi });
|
||||||
|
const alsLuna = await roh("/workspace/api/dateien/" + bannerId + "/bild", { keks: keksLuna });
|
||||||
|
ok(alsDogi.code === 200, `DogFather bekommt das Banner (HTTP ${alsDogi.code})`);
|
||||||
|
ok(alsLuna.code === 200, `und die Creatorin auch (HTTP ${alsLuna.code}, vorher 404)`);
|
||||||
|
|
||||||
|
/* DIE GEGENPROBE, auf die es ankommt: Die Reparatur darf NICHT mehr
|
||||||
|
oeffnen als noetig. Ein Eintrag, den Luna nicht sehen darf, muss
|
||||||
|
sein Bild weiterhin verweigern -- sonst waere aus einer Luecke
|
||||||
|
eine groessere geworden. */
|
||||||
|
const verboten = await roh("/workspace/api/dateien/" + geheimBildId + "/bild", { keks: keksLuna });
|
||||||
|
ok(verboten.code === 404,
|
||||||
|
`ein Bild an einem fremden Eintrag bleibt verborgen (HTTP ${verboten.code})`);
|
||||||
|
/* Und dass dieses Bild ueberhaupt existiert -- sonst waere die
|
||||||
|
Gegenprobe gruen, weil es nichts zu sehen gab. */
|
||||||
|
const existiert = await roh("/workspace/api/dateien/" + geheimBildId + "/bild", { keks: keksDogi });
|
||||||
|
ok(existiert.code === 200,
|
||||||
|
`es gibt dieses Bild wirklich (DogFather: HTTP ${existiert.code})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
1. Die Punkte: aus Fliesstext wird eine Liste
|
||||||
|
======================================================================= */
|
||||||
|
melde("\n=== 1. Die Punkte kommen als Liste vom Server ===");
|
||||||
|
{
|
||||||
|
const daten = await brett(keksDogi);
|
||||||
|
const e = (daten.eintraege || []).find((x) => x.titel === "Oktober Event");
|
||||||
|
ok(!!e, "das laufende Event ist auf dem Brett");
|
||||||
|
|
||||||
|
const p = e?.event_punkte || [];
|
||||||
|
ok(p.length === 3, `3 Aufgabenpunkte (${p.length})`);
|
||||||
|
/* DAS IST DER EIGENTLICHE MANGEL AUS FILIPES BILDSCHIRMFOTO: Im
|
||||||
|
Original stand „·Jeden Tag Live gehen" neben „· 33k Diamanten
|
||||||
|
erreichen" -- einmal ohne, einmal mit Leerzeichen. */
|
||||||
|
ok(p[0]?.text === "Jeden Tag Live gehen",
|
||||||
|
`ohne Leerzeichen getippt -> sauber: ${JSON.stringify(p[0]?.text)}`);
|
||||||
|
ok(p[2]?.text === "33k Diamanten erreichen",
|
||||||
|
`mit Leerzeichen getippt -> gleich sauber: ${JSON.stringify(p[2]?.text)}`);
|
||||||
|
ok(p.every((x) => /^[0-9a-f]{16}$/.test(x.schluessel || "")) && p.length > 0,
|
||||||
|
"jeder Punkt hat einen Schluessel (16 Hexzeichen)");
|
||||||
|
ok((e?.event_regelpunkte || []).length === 2,
|
||||||
|
`2 Regelpunkte (${(e?.event_regelpunkte || []).length})`);
|
||||||
|
ok(e?.event_geschafft === 0, `noch nichts abgehakt (${e?.event_geschafft})`);
|
||||||
|
|
||||||
|
/* GEGENPROBE: Ein Eintrag, der KEIN Event ist, bekommt keine Punkte.
|
||||||
|
Ohne sie wuesste niemand, ob die Zerlegung nicht einfach ueberall
|
||||||
|
laeuft -- und dann waere "nur Events sind betroffen" unbelegt. */
|
||||||
|
const schulung = (daten.eintraege || []).find((x) => x.art === "schulung");
|
||||||
|
ok(!!schulung, "der Nicht-Event-Eintrag ist da (sonst prueft die Gegenprobe nichts)");
|
||||||
|
ok(schulung && schulung.event_punkte === undefined,
|
||||||
|
"ein Eintrag ohne Eventfelder bekommt keine Punkteliste");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
2. Abhaken -- und was dabei NICHT geht
|
||||||
|
======================================================================= */
|
||||||
|
melde("\n=== 2. Abhaken: jeder fuer sich ===");
|
||||||
|
let schluesselA = null, schluesselB = null;
|
||||||
|
{
|
||||||
|
const daten = await brett(keksDogi);
|
||||||
|
const e = daten.eintraege.find((x) => x.titel === "Oktober Event");
|
||||||
|
schluesselA = e.event_punkte[1].schluessel; /* 22-Live-Stunden */
|
||||||
|
schluesselB = e.event_punkte[2].schluessel; /* 33k Diamanten */
|
||||||
|
|
||||||
|
const a = await roh(`/workspace/api/eintrag/${laufend}/punkt/${schluesselA}`, {
|
||||||
|
keks: keksLuna, methode: "PUT", rumpf: {}, kopf: { "Content-Type": "application/json" } });
|
||||||
|
ok(a.code === 200, `Luna hakt einen Punkt ab (HTTP ${a.code})`);
|
||||||
|
const j = JSON.parse(a.text || "{}");
|
||||||
|
ok(j.geschafft === 1 && j.gesamt === 3, `Antwort sagt ${j.geschafft} von ${j.gesamt} (erwartet 1 von 3)`);
|
||||||
|
|
||||||
|
/* HAELT ES AUCH? Die Zahl aus der Antwort koennte gerechnet sein,
|
||||||
|
ohne dass etwas gespeichert wurde. Deshalb ein frischer Abruf. */
|
||||||
|
const nachher = await brett(keksLuna);
|
||||||
|
const eL = nachher.eintraege.find((x) => x.titel === "Oktober Event");
|
||||||
|
ok(eL.event_geschafft === 1, `nach frischem Abruf: ${eL.event_geschafft} abgehakt`);
|
||||||
|
ok(eL.event_punkte.filter((p) => p.meiner).length === 1
|
||||||
|
&& eL.event_punkte[1].meiner === true,
|
||||||
|
"und zwar genau der angeklickte Punkt");
|
||||||
|
|
||||||
|
/* DER KERN DER ZUSAGE: DogFather sieht Lunas Haken NICHT als seinen
|
||||||
|
eigenen. Ohne diese Pruefung waere "jeder hakt fuer sich ab" eine
|
||||||
|
Behauptung. */
|
||||||
|
const beiDogi = await brett(keksDogi);
|
||||||
|
const eD = beiDogi.eintraege.find((x) => x.titel === "Oktober Event");
|
||||||
|
ok(eD.event_geschafft === 0,
|
||||||
|
`DogFather sieht Lunas Haken nicht als seinen (${eD.event_geschafft})`);
|
||||||
|
ok(eD.event_punkte.every((p) => p.meiner === false),
|
||||||
|
"kein einziger Punkt ist bei ihm angehakt");
|
||||||
|
|
||||||
|
/* ... sieht aber, DASS jemand dabei ist -- er ist die Leitung. */
|
||||||
|
ok(Array.isArray(eD.event_stand) && eD.event_stand.length === 1
|
||||||
|
&& eD.event_stand[0].name === "Luna" && eD.event_stand[0].geschafft === 1,
|
||||||
|
`die Leitung sieht den Stand: ${JSON.stringify(eD.event_stand)}`);
|
||||||
|
/* GEGENPROBE ZUR LEITUNG: Luna selbst darf diese Liste NICHT
|
||||||
|
bekommen -- sonst waere "wer macht mit" eine Auskunft fuer alle. */
|
||||||
|
ok(eL.event_stand === undefined,
|
||||||
|
"eine Creatorin bekommt die Mitmacherliste gar nicht erst");
|
||||||
|
|
||||||
|
/* Zweimal dasselbe ist kein Fehler, aendert aber auch nichts. */
|
||||||
|
const nochmal = await roh(`/workspace/api/eintrag/${laufend}/punkt/${schluesselA}`, {
|
||||||
|
keks: keksLuna, methode: "PUT", rumpf: {}, kopf: { "Content-Type": "application/json" } });
|
||||||
|
const j2 = JSON.parse(nochmal.text || "{}");
|
||||||
|
ok(nochmal.code === 200 && j2.geschafft === 1,
|
||||||
|
`zweimal derselbe Haken bleibt 1 (HTTP ${nochmal.code}, ${j2.geschafft})`);
|
||||||
|
|
||||||
|
/* Und wieder weg. */
|
||||||
|
const ab = await roh(`/workspace/api/eintrag/${laufend}/punkt/${schluesselA}`, {
|
||||||
|
keks: keksLuna, methode: "DELETE" });
|
||||||
|
const j3 = JSON.parse(ab.text || "{}");
|
||||||
|
ok(ab.code === 200 && j3.geschafft === 0, `Haken wieder weg (${j3.geschafft})`);
|
||||||
|
/* Fuer die folgenden Pruefungen wieder setzen. */
|
||||||
|
await roh(`/workspace/api/eintrag/${laufend}/punkt/${schluesselA}`, {
|
||||||
|
keks: keksLuna, methode: "PUT", rumpf: {}, kopf: { "Content-Type": "application/json" } });
|
||||||
|
}
|
||||||
|
|
||||||
|
melde("\n=== 2b. Was NICHT geht ===");
|
||||||
|
{
|
||||||
|
/* EIN ERFUNDENER SCHLUESSEL. Ohne diese Schranke koennte sich jeder
|
||||||
|
„3 von 3" setzen, ohne dass eine der drei Aufgaben je dastand --
|
||||||
|
und eine Zahl, die man sich ausdenken kann, zaehlt nichts. */
|
||||||
|
const a = await roh(`/workspace/api/eintrag/${laufend}/punkt/00112233445566ff`, {
|
||||||
|
keks: keksLuna, methode: "PUT", rumpf: {}, kopf: { "Content-Type": "application/json" } });
|
||||||
|
ok(a.code === 404, `erfundener Punkt wird abgelehnt (HTTP ${a.code})`);
|
||||||
|
|
||||||
|
/* Unsinn in der Adresse. */
|
||||||
|
const b = await roh(`/workspace/api/eintrag/${laufend}/punkt/..%2F..%2Fetc`, {
|
||||||
|
keks: keksLuna, methode: "PUT", rumpf: {}, kopf: { "Content-Type": "application/json" } });
|
||||||
|
ok(b.code === 400 || b.code === 404, `kein Schluesselformat -> abgelehnt (HTTP ${b.code})`);
|
||||||
|
|
||||||
|
/* Ohne Anmeldung gar nichts. */
|
||||||
|
const c = await roh(`/workspace/api/eintrag/${laufend}/punkt/${schluesselB}`, {
|
||||||
|
methode: "PUT", rumpf: {}, kopf: { "Content-Type": "application/json" } });
|
||||||
|
ok(c.code === 401, `ohne Anmeldung abgewiesen (HTTP ${c.code})`);
|
||||||
|
|
||||||
|
/* Fremde Herkunft (CSRF). */
|
||||||
|
const e = await new Promise((f, s) => {
|
||||||
|
const a2 = request({
|
||||||
|
host: "127.0.0.1", port: PORT,
|
||||||
|
path: `/workspace/api/eintrag/${laufend}/punkt/${schluesselB}`,
|
||||||
|
method: "PUT",
|
||||||
|
headers: { Host: HOST, Origin: "https://boeswillig.example", Cookie: keksLuna,
|
||||||
|
"Content-Type": "application/json", "Content-Length": 2 },
|
||||||
|
}, (r) => { const t = []; r.on("data", (x) => t.push(x));
|
||||||
|
r.on("end", () => f({ code: r.statusCode })); });
|
||||||
|
a2.on("error", s); a2.write("{}"); a2.end();
|
||||||
|
});
|
||||||
|
ok(e.code === 403, `fremde Herkunft abgewiesen (HTTP ${e.code})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
3. Der Schluessel ueberlebt das Umsortieren -- aber nicht das Umschreiben
|
||||||
|
======================================================================= */
|
||||||
|
melde("\n=== 3. Haken bleiben am richtigen Punkt ===");
|
||||||
|
{
|
||||||
|
/* UMSORTIEREN: Der Haken an „22-Live-Stunden" muss bleiben, wo er
|
||||||
|
ist -- auch wenn eine Zeile DAVOR eingefuegt wird. Haengt er an
|
||||||
|
einer Zeilennummer, wandert er still auf eine andere Aufgabe, und
|
||||||
|
jemand hat etwas abgehakt, was er nie gemacht hat. */
|
||||||
|
const a = await roh(`/workspace/api/bereich/agentur/${laufend}`, {
|
||||||
|
keks: keksDogi, methode: "PATCH",
|
||||||
|
rumpf: { event_aufgaben: "· GANZ NEU ganz oben\n· 33k Diamanten erreichen\n· 22-Live-Stunden erreichen\n· Jeden Tag Live gehen" },
|
||||||
|
kopf: { "Content-Type": "application/json" } });
|
||||||
|
ok(a.code === 200, `Aufgaben umsortiert und ergaenzt (HTTP ${a.code})`);
|
||||||
|
|
||||||
|
const nach = await brett(keksLuna);
|
||||||
|
const e = nach.eintraege.find((x) => x.titel === "Oktober Event");
|
||||||
|
ok((e.event_punkte || []).length === 4, `jetzt 4 Punkte (${(e.event_punkte || []).length})`);
|
||||||
|
const haken = (e.event_punkte || []).filter((p) => p.meiner);
|
||||||
|
ok(haken.length === 1 && haken[0].text === "22-Live-Stunden erreichen",
|
||||||
|
`der Haken sitzt weiterhin an: ${JSON.stringify(haken.map((h) => h.text))}`);
|
||||||
|
|
||||||
|
/* GEGENPROBE: Wird die Bedingung SELBST geaendert, muss der Haken
|
||||||
|
fallen -- eine geaenderte Bedingung ist eine andere Bedingung, und
|
||||||
|
ein Haken daran waere eine Falschauskunft. */
|
||||||
|
const b = await roh(`/workspace/api/bereich/agentur/${laufend}`, {
|
||||||
|
keks: keksDogi, methode: "PATCH",
|
||||||
|
rumpf: { event_aufgaben: "· GANZ NEU ganz oben\n· 33k Diamanten erreichen\n· 30-Live-Stunden erreichen\n· Jeden Tag Live gehen" },
|
||||||
|
kopf: { "Content-Type": "application/json" } });
|
||||||
|
ok(b.code === 200, `Bedingung umgeschrieben: 22 -> 30 Stunden (HTTP ${b.code})`);
|
||||||
|
const nach2 = await brett(keksLuna);
|
||||||
|
const e2 = nach2.eintraege.find((x) => x.titel === "Oktober Event");
|
||||||
|
ok((e2.event_punkte || []).filter((p) => p.meiner).length === 0,
|
||||||
|
"der Haken ist gefallen -- 30 Stunden sind nicht 22");
|
||||||
|
ok(e2.event_geschafft === 0, `und die Zahl stimmt dazu (${e2.event_geschafft})`);
|
||||||
|
|
||||||
|
/* Zurueckstellen fuer die Oberflaechenpruefung. */
|
||||||
|
await roh(`/workspace/api/bereich/agentur/${laufend}`, {
|
||||||
|
keks: keksDogi, methode: "PATCH",
|
||||||
|
rumpf: { event_aufgaben: "·Jeden Tag Live gehen\n·22-Live-Stunden erreichen\n· 33k Diamanten erreichen" },
|
||||||
|
kopf: { "Content-Type": "application/json" } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
4. Die Oberflaeche
|
||||||
|
======================================================================= */
|
||||||
|
melde("\n=== 4. Die Karte im Browser ===");
|
||||||
|
const pw = await import("file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs");
|
||||||
|
const browser = await pw.chromium.launch();
|
||||||
|
const klagen = [];
|
||||||
|
|
||||||
|
async function alsRolle(rolle, code, breite = 1280) {
|
||||||
|
const ctx = await browser.newContext({ viewport: { width: breite, height: 1000 }, hasTouch: breite <= 860 });
|
||||||
|
await ctx.route("**/*", (route) => {
|
||||||
|
const u = new URL(route.request().url());
|
||||||
|
if (u.hostname === "127.0.0.1") {
|
||||||
|
return route.continue({ headers: { ...route.request().headers(), host: HOST } });
|
||||||
|
}
|
||||||
|
return route.continue();
|
||||||
|
});
|
||||||
|
const seite = await ctx.newPage();
|
||||||
|
seite.on("pageerror", (f) => klagen.push("pageerror: " + f.message));
|
||||||
|
seite.on("console", (m) => { if (m.type() === "error") klagen.push("console: " + m.text().slice(0, 160)); });
|
||||||
|
/* WELCHE Datei fehlt -- die Konsolenmeldung sagt nur "404 (Not
|
||||||
|
Found)". Beim ersten Lauf standen hier drei davon, und sie waren
|
||||||
|
nicht zuzuordnen; eine Pruefung, die nicht sagen kann, woran sie
|
||||||
|
scheitert, kostet eine Stunde Suchen (Projektgedaechtnis,
|
||||||
|
11.09.2026). */
|
||||||
|
seite.on("response", (r) => {
|
||||||
|
if (r.status() >= 400) klagen.push(`HTTP ${r.status()}: ${new URL(r.url()).pathname}`);
|
||||||
|
});
|
||||||
|
await seite.goto(BASIS + "/workspace/", { waitUntil: "networkidle" });
|
||||||
|
await seite.click('.rolle[data-rolle="' + rolle + '"]');
|
||||||
|
await seite.fill("#code", code);
|
||||||
|
await seite.click("button[type=submit]");
|
||||||
|
await seite.waitForURL("**/start.html", { timeout: 25000 });
|
||||||
|
await seite.goto(BASIS + "/workspace/bereich.html?b=agentur", { waitUntil: "networkidle" });
|
||||||
|
await seite.waitForSelector(".eintrag-karte", { timeout: 15000 });
|
||||||
|
await seite.waitForTimeout(700);
|
||||||
|
return { ctx, seite };
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const { ctx, seite } = await alsRolle("admin", "CODE-DOGI-0001", 1280);
|
||||||
|
|
||||||
|
const karten = await seite.$$('.eintrag-karte[data-eventkarte="ja"]');
|
||||||
|
ok(karten.length === 3, `3 Eventkarten (${karten.length}) -- die Schulung ist keine`);
|
||||||
|
|
||||||
|
/* GEGENPROBE: Die Schulung bleibt eine gewoehnliche Karte. Ohne sie
|
||||||
|
waere "nur Events sind umgebaut" unbelegt. */
|
||||||
|
const schulung = await seite.$('.eintrag-karte:not([data-eventkarte="ja"])');
|
||||||
|
ok(!!schulung, "der Nicht-Event-Eintrag ist weiterhin eine gewoehnliche Karte");
|
||||||
|
|
||||||
|
const masse = await seite.evaluate(() => {
|
||||||
|
const k = [...document.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')]
|
||||||
|
.find((x) => x.textContent.includes("Oktober Event"));
|
||||||
|
const b = k.querySelector(".ev-buehne");
|
||||||
|
const bild = k.querySelector(".ev-buehne__bild");
|
||||||
|
const t = k.querySelector(".eintrag-titel");
|
||||||
|
const kr = k.getBoundingClientRect();
|
||||||
|
const tr = t.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
karte: Math.round(kr.height),
|
||||||
|
buehne: b ? Math.round(b.getBoundingClientRect().height) : 0,
|
||||||
|
bildBreite: bild ? Math.round(bild.getBoundingClientRect().width) : 0,
|
||||||
|
buehneBreite: b ? Math.round(b.getBoundingClientRect().width) : 0,
|
||||||
|
titelGroesse: parseFloat(getComputedStyle(t).fontSize),
|
||||||
|
textGroesse: parseFloat(getComputedStyle(k.querySelector(".eintrag-text")).fontSize),
|
||||||
|
markeGroesse: parseFloat(getComputedStyle(k.querySelector(".marke-art")).fontSize),
|
||||||
|
/* Wie weit oben steht der Titel INNERHALB der Karte? Das war der
|
||||||
|
eigentliche Mangel: vorher unter 638 px Bild. */
|
||||||
|
titelInKarte: Math.round(tr.top - kr.top),
|
||||||
|
datumZeilen: [...k.querySelectorAll(".ev-spanne, .im-kalender, .event-zeitraum")]
|
||||||
|
.map((x) => x.textContent.trim()),
|
||||||
|
noch: k.querySelector(".ev-noch")?.textContent || null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
melde(" -- gemessen: " + JSON.stringify(masse));
|
||||||
|
|
||||||
|
/* DIE ZAHLEN AUS DEM BEFUND, jede einzeln. */
|
||||||
|
ok(masse.titelInKarte < 180,
|
||||||
|
`der Titel steht ${masse.titelInKarte} px unter der Kartenkante (vorher 638+, Grenze 180)`);
|
||||||
|
ok(masse.titelGroesse >= 18,
|
||||||
|
`Titel ${masse.titelGroesse} px (vorher 15,36 -- Grenze 18)`);
|
||||||
|
ok(masse.titelGroesse >= masse.textGroesse * 1.3,
|
||||||
|
`Titel deutlich groesser als der Text darunter (${masse.titelGroesse} vs ${masse.textGroesse})`);
|
||||||
|
/* Die projekteigene Grenze fuer Grossbuchstaben mit Sperrung. Sie
|
||||||
|
galt bisher nur unter 760 px Fensterbreite -- eine Grenze, die nur
|
||||||
|
bei schmalen Fenstern gilt, ist keine. */
|
||||||
|
ok(masse.markeGroesse >= 11.5,
|
||||||
|
`Etikett ${masse.markeGroesse} px (vorher 10,88 -- Grenze 11,5)`);
|
||||||
|
ok(masse.buehne <= 320 && masse.buehne > 0,
|
||||||
|
`Buehne ${masse.buehne} px hoch (vorher 638)`);
|
||||||
|
ok(masse.datumZeilen.length === 1,
|
||||||
|
`das Datum steht einmal, nicht dreimal: ${JSON.stringify(masse.datumZeilen)}`);
|
||||||
|
ok(/^noch \d+ Tage?$/.test(masse.noch || ""),
|
||||||
|
`der Countdown beantwortet "wie lange noch": ${JSON.stringify(masse.noch)}`);
|
||||||
|
|
||||||
|
/* Die drei Zustaende -- jeder einzeln nachgewiesen, nicht als Summe. */
|
||||||
|
const staende = await seite.evaluate(() => {
|
||||||
|
const raus = {};
|
||||||
|
for (const k of document.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')) {
|
||||||
|
const t = k.querySelector(".eintrag-titel")?.textContent || "?";
|
||||||
|
raus[t] = { stand: k.dataset.event, wort: k.querySelector(".ev-noch")?.textContent };
|
||||||
|
}
|
||||||
|
return raus;
|
||||||
|
});
|
||||||
|
ok(staende["Oktober Event"]?.stand === "laeuft",
|
||||||
|
`laufend: ${JSON.stringify(staende["Oktober Event"])}`);
|
||||||
|
ok(staende["November Challenge"]?.stand === "kommt"
|
||||||
|
&& /^startet in \d+ Tagen$/.test(staende["November Challenge"]?.wort || ""),
|
||||||
|
`kommend: ${JSON.stringify(staende["November Challenge"])}`);
|
||||||
|
ok(staende["September Rückblick"]?.stand === "vorbei"
|
||||||
|
&& /^vorbei seit \d+ Tagen$/.test(staende["September Rückblick"]?.wort || ""),
|
||||||
|
`vorbei: ${JSON.stringify(staende["September Rückblick"])}`);
|
||||||
|
|
||||||
|
/* EIN VORBEIGELAUFENES EVENT WIRD NICHT MEHR ABGEHAKT -- ein Haken
|
||||||
|
waere eine Behauptung ueber etwas, das nicht mehr stattfindet. */
|
||||||
|
const knoepfeVorbei = await seite.evaluate(() => {
|
||||||
|
const k = [...document.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')]
|
||||||
|
.find((x) => x.textContent.includes("September"));
|
||||||
|
return {
|
||||||
|
knoepfe: k.querySelectorAll(".ev-punkt__knopf").length,
|
||||||
|
zeilen: k.querySelectorAll(".ev-punkt").length,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
ok(knoepfeVorbei.zeilen > 0 && knoepfeVorbei.knoepfe === 0,
|
||||||
|
`vorbei: ${knoepfeVorbei.zeilen} Zeilen lesbar, ${knoepfeVorbei.knoepfe} Knoepfe`);
|
||||||
|
|
||||||
|
/* DER WEG ZUM GANZEN BANNER. Er war beim ersten Entwurf verloren
|
||||||
|
gegangen: Vorher war das Bild ein Verweis, als Buehne nicht mehr --
|
||||||
|
und bei Filipes Banner steht die eigentliche Ansage IM Bild. */
|
||||||
|
const ganz = await seite.evaluate(() => {
|
||||||
|
const k = [...document.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')]
|
||||||
|
.find((x) => x.textContent.includes("Oktober Event"));
|
||||||
|
const a = k.querySelector(".ev-buehne__ganz");
|
||||||
|
const t = k.querySelector(".eintrag-titel");
|
||||||
|
if (!a) return null;
|
||||||
|
const ar = a.getBoundingClientRect(), tr = t.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
ziel: a.getAttribute("href"),
|
||||||
|
neuesFenster: a.getAttribute("target") === "_blank" && /noopener/.test(a.getAttribute("rel") || ""),
|
||||||
|
wort: a.textContent.trim(),
|
||||||
|
/* Deckt er den Titel zu? Das haeufigste Problem bei einem Knopf,
|
||||||
|
der absolut in einer Ecke sitzt. */
|
||||||
|
ueberlappt: !(ar.bottom < tr.top || ar.top > tr.bottom || ar.right < tr.left || ar.left > tr.right),
|
||||||
|
hoehe: Math.round(ar.height),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
ok(!!ganz && /^\/workspace\/api\/dateien\/\d+\/bild$/.test(ganz.ziel || ""),
|
||||||
|
`"Banner ganz" fuehrt zum vollen Bild: ${JSON.stringify(ganz)}`);
|
||||||
|
ok(!!ganz && ganz.neuesFenster, "und zwar in einem neuen Fenster, mit noopener");
|
||||||
|
ok(!!ganz && !ganz.ueberlappt, "er liegt nicht ueber dem Titel");
|
||||||
|
|
||||||
|
/* GEGENPROBE: Ohne Bild gibt es ihn nicht -- ein Knopf, der auf eine
|
||||||
|
Fehlerseite fuehrt, ist schlimmer als keiner. */
|
||||||
|
const ohneBild = await seite.evaluate(() => {
|
||||||
|
const k = [...document.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')]
|
||||||
|
.find((x) => x.textContent.includes("November Challenge"));
|
||||||
|
return { mitbild: k.querySelector(".ev-buehne")?.dataset.mitbild || null,
|
||||||
|
knopf: k.querySelectorAll(".ev-buehne__ganz").length };
|
||||||
|
});
|
||||||
|
ok(ohneBild.mitbild === null && ohneBild.knopf === 0,
|
||||||
|
`ohne Banner kein Knopf: ${JSON.stringify(ohneBild)}`);
|
||||||
|
|
||||||
|
/* Der Loeschknopf unterscheidet sich jetzt von den anderen. */
|
||||||
|
const gefahr = await seite.evaluate(() => {
|
||||||
|
const k = [...document.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')]
|
||||||
|
.find((x) => x.textContent.includes("Oktober Event"));
|
||||||
|
const l = k.querySelector(".schritt--gefahr");
|
||||||
|
const andere = k.querySelector(".eintrag-knoepfe .schritt:not(.schritt--gefahr)");
|
||||||
|
return l && andere
|
||||||
|
? { l: getComputedStyle(l).color, a: getComputedStyle(andere).color, text: l.textContent.trim() }
|
||||||
|
: null;
|
||||||
|
});
|
||||||
|
ok(!!gefahr && gefahr.text === "löschen" && gefahr.l !== gefahr.a,
|
||||||
|
`"löschen" sieht anders aus als die uebrigen Knoepfe: ${JSON.stringify(gefahr)}`);
|
||||||
|
|
||||||
|
await ctx.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
melde("\n=== 5. Abhaken im Browser, mit Neuladen ===");
|
||||||
|
{
|
||||||
|
const { ctx, seite } = await alsRolle("creator", "CODE-CREA-0001", 1280);
|
||||||
|
|
||||||
|
/* DEN ZAEHLER DER RICHTIGEN KARTE LESEN.
|
||||||
|
Beim ersten Lauf stand hier `seite.textContent(".ev-zaehler")` --
|
||||||
|
das nimmt den ERSTEN auf der Seite, und der gehoerte zur November-
|
||||||
|
Challenge ("0 von 1"). Die Pruefung meldete daraufhin FEHL, obwohl
|
||||||
|
am Zaehler nichts falsch war. Eine Pruefung, die das Falsche misst,
|
||||||
|
kostet dieselbe Zeit wie ein echter Fehler. */
|
||||||
|
const OKT = '.eintrag-karte[data-eventkarte="ja"]:has(.eintrag-titel:text-is("Oktober Event"))';
|
||||||
|
const zaehlerLesen = async () =>
|
||||||
|
(await seite.textContent(OKT + " .ev-zaehler") || "").trim();
|
||||||
|
|
||||||
|
const vorher = await zaehlerLesen();
|
||||||
|
ok(/^\d+ von \d+$/.test(vorher), `Zaehler steht da: ${JSON.stringify(vorher)}`);
|
||||||
|
|
||||||
|
/* Luna hat aus Teil 2 noch einen Haken -- also 1 von 3. */
|
||||||
|
ok(vorher === "1 von 3", `Lunas Stand vom Server: ${vorher}`);
|
||||||
|
|
||||||
|
const knoepfe = await seite.$$(OKT + " .ev-punkt__knopf");
|
||||||
|
ok(knoepfe.length === 3, `${knoepfe.length} abhakbare Punkte an diesem Event`);
|
||||||
|
/* Den NICHT bereits abgehakten nehmen -- sonst zaehlt der Klick
|
||||||
|
herunter statt herauf, und die Pruefung misst das Gegenteil. */
|
||||||
|
await knoepfe[0].click();
|
||||||
|
await seite.waitForTimeout(600);
|
||||||
|
const danach = await zaehlerLesen();
|
||||||
|
ok(danach === "2 von 3", `nach dem Klick: ${danach}`);
|
||||||
|
|
||||||
|
/* HAELT ES EINEN SEITENWECHSEL AUS? Eine Anzeige, die nur im
|
||||||
|
Browser zaehlt, sieht genauso aus -- und ist nichts wert. */
|
||||||
|
await seite.reload({ waitUntil: "networkidle" });
|
||||||
|
await seite.waitForSelector(".ev-zaehler", { timeout: 15000 });
|
||||||
|
await seite.waitForTimeout(500);
|
||||||
|
const nachNeuladen = await zaehlerLesen();
|
||||||
|
ok(nachNeuladen === "2 von 3", `nach dem Neuladen immer noch: ${nachNeuladen}`);
|
||||||
|
|
||||||
|
/* Und wieder ab. */
|
||||||
|
const k2 = await seite.$$(OKT + " .ev-punkt__knopf");
|
||||||
|
await k2[0].click();
|
||||||
|
await seite.waitForTimeout(600);
|
||||||
|
const ab = await zaehlerLesen();
|
||||||
|
ok(ab === "1 von 3", `wieder abgewaehlt: ${ab}`);
|
||||||
|
|
||||||
|
await ctx.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
melde("\n=== 6. Das Formular ===");
|
||||||
|
{
|
||||||
|
const { ctx, seite } = await alsRolle("admin", "CODE-DOGI-0001", 1280);
|
||||||
|
await seite.click("#neu-oeffnen");
|
||||||
|
await seite.waitForTimeout(250);
|
||||||
|
await seite.selectOption("#f-art", "kampagne");
|
||||||
|
await seite.waitForTimeout(350);
|
||||||
|
|
||||||
|
const editoren = await seite.$$(".zeileneditor");
|
||||||
|
ok(editoren.length === 2, `zwei Zeilen-Editoren (Aufgaben, Regeln): ${editoren.length}`);
|
||||||
|
|
||||||
|
/* DIE TEXTGESTALTUNGS-LEISTE GEHOERT ZUM VERBORGENEN FELD und darf
|
||||||
|
nicht allein unter der Punkteliste schweben. */
|
||||||
|
const leisten = await seite.evaluate(() => {
|
||||||
|
const raus = [];
|
||||||
|
for (const id of ["f-aufgaben", "f-regeln"]) {
|
||||||
|
const f = document.getElementById(id);
|
||||||
|
const l = f?.parentElement?.querySelector(".textform");
|
||||||
|
raus.push({ id, feldVerborgen: !!f?.hidden, leisteVerborgen: l ? !!l.hidden : null });
|
||||||
|
}
|
||||||
|
return raus;
|
||||||
|
});
|
||||||
|
ok(leisten.length === 2 && leisten.every((x) => x.feldVerborgen && x.leisteVerborgen === true),
|
||||||
|
`Leiste ist mit ihrem Feld verborgen: ${JSON.stringify(leisten)}`);
|
||||||
|
|
||||||
|
/* Platzhalter passend zum Feld -- "22 Live-Stunden" unter REGELN
|
||||||
|
waere eine Fehlanleitung. */
|
||||||
|
const halter = await seite.evaluate(() =>
|
||||||
|
[...document.querySelectorAll(".zeileneditor")].map((r) =>
|
||||||
|
r.querySelector(".zeileneditor__feld")?.placeholder || ""));
|
||||||
|
ok(halter.length === 2 && halter[0] !== halter[1]
|
||||||
|
&& /Live-Stunden/.test(halter[0]) && /Konto/.test(halter[1]),
|
||||||
|
`je Feld ein eigenes Beispiel: ${JSON.stringify(halter)}`);
|
||||||
|
|
||||||
|
await seite.fill("#f-titel", "Testevent");
|
||||||
|
await seite.fill("#f-datum", tag(0));
|
||||||
|
await seite.fill("#f-ende", tag(13));
|
||||||
|
await seite.waitForTimeout(250);
|
||||||
|
const dauer = (await seite.textContent("#hinweis-dauer") || "").trim();
|
||||||
|
ok(dauer === "Läuft 14 Tage.", `Dauer wird mitgerechnet: ${JSON.stringify(dauer)}`);
|
||||||
|
|
||||||
|
/* GEGENPROBE: Ein Ende VOR dem Anfang muss auffallen -- sonst stuende
|
||||||
|
auf der frischen Karte "vorbei seit 3 Tagen". */
|
||||||
|
await seite.fill("#f-ende", tag(-3));
|
||||||
|
await seite.waitForTimeout(250);
|
||||||
|
const warnung = (await seite.textContent("#hinweis-dauer") || "").trim();
|
||||||
|
const warnMerkmal = await seite.getAttribute("#hinweis-dauer", "data-warnung");
|
||||||
|
ok(/vor dem Anfang/.test(warnung) && warnMerkmal === "ja",
|
||||||
|
`verdrehter Zeitraum faellt auf: ${JSON.stringify(warnung)}`);
|
||||||
|
await seite.fill("#f-ende", tag(13));
|
||||||
|
await seite.waitForTimeout(250);
|
||||||
|
|
||||||
|
/* Die Vorschau zeigt die echte Buehne. */
|
||||||
|
const vorschau = await seite.evaluate(() => {
|
||||||
|
const v = document.getElementById("ev-vorschau");
|
||||||
|
return {
|
||||||
|
sichtbar: v ? !v.hidden : false,
|
||||||
|
buehne: !!v?.querySelector(".ev-buehne"),
|
||||||
|
titel: v?.querySelector(".eintrag-titel")?.textContent || null,
|
||||||
|
noch: v?.querySelector(".ev-noch")?.textContent || null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
ok(vorschau.sichtbar && vorschau.buehne && vorschau.titel === "Testevent"
|
||||||
|
&& /^noch \d+ Tage?$/.test(vorschau.noch || ""),
|
||||||
|
`Vorschau zeigt die echte Buehne: ${JSON.stringify(vorschau)}`);
|
||||||
|
|
||||||
|
/* DER KERN DES FORMULAR-UMBAUS: Was am Ende gespeichert wird, ist
|
||||||
|
gleichmaessig -- egal wie jemand tippt. */
|
||||||
|
const felder = await seite.$$(".zeileneditor__feld");
|
||||||
|
await felder[0].fill("Jeden Tag Live gehen");
|
||||||
|
await seite.click(".zeileneditor__mehr");
|
||||||
|
const f2 = await seite.$$(".zeileneditor__feld");
|
||||||
|
await f2[1].fill("22 Live-Stunden erreichen");
|
||||||
|
await seite.waitForTimeout(250);
|
||||||
|
const roh2 = await seite.inputValue("#f-aufgaben");
|
||||||
|
ok(roh2 === "· Jeden Tag Live gehen\n· 22 Live-Stunden erreichen",
|
||||||
|
`gleichmaessig gesetzte Zeichen: ${JSON.stringify(roh2)}`);
|
||||||
|
|
||||||
|
/* Und das Ganze wirklich abschicken -- bis auf die Karte. */
|
||||||
|
await seite.click("#neu-speichern");
|
||||||
|
await seite.waitForTimeout(1200);
|
||||||
|
/* IM BRETT SUCHEN, NICHT IM FORMULAR.
|
||||||
|
Beim ersten Lauf stand hier ein Suchlauf ueber ALLE Karten der
|
||||||
|
Seite -- und die VORSCHAU im Formular ist ebenfalls eine Karte mit
|
||||||
|
demselben Merkmal und demselben Titel. Gefunden wurde sie zuerst,
|
||||||
|
und sie hat naturgemaess keine Aufgabenliste. Die Pruefung meldete
|
||||||
|
einen Fehler, den es nicht gab. */
|
||||||
|
const neu = await seite.evaluate(() => {
|
||||||
|
const liste = document.getElementById("liste");
|
||||||
|
const k = [...liste.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')]
|
||||||
|
.find((x) => x.textContent.includes("Testevent"));
|
||||||
|
return k ? {
|
||||||
|
punkte: [...k.querySelectorAll(".ev-block--aufgaben .ev-punkt__text")].map((x) => x.textContent),
|
||||||
|
zaehler: k.querySelector(".ev-zaehler")?.textContent || null,
|
||||||
|
} : null;
|
||||||
|
});
|
||||||
|
ok(!!neu && neu.punkte.length === 2
|
||||||
|
&& neu.punkte[0] === "Jeden Tag Live gehen"
|
||||||
|
&& neu.punkte[1] === "22 Live-Stunden erreichen",
|
||||||
|
`aus dem Editor wurde die Liste auf der Karte: ${JSON.stringify(neu)}`);
|
||||||
|
ok(neu?.zaehler === "0 von 2", `und der Zaehler steht auf null: ${neu?.zaehler}`);
|
||||||
|
|
||||||
|
/* NACH DEM SPEICHERN IST DIE VORSCHAU LEER. Sonst stuende beim
|
||||||
|
naechsten "Neuer Eintrag" das vorige Event darin -- und man
|
||||||
|
glaubte, es sei nicht gespeichert worden. */
|
||||||
|
const nachher = await seite.evaluate(() => {
|
||||||
|
const v = document.getElementById("ev-vorschau");
|
||||||
|
return { verborgen: !!v?.hidden, inhalt: (v?.textContent || "").trim().length };
|
||||||
|
});
|
||||||
|
ok(nachher.verborgen && nachher.inhalt === 0,
|
||||||
|
`die Vorschau ist zurueckgesetzt: ${JSON.stringify(nachher)}`);
|
||||||
|
|
||||||
|
await ctx.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
melde("\n=== 7. Auf dem Handy (412 px) ===");
|
||||||
|
{
|
||||||
|
const { ctx, seite } = await alsRolle("creator", "CODE-CREA-0001", 412);
|
||||||
|
const handy = await seite.evaluate(() => {
|
||||||
|
const k = [...document.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')]
|
||||||
|
.find((x) => x.textContent.includes("Oktober Event"));
|
||||||
|
const knopf = k.querySelector(".ev-punkt__knopf");
|
||||||
|
const b = k.querySelector(".ev-buehne");
|
||||||
|
return {
|
||||||
|
buehne: Math.round(b.getBoundingClientRect().height),
|
||||||
|
knopfHoehe: knopf ? Math.round(knopf.getBoundingClientRect().height) : 0,
|
||||||
|
/* Laeuft etwas ueber den Rand? Das haeufigste Handy-Problem. */
|
||||||
|
ueberlauf: Math.round(k.scrollWidth - k.clientWidth),
|
||||||
|
bloeckeSpalten: getComputedStyle(k.querySelector(".ev-bloecke")).gridTemplateColumns,
|
||||||
|
ganzHoehe: (() => { const a = k.querySelector(".ev-buehne__ganz");
|
||||||
|
return a ? Math.round(a.getBoundingClientRect().height) : null; })(),
|
||||||
|
ganzBreite: (() => { const a = k.querySelector(".ev-buehne__ganz");
|
||||||
|
return a ? Math.round(a.getBoundingClientRect().width) : null; })(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
melde(" -- gemessen: " + JSON.stringify(handy));
|
||||||
|
ok(handy.knopfHoehe >= 44,
|
||||||
|
`das Beruehrziel ist ${handy.knopfHoehe} px hoch (Grenze 44)`);
|
||||||
|
/* UND WENN DOCH, DANN WELCHES ELEMENT? Eine Zahl allein schickt
|
||||||
|
einen auf die Suche; der Schuldige steht im DOM und wird nur nicht
|
||||||
|
genannt. (Projektgedaechtnis: eine Pruefung, die nicht sagen kann,
|
||||||
|
woran sie scheitert, kostet eine Stunde.) */
|
||||||
|
if (handy.ueberlauf > 1) {
|
||||||
|
const taeter = await seite.evaluate(() => {
|
||||||
|
const k = [...document.querySelectorAll('.eintrag-karte[data-eventkarte="ja"]')]
|
||||||
|
.find((x) => x.textContent.includes("Oktober Event"));
|
||||||
|
const kr = k.getBoundingClientRect();
|
||||||
|
return [...k.querySelectorAll("*")]
|
||||||
|
.map((e) => ({ was: e.className || e.tagName,
|
||||||
|
rechts: Math.round(e.getBoundingClientRect().right - kr.right) }))
|
||||||
|
.filter((x) => x.rechts > 0)
|
||||||
|
.sort((a, b) => b.rechts - a.rechts).slice(0, 5);
|
||||||
|
});
|
||||||
|
melde(" -- was ueberlaeuft: " + JSON.stringify(taeter)
|
||||||
|
+ (taeter.length === 0
|
||||||
|
? " (KEIN Element -- dann ist es ein ::before/::after, das"
|
||||||
|
+ " querySelectorAll nicht findet. Beim ersten Mal war es"
|
||||||
|
+ " .ev-buehne__inhalt::before mit festem -20px gegen 14px Polsterung.)"
|
||||||
|
: ""));
|
||||||
|
}
|
||||||
|
ok(handy.ueberlauf <= 1, `nichts laeuft ueber den Rand (${handy.ueberlauf} px)`);
|
||||||
|
ok(handy.bloeckeSpalten.split(" ").length === 1,
|
||||||
|
`auf 412 px eine Spalte, nicht zwei: ${handy.bloeckeSpalten}`);
|
||||||
|
ok(handy.buehne <= 240 && handy.buehne > 0, `Buehne ${handy.buehne} px`);
|
||||||
|
/* Auf dem Handy schrumpft "Banner ganz" auf die Lupe -- das Ziel
|
||||||
|
darf dabei nicht unter 32 px fallen. (32 statt 44: Er sitzt frei
|
||||||
|
in einer Ecke ohne Nachbarn, und sein Wort bleibt fuer
|
||||||
|
Vorleseprogramme erhalten.) */
|
||||||
|
ok(handy.ganzHoehe !== null && handy.ganzHoehe >= 32 && handy.ganzBreite >= 32,
|
||||||
|
`der Banner-Knopf bleibt greifbar: ${handy.ganzBreite} x ${handy.ganzHoehe} px`);
|
||||||
|
await ctx.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
melde("\n=== 8. Das andere Haus bleibt unberuehrt ===");
|
||||||
|
{
|
||||||
|
/* DIE REGEL VOM 24.09.2026: "Ab sofort wird JEDER Umbau getrennt
|
||||||
|
gefuehrt. Eine Aenderung an einem der beiden Haeuser darf im
|
||||||
|
anderen nichts bewirken ... Wer etwas baut, sagt vorher, fuer
|
||||||
|
WELCHES Haus es ist, und weist danach nach, dass das andere
|
||||||
|
unveraendert ist."
|
||||||
|
|
||||||
|
DAS IST HIER NICHT SELBSTVERSTAENDLICH: `bereich.css` wird von
|
||||||
|
JEDEM Brett geladen, auch von denen der Crew, und `tuKnopf` ist
|
||||||
|
die Knopffabrik aller Bretter. Beides wurde angefasst. Dass
|
||||||
|
trotzdem nur Agentur-Events betroffen sind, haengt daran, dass
|
||||||
|
jede neue Regel an `[data-eventkarte="ja"]` oder einer `ev-`
|
||||||
|
Klasse haengt -- und dieses Merkmal setzt nur istEventArt().
|
||||||
|
Eine Behauptung, solange sie niemand nachmisst. */
|
||||||
|
const ctx = await browser.newContext({ viewport: { width: 1280, height: 1000 } });
|
||||||
|
await ctx.route("**/*", (route) => {
|
||||||
|
const u = new URL(route.request().url());
|
||||||
|
if (u.hostname === "127.0.0.1") {
|
||||||
|
return route.continue({ headers: { ...route.request().headers(), host: "crew.dogfather-universe.com" } });
|
||||||
|
}
|
||||||
|
return route.continue();
|
||||||
|
});
|
||||||
|
const seite = await ctx.newPage();
|
||||||
|
seite.on("pageerror", (f) => klagen.push("crew pageerror: " + f.message));
|
||||||
|
await seite.goto(BASIS + "/workspace/", { waitUntil: "networkidle" });
|
||||||
|
await seite.click('.rolle[data-rolle="admin"]');
|
||||||
|
await seite.fill("#code", "CODE-DOGI-0001");
|
||||||
|
await seite.click("button[type=submit]");
|
||||||
|
await seite.waitForURL("**/start.html", { timeout: 25000 });
|
||||||
|
|
||||||
|
/* Das Brett der Agentur gibt es auf dieser Adresse gar nicht. */
|
||||||
|
await seite.goto(BASIS + "/workspace/bereich.html?b=agentur", { waitUntil: "networkidle" });
|
||||||
|
await seite.waitForTimeout(900);
|
||||||
|
const dort = await seite.evaluate(() => ({
|
||||||
|
adresse: location.pathname,
|
||||||
|
eventkarten: document.querySelectorAll('[data-eventkarte="ja"]').length,
|
||||||
|
evTeile: document.querySelectorAll('[class*="ev-buehne"], [class*="ev-punkt"], .zeileneditor').length,
|
||||||
|
}));
|
||||||
|
/* ==== EIN BEFUND, DER NICHT AUS DIESEM UMBAU STAMMT ===============
|
||||||
|
|
||||||
|
Hier stand zuerst die Zusage "auf der Crew-Adresse nichts davon" --
|
||||||
|
und sie wurde rot: Das Agentur-Brett ist dort erreichbar, mit
|
||||||
|
Inhalt. Vor dem Schreiben einer Reparatur erst nachgemessen, ob
|
||||||
|
ich das verursacht habe (03.10.2026, server/_mess/haus.mjs, einmal
|
||||||
|
mit und einmal ohne den Umbau):
|
||||||
|
|
||||||
|
Host crew.dogfather-universe.com haus=crew
|
||||||
|
/workspace/api/bereich/agentur -> 200, 1 Eintrag
|
||||||
|
|
||||||
|
ZWEIMAL DASSELBE, mit und ohne. Der Durchgriff ist also aelter als
|
||||||
|
dieser Umbau und gehoert zur Regel vom 24.09.2026 ("Kein Bestand
|
||||||
|
wird geteilt"), nicht hierher -- er ist Filipe gemeldet und wird
|
||||||
|
getrennt entschieden. Ihn hier nebenbei zuzumauern hiesse, am
|
||||||
|
Rechtesystem beider Haeuser zu drehen, waehrend eigentlich eine
|
||||||
|
Karte umgebaut wird.
|
||||||
|
|
||||||
|
WAS DIESE DATEI DESHALB ZUSAGT, ist das, wofuer sie zustaendig
|
||||||
|
ist: Der Umbau aendert an der Crew-Adresse NICHTS -- die Karten
|
||||||
|
sehen dort aus wie auf der Agenturadresse, und die eigenen Bretter
|
||||||
|
der Crew bleiben unberuehrt (gleich darunter).
|
||||||
|
|
||||||
|
Die Zahl wird trotzdem ausgegeben: Faellt sie eines Tages auf 0,
|
||||||
|
ist der Durchgriff behoben, und das soll man hier sehen. */
|
||||||
|
melde(" -- Crew-Adresse, Brett `agentur`: " + JSON.stringify(dort)
|
||||||
|
+ (dort.eventkarten > 0
|
||||||
|
? " (vorbestehender Durchgriff, siehe Kommentar -- nicht aus diesem Umbau)"
|
||||||
|
: " (der Durchgriff ist behoben)"));
|
||||||
|
/* Wenn das Brett dort erscheint, dann wenigstens vollstaendig und
|
||||||
|
ohne Fehler -- eine halb gebaute Karte waere ein echter Schaden. */
|
||||||
|
ok(dort.eventkarten === 0 || dort.evTeile > 0,
|
||||||
|
`was dort erscheint, ist vollstaendig gebaut (${dort.eventkarten} Karten, ${dort.evTeile} Teile)`);
|
||||||
|
|
||||||
|
/* Und ein Brett, das es dort WIRKLICH gibt, sieht aus wie immer.
|
||||||
|
Ohne diese Haelfte waere oben nur bewiesen, dass die Seite leer
|
||||||
|
ist -- das waere sie auch bei einem kaputten Brett. */
|
||||||
|
await seite.goto(BASIS + "/workspace/bereich.html?b=treff", { waitUntil: "networkidle" });
|
||||||
|
await seite.waitForTimeout(900);
|
||||||
|
const treff = await seite.evaluate(() => ({
|
||||||
|
liste: !!document.getElementById("liste"),
|
||||||
|
formular: !!document.getElementById("neu"),
|
||||||
|
knoepfe: document.querySelectorAll(".schritt").length,
|
||||||
|
gefahr: document.querySelectorAll(".schritt--gefahr").length,
|
||||||
|
evTeile: document.querySelectorAll('[class*="ev-buehne"], [class*="ev-punkt"], .zeileneditor').length,
|
||||||
|
}));
|
||||||
|
ok(treff.liste && treff.formular,
|
||||||
|
`ein Crew-Brett steht und funktioniert: ${JSON.stringify(treff)}`);
|
||||||
|
ok(treff.evTeile === 0, `und zeigt keinen Teil des Event-Umbaus (${treff.evTeile})`);
|
||||||
|
/* Auch der Loeschknopf bleibt dort der alte: Die Markierung wird
|
||||||
|
zwar ueberall gesetzt, aber gestaltet wird sie nur innerhalb einer
|
||||||
|
Eventkarte. */
|
||||||
|
const farben = await seite.evaluate(() => {
|
||||||
|
const g = document.querySelector(".schritt--gefahr");
|
||||||
|
const n = document.querySelector(".schritt:not(.schritt--gefahr)");
|
||||||
|
return g && n ? { gefahr: getComputedStyle(g).color, normal: getComputedStyle(n).color } : null;
|
||||||
|
});
|
||||||
|
ok(farben === null || farben.gefahr === farben.normal,
|
||||||
|
`der Loeschknopf sieht dort aus wie immer: ${JSON.stringify(farben)}`);
|
||||||
|
|
||||||
|
await ctx.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
await browser.close();
|
||||||
|
|
||||||
|
melde("\n=== Browser-Meldungen ===");
|
||||||
|
ok(klagen.length === 0, klagen.length ? "Klagen: " + klagen.join(" | ") : "keine Fehler in der Konsole");
|
||||||
|
|
||||||
|
melde("");
|
||||||
|
melde(`${geprueft} geprueft, ${fehler} Fehler`);
|
||||||
|
if (!geprueft) { melde("ABBRUCH: nichts geprueft -- das ist ein Fehler, kein Erfolg."); process.exit(3); }
|
||||||
|
process.exit(fehler ? 1 : 0);
|
||||||
@@ -20,7 +20,7 @@ import express from "express";
|
|||||||
Fassung, und an ihr haengt die Sicherheit aller Uploads im Haus. */
|
Fassung, und an ihr haengt die Sicherheit aller Uploads im Haus. */
|
||||||
import { writeFileSync, mkdirSync, unlinkSync } from "node:fs";
|
import { writeFileSync, mkdirSync, unlinkSync } from "node:fs";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { randomBytes } from "node:crypto";
|
import { randomBytes, createHash } from "node:crypto";
|
||||||
import { dateiErkennen } from "./workspace-chat.js";
|
import { dateiErkennen } from "./workspace-chat.js";
|
||||||
import { TREFF_START, VORSCHLAG_HINWEIS } from "./workspace-treff-start.js";
|
import { TREFF_START, VORSCHLAG_HINWEIS } from "./workspace-treff-start.js";
|
||||||
import { vorlagenFuer } from "./workspace-treff-vorlagen.js";
|
import { vorlagenFuer } from "./workspace-treff-vorlagen.js";
|
||||||
@@ -752,6 +752,89 @@ const MIT_ANTWORTEN = new Set(["treff", "wunsch"]);
|
|||||||
const TITEL_MAX = 160;
|
const TITEL_MAX = 160;
|
||||||
const TEXT_MAX = 6000;
|
const TEXT_MAX = 6000;
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DIE PUNKTE EINES AGENTUR-EVENTS (03.10.2026)
|
||||||
|
|
||||||
|
`event_aufgaben` und `event_regeln` sind Fliesstext, den DogFather
|
||||||
|
tippt -- eine Zeile je Punkt, meistens mit einem Aufzaehlungszeichen
|
||||||
|
davor. Dass er von Hand gesetzt wird, sieht man dem Ergebnis an: Im
|
||||||
|
echten Oktober-Event stand „·Jeden Tag Live gehen" neben
|
||||||
|
„· 33k Diamanten erreichen", einmal mit Leerzeichen, einmal ohne.
|
||||||
|
|
||||||
|
HIER WIRD DARAUS EINE LISTE. Die Oberflaeche bekommt Punkte, keinen
|
||||||
|
Absatz -- damit sie Haken daran haengen kann und die Einrueckung
|
||||||
|
nicht mehr davon abhaengt, wie jemand getippt hat.
|
||||||
|
|
||||||
|
DER SPEICHERTEXT BLEIBT UNVERAENDERT. Zerlegt wird beim LESEN, nicht
|
||||||
|
beim Schreiben: Wer das Event spaeter bearbeitet, soll genau das
|
||||||
|
wiederfinden, was er geschrieben hat. Und ein Textfeld, das beim
|
||||||
|
Speichern umformatiert wird, ist ein Textfeld, dem man nicht traut.
|
||||||
|
===================================================================== */
|
||||||
|
|
||||||
|
/* Die Zeichen, mit denen Menschen Aufzaehlungen anfangen. Sie gehoeren
|
||||||
|
nicht zum Inhalt des Punktes -- und wer heute „·" tippt und morgen
|
||||||
|
„-", meint denselben Punkt. */
|
||||||
|
const PUNKT_ZEICHEN = /^[\s]*[-–—•·*▪◦‣>+]+[\s]*/u;
|
||||||
|
|
||||||
|
/** Der Kern einer Aufgabenzeile, ohne Zierde.
|
||||||
|
* Nur fuer den Vergleich gedacht -- angezeigt wird der Originaltext. */
|
||||||
|
function punktKern(zeile) {
|
||||||
|
return String(zeile || "")
|
||||||
|
.replace(PUNKT_ZEICHEN, "")
|
||||||
|
/* Eine fuehrende Nummerierung („1.", „2)") ebenfalls weg: Wer
|
||||||
|
einen Punkt davorsetzt, verschiebt sonst alle Nummern und damit
|
||||||
|
alle Schluessel -- genau der stille Haken-Umzug, den die Tabelle
|
||||||
|
verhindern soll. */
|
||||||
|
.replace(/^\s*\d+[.)]\s*/, "")
|
||||||
|
.replace(/\s+/gu, " ")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Der Schluessel, unter dem ein Haken gespeichert wird.
|
||||||
|
*
|
||||||
|
* AUS DEM TEXT, NICHT AUS DER ZEILENNUMMER -- die Begruendung steht
|
||||||
|
* bei der Tabelle `event_punkte` in workspace.js. Hier nur das Wie:
|
||||||
|
* Kern bilden, davon die ersten 16 Zeichen des SHA-256. 16 Zeichen
|
||||||
|
* sind 64 Bit; bei hoechstens ein paar Dutzend Punkten je Event ist
|
||||||
|
* eine Verwechslung ausgeschlossen, und der Schluessel bleibt kurz
|
||||||
|
* genug, um in einer Adresse zu stehen. */
|
||||||
|
export function punktSchluessel(zeile) {
|
||||||
|
return createHash("sha256").update(punktKern(zeile), "utf8")
|
||||||
|
.digest("hex").slice(0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Zerlegt ein Textfeld in Punkte.
|
||||||
|
*
|
||||||
|
* LEERE ZEILEN FALLEN WEG, aber nicht die Absicht dahinter: Wer eine
|
||||||
|
* Leerzeile zwischen zwei Bloecke setzt, trennt -- und das ergibt in
|
||||||
|
* einer Liste ohnehin keinen eigenen Punkt.
|
||||||
|
*
|
||||||
|
* GLEICHE PUNKTE NUR EINMAL: Stuende „22 Live-Stunden" zweimal da,
|
||||||
|
* haetten beide denselben Schluessel. Ein Haken wuerde dann an zwei
|
||||||
|
* Stellen gleichzeitig erscheinen und die Zaehlung „2 von 3" waere
|
||||||
|
* falsch. Der zweite faellt deshalb weg -- zusammen mit der Zeile,
|
||||||
|
* denn eine doppelte Bedingung ist ohnehin ein Tippfehler. */
|
||||||
|
export function punkteAusText(text) {
|
||||||
|
const raus = [];
|
||||||
|
const gesehen = new Set();
|
||||||
|
for (const zeile of String(text || "").split(/\r?\n/)) {
|
||||||
|
const kern = punktKern(zeile);
|
||||||
|
if (!kern) continue;
|
||||||
|
const schluessel = punktSchluessel(zeile);
|
||||||
|
if (gesehen.has(schluessel)) continue;
|
||||||
|
gesehen.add(schluessel);
|
||||||
|
raus.push({
|
||||||
|
schluessel,
|
||||||
|
/* Angezeigt wird der Text OHNE das getippte Aufzaehlungszeichen:
|
||||||
|
Die Liste setzt ihr eigenes, und zwei davon nebeneinander
|
||||||
|
sehen nach einem Fehler aus. */
|
||||||
|
text: String(zeile).replace(PUNKT_ZEICHEN, "").trim(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return raus;
|
||||||
|
}
|
||||||
|
|
||||||
const jetzt = () => new Date().toISOString();
|
const jetzt = () => new Date().toISOString();
|
||||||
|
|
||||||
function angemeldet(req, res, next) {
|
function angemeldet(req, res, next) {
|
||||||
@@ -1525,6 +1608,73 @@ bereicheRouter.get("/workspace/api/bereich/:bereich", (req, res) => {
|
|||||||
}
|
}
|
||||||
for (const e of eintraege) e.antworten = jeE.get(e.id) || [];
|
for (const e of eintraege) e.antworten = jeE.get(e.id) || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==== DIE PUNKTE EINES EVENTS (03.10.2026) ====================
|
||||||
|
|
||||||
|
Aus dem Fliesstext in event_aufgaben/event_regeln wird eine
|
||||||
|
Liste, und an die Aufgaben kommen die Haken der eigenen
|
||||||
|
Person. Zerlegt wird HIER und nicht im Browser: Der Schluessel
|
||||||
|
eines Punktes entscheidet, wo ein Haken landet -- eine zweite
|
||||||
|
Rechenvorschrift dafuer waere die, die beim naechsten Umbau
|
||||||
|
auslaeuft, und zwar still.
|
||||||
|
|
||||||
|
IN EINER ABFRAGE FUER DIE GANZE LISTE, wie bei den Bildern und
|
||||||
|
den Antworten darueber. Ein Event hat ein Dutzend Punkte und
|
||||||
|
ein Brett ein Dutzend Events; einzeln gefragt waere das bei
|
||||||
|
jedem Seitenaufbau ein Schwall kleiner Abfragen.
|
||||||
|
|
||||||
|
NUR DORT, WO ES EVENTS GIBT. Auf den uebrigen Brettern sind
|
||||||
|
diese Felder leer, und eine Abfrage mit leerer Liste ist eine
|
||||||
|
Abfrage ohne Zweck. */
|
||||||
|
const events = eintraege.filter((e) => e.event_aufgaben || e.event_regeln);
|
||||||
|
if (events.length) {
|
||||||
|
const ichId = (req.sicht || req.person)?.id;
|
||||||
|
const p5 = events.map(() => "?").join(", ");
|
||||||
|
/* Meine eigenen Haken ... */
|
||||||
|
const meine = new Map();
|
||||||
|
for (const z of db().prepare(
|
||||||
|
`SELECT eintrag_id, punkt FROM event_punkte
|
||||||
|
WHERE eintrag_id IN (${p5}) AND person_id = ?`)
|
||||||
|
.all(...events.map((e) => e.id), ichId)) {
|
||||||
|
if (!meine.has(z.eintrag_id)) meine.set(z.eintrag_id, new Set());
|
||||||
|
meine.get(z.eintrag_id).add(z.punkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... und fuer die Leitung: wer macht mit, und wie weit?
|
||||||
|
|
||||||
|
NUR FUER DIE LEITUNG. „Wer hat was geschafft" ist eine
|
||||||
|
Auskunft ueber andere Personen; die gehoert nicht an jede
|
||||||
|
Karte, die irgendwer aufmacht. Wer nicht zur Leitung gehoert,
|
||||||
|
bekommt das Feld gar nicht erst -- nicht leer, sondern
|
||||||
|
ueberhaupt nicht: Ein leeres Feld laedt dazu ein, es spaeter
|
||||||
|
„versehentlich" zu fuellen. */
|
||||||
|
const stand = new Map();
|
||||||
|
if (istLeitung(req.person)) {
|
||||||
|
for (const z of db().prepare(
|
||||||
|
`SELECT ep.eintrag_id, ep.person_id, p.name, COUNT(*) AS n
|
||||||
|
FROM event_punkte ep
|
||||||
|
LEFT JOIN personen p ON p.id = ep.person_id
|
||||||
|
WHERE ep.eintrag_id IN (${p5})
|
||||||
|
GROUP BY ep.eintrag_id, ep.person_id
|
||||||
|
ORDER BY n DESC, p.name`)
|
||||||
|
.all(...events.map((e) => e.id))) {
|
||||||
|
if (!stand.has(z.eintrag_id)) stand.set(z.eintrag_id, []);
|
||||||
|
stand.get(z.eintrag_id).push({ id: z.person_id, name: z.name, geschafft: z.n });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const e of events) {
|
||||||
|
const haken = meine.get(e.id) || new Set();
|
||||||
|
e.event_punkte = punkteAusText(e.event_aufgaben)
|
||||||
|
.map((p) => ({ ...p, meiner: haken.has(p.schluessel) }));
|
||||||
|
e.event_regelpunkte = punkteAusText(e.event_regeln);
|
||||||
|
/* DIE ZAHL KOMMT MIT, statt im Browser gezaehlt zu werden --
|
||||||
|
sie steht sonst an zwei Stellen, und „2 von 3" ist genau
|
||||||
|
die Sorte Angabe, die man nicht zweimal haben will. */
|
||||||
|
e.event_geschafft = e.event_punkte.filter((p) => p.meiner).length;
|
||||||
|
if (stand.size) e.event_stand = stand.get(e.id) || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DASS DIES EIN BRETT DES TREFFS IST, SAGT DER SERVER (11.09.2026).
|
/* DASS DIES EIN BRETT DES TREFFS IST, SAGT DER SERVER (11.09.2026).
|
||||||
@@ -2555,6 +2705,41 @@ bereicheRouter.post("/workspace/api/bereich/:bereich", gleicheHerkunft, (req, re
|
|||||||
|
|
||||||
/* ---------- Ändern und Löschen ------------------------------------------- */
|
/* ---------- Ändern und Löschen ------------------------------------------- */
|
||||||
|
|
||||||
|
/** Darf diese Person diesen Eintrag sehen?
|
||||||
|
*
|
||||||
|
* ENTSTANDEN AM 03.10.2026, weil das Banner eines Agentur-Events fuer
|
||||||
|
* Creator mit 404 beantwortet wurde -- gemessen, nicht vermutet:
|
||||||
|
*
|
||||||
|
* workspace.dogfather-universe.com admin Bild=200
|
||||||
|
* workspace.dogfather-universe.com creator Bild=404
|
||||||
|
*
|
||||||
|
* Der Bildweg (workspace-dateien.js) kannte bisher zwei Regeln: die
|
||||||
|
* Treff-Regel ("wer das Brett sieht, sieht das Bild" -- aber nur fuer
|
||||||
|
* die sieben Community-Bretter) und sonst die ABLAGE-Regel, die an
|
||||||
|
* Creator-Zuordnungen haengt. Ein Agentur-Event ist weder das eine
|
||||||
|
* noch das andere: Es gehoert niemandem, und `agentur` ist kein
|
||||||
|
* Treff-Brett. Also fiel es durch beide.
|
||||||
|
*
|
||||||
|
* Vor dem Umbau fiel das kaum auf -- das Bild war ein Anhang unter
|
||||||
|
* dem Text. Seit es die Buehne hinter dem Titel ist, saehe eine
|
||||||
|
* Creatorin eine leere Flaeche an genau der Karte, die fuer sie
|
||||||
|
* gemacht ist.
|
||||||
|
*
|
||||||
|
* WARUM EINE FUNKTION UND KEINE ZWEITE LISTE: Der naheliegende Weg
|
||||||
|
* waere gewesen, in workspace-dateien.js `|| e.bereich === "agentur"`
|
||||||
|
* zu ergaenzen. Das waere eine zweite Stelle, an der steht, wer was
|
||||||
|
* sehen darf -- und die laeuft beim naechsten Brett aus. Hier wird
|
||||||
|
* stattdessen dieselbe Regel gefragt, die auch das Brett selbst
|
||||||
|
* benutzt (sichtbarEintrag). Was dort verborgen ist, bleibt es auch
|
||||||
|
* hier; es gibt keine Rechteausweitung, nur keine Luecke mehr. */
|
||||||
|
export function darfEintragSehen(person, eintragId) {
|
||||||
|
if (!person || !Number.isInteger(Number(eintragId))) return false;
|
||||||
|
const regel = sichtbarEintrag(person);
|
||||||
|
if (!regel) return false;
|
||||||
|
return !!db().prepare(`SELECT e.id ${VERBUND} WHERE ${regel.wo} AND e.id = ?`)
|
||||||
|
.get(...regel.werte, Number(eintragId));
|
||||||
|
}
|
||||||
|
|
||||||
function holen(req, id) {
|
function holen(req, id) {
|
||||||
const regel = sichtbarEintrag(req.person);
|
const regel = sichtbarEintrag(req.person);
|
||||||
if (!regel) return null;
|
if (!regel) return null;
|
||||||
@@ -2674,6 +2859,114 @@ function darfBildAnhaengen(req, res, next) {
|
|||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
EINEN PUNKT ABHAKEN (03.10.2026)
|
||||||
|
|
||||||
|
Filipe: „ich will das viel geiler viel perfekter. und auch wenn man
|
||||||
|
die eintraegt und so soll viel mehr perfektioniert und
|
||||||
|
uebersichtlicher sein."
|
||||||
|
|
||||||
|
Ein Agentur-Event stellt Bedingungen -- „jeden Tag live",
|
||||||
|
„22 Live-Stunden", „33k Diamanten". Wer mitmacht, will sehen, wo er
|
||||||
|
steht, ohne nachzufragen. Genau das ist der Unterschied zwischen
|
||||||
|
einem Aushang und einer Aktion, an der jemand teilnimmt.
|
||||||
|
|
||||||
|
JEDER HAKT NUR FUER SICH SELBST. Es gibt bewusst keinen Weg, einen
|
||||||
|
Haken bei einer ANDEREN Person zu setzen -- auch nicht fuer die
|
||||||
|
Leitung. „Ich habe meine 22 Stunden" ist eine Aussage ueber sich,
|
||||||
|
und wer sie fuer andere treffen koennte, macht aus einer Selbstaus-
|
||||||
|
kunft eine Bewertung. Die Person steht deshalb nirgends in der
|
||||||
|
Adresse; sie kommt aus der Sitzung.
|
||||||
|
|
||||||
|
KEIN KOERPER BEIM DELETE (gemessen 11.09.2026, steht so schon in
|
||||||
|
bereich.js): Nodes HTTP-Parser weist ein DELETE mit Koerper mit
|
||||||
|
einem leeren 400 ab, bevor Express die Anfrage sieht.
|
||||||
|
===================================================================== */
|
||||||
|
function punktZugang(req, res, next) {
|
||||||
|
const id = Number(req.params.id);
|
||||||
|
const schluessel = String(req.params.punkt || "");
|
||||||
|
/* Der Schluessel ist 16 Hexzeichen -- was anders aussieht, kommt
|
||||||
|
nicht aus unserer Liste und hat in der Tabelle nichts zu suchen.
|
||||||
|
Ohne diese Pruefung koennte jemand beliebigen Text ablegen und die
|
||||||
|
Tabelle als Notizbuch missbrauchen. */
|
||||||
|
if (!Number.isInteger(id) || !/^[0-9a-f]{16}$/.test(schluessel)) {
|
||||||
|
return res.status(400).json({ fehler: "ungueltig" });
|
||||||
|
}
|
||||||
|
const eintrag = holen(req, id);
|
||||||
|
if (!eintrag) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||||
|
|
||||||
|
/* GEHOERT DER PUNKT UEBERHAUPT ZU DIESEM EVENT?
|
||||||
|
|
||||||
|
Das ist der eigentliche Grund fuer diesen Waechter. Ohne ihn
|
||||||
|
koennte man einen beliebigen gueltig aussehenden Schluessel
|
||||||
|
setzen; die Zahl „3 von 3" waere danach erreichbar, ohne dass eine
|
||||||
|
der drei Aufgaben je dastand. Eine Zaehlung, die man sich selbst
|
||||||
|
ausdenken kann, zaehlt nichts.
|
||||||
|
|
||||||
|
Gefragt wird die LISTE, nicht der Text: punkteAusText ist die eine
|
||||||
|
Stelle, die entscheidet, was ein Punkt ist. */
|
||||||
|
const punkte = punkteAusText(eintrag.event_aufgaben);
|
||||||
|
if (!punkte.some((p) => p.schluessel === schluessel)) {
|
||||||
|
return res.status(404).json({ fehler: "punkt_unbekannt" });
|
||||||
|
}
|
||||||
|
req.eventEintrag = eintrag;
|
||||||
|
req.eventPunkt = schluessel;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
bereicheRouter.put("/workspace/api/eintrag/:id(\\d+)/punkt/:punkt",
|
||||||
|
angemeldet, gleicheHerkunft, punktZugang, (req, res) => {
|
||||||
|
try {
|
||||||
|
/* ON CONFLICT DO NOTHING und kein Fehler beim zweiten Mal: Zwei
|
||||||
|
Klicks kurz hintereinander (oder ein zweites Geraet) sind kein
|
||||||
|
Versehen, das man melden muesste -- das Ergebnis ist in beiden
|
||||||
|
Faellen „der Haken ist gesetzt". */
|
||||||
|
db().prepare(
|
||||||
|
"INSERT INTO event_punkte (eintrag_id, person_id, punkt, gesetzt)"
|
||||||
|
+ " VALUES (?,?,?,?) ON CONFLICT DO NOTHING")
|
||||||
|
.run(req.eventEintrag.id, req.person.id, req.eventPunkt, jetzt());
|
||||||
|
res.json(punktStand(req.eventEintrag, req.person.id));
|
||||||
|
} catch (fehler) {
|
||||||
|
console.error("[bereich] Punkt setzen:", fehler?.message);
|
||||||
|
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bereicheRouter.delete("/workspace/api/eintrag/:id(\\d+)/punkt/:punkt",
|
||||||
|
angemeldet, gleicheHerkunft, punktZugang, (req, res) => {
|
||||||
|
try {
|
||||||
|
db().prepare(
|
||||||
|
"DELETE FROM event_punkte WHERE eintrag_id = ? AND person_id = ? AND punkt = ?")
|
||||||
|
.run(req.eventEintrag.id, req.person.id, req.eventPunkt);
|
||||||
|
res.json(punktStand(req.eventEintrag, req.person.id));
|
||||||
|
} catch (fehler) {
|
||||||
|
console.error("[bereich] Punkt loeschen:", fehler?.message);
|
||||||
|
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Was nach einem Haken zurueckgeht: der gueltige Stand, vom Server.
|
||||||
|
*
|
||||||
|
* NICHT „ok". Der Browser rechnet sonst selbst weiter („war 2, jetzt
|
||||||
|
* 3") -- und liegt daneben, sobald zwei Fenster offen sind oder eine
|
||||||
|
* Aufgabe inzwischen umgeschrieben wurde. Die Zahl, die auf der Karte
|
||||||
|
* steht, kommt immer von hier. */
|
||||||
|
function punktStand(eintrag, personId) {
|
||||||
|
const punkte = punkteAusText(eintrag.event_aufgaben);
|
||||||
|
const meine = new Set(db().prepare(
|
||||||
|
"SELECT punkt FROM event_punkte WHERE eintrag_id = ? AND person_id = ?")
|
||||||
|
.all(eintrag.id, personId).map((z) => z.punkt));
|
||||||
|
return {
|
||||||
|
gesamt: punkte.length,
|
||||||
|
/* Nur zaehlen, was AUCH in der Liste steht: Wird eine Aufgabe
|
||||||
|
umgeschrieben, bleibt ihr alter Haken als Zeile liegen (das ist
|
||||||
|
richtig, siehe Tabelle) -- mitzaehlen darf er nicht. */
|
||||||
|
geschafft: punkte.filter((p) => meine.has(p.schluessel)).length,
|
||||||
|
punkte: punkte.map((p) => ({ ...p, meiner: meine.has(p.schluessel) })),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
bereicheRouter.post("/workspace/api/bereich/:bereich/:id(\\d+)/bild",
|
bereicheRouter.post("/workspace/api/bereich/:bereich/:id(\\d+)/bild",
|
||||||
gleicheHerkunft,
|
gleicheHerkunft,
|
||||||
darfBildAnhaengen,
|
darfBildAnhaengen,
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ import {
|
|||||||
ohneTeamDogi, ohneAgentur, siehtModis,
|
ohneTeamDogi, ohneAgentur, siehtModis,
|
||||||
TREFF_BRETTER, TREFF_ROLLEN,
|
TREFF_BRETTER, TREFF_ROLLEN,
|
||||||
} from "./workspace.js";
|
} from "./workspace.js";
|
||||||
|
/* Die eine Stelle, die beantwortet, wer welchen Eintrag sehen darf.
|
||||||
|
Kein Zirkel: workspace-bereiche.js kennt diese Datei nicht. */
|
||||||
|
import { darfEintragSehen } from "./workspace-bereiche.js";
|
||||||
|
|
||||||
export const dateienRouter = express.Router();
|
export const dateienRouter = express.Router();
|
||||||
|
|
||||||
@@ -658,6 +661,29 @@ dateienRouter.get("/workspace/api/dateien/:id/bild", (req, res) => {
|
|||||||
const e = db().prepare("SELECT bereich FROM eintraege WHERE id = ?").get(datei.eintrag_id);
|
const e = db().prepare("SELECT bereich FROM eintraege WHERE id = ?").get(datei.eintrag_id);
|
||||||
erlaubt = !!e && TREFF_BRETTER.includes(e.bereich)
|
erlaubt = !!e && TREFF_BRETTER.includes(e.bereich)
|
||||||
&& TREFF_ROLLEN.has((req.sicht || req.person)?.rolle);
|
&& TREFF_ROLLEN.has((req.sicht || req.person)?.rolle);
|
||||||
|
/* ==== UND SONST: WER DEN EINTRAG SIEHT, SIEHT SEIN BILD =======
|
||||||
|
(03.10.2026, gemessen am Banner eines Agentur-Events.)
|
||||||
|
|
||||||
|
Die Zeile darueber deckt die sieben Community-Bretter ab. Ein
|
||||||
|
Agentur-Event ist keines davon -- und es gehoert auch
|
||||||
|
niemandem, also griff danach auch die Ablage-Regel nicht, die
|
||||||
|
an Creator-Zuordnungen haengt. Ergebnis, nachgemessen:
|
||||||
|
|
||||||
|
admin -> Bild 200
|
||||||
|
creator -> Bild 404
|
||||||
|
|
||||||
|
Also genau an der Karte, die fuer Creator gemacht ist, eine
|
||||||
|
leere Buehne. Vor dem Umbau war das Bild ein Anhang unter dem
|
||||||
|
Text und fiel kaum auf.
|
||||||
|
|
||||||
|
GEFRAGT WIRD DIESELBE REGEL WIE AUF DEM BRETT
|
||||||
|
(darfEintragSehen -> sichtbarEintrag). Keine zweite Liste von
|
||||||
|
Brettnamen hier: Was dort verborgen ist, bleibt auch hier
|
||||||
|
verborgen, und beim naechsten neuen Brett muss niemand daran
|
||||||
|
denken. Die Gegenprobe dazu steht in pruef-eventkarte.mjs --
|
||||||
|
ein Eintrag, den die Person NICHT sehen darf, liefert
|
||||||
|
weiterhin 404. */
|
||||||
|
if (!erlaubt) erlaubt = darfEintragSehen(req.sicht || req.person, datei.eintrag_id);
|
||||||
}
|
}
|
||||||
if (!erlaubt) {
|
if (!erlaubt) {
|
||||||
const { wo, werte } = sichtbar(req.person);
|
const { wo, werte } = sichtbar(req.person);
|
||||||
|
|||||||
@@ -5940,6 +5940,57 @@ export function db() {
|
|||||||
geaendert TEXT
|
geaendert TEXT
|
||||||
);
|
);
|
||||||
CREATE INDEX IF NOT EXISTS idx_eintraege_bereich ON eintraege (bereich, creator_id);
|
CREATE INDEX IF NOT EXISTS idx_eintraege_bereich ON eintraege (bereich, creator_id);
|
||||||
|
|
||||||
|
/* =================================================================
|
||||||
|
WER HAT WELCHEN PUNKT EINES EVENTS GESCHAFFT? (03.10.2026)
|
||||||
|
|
||||||
|
Filipe: „ich will das viel geiler viel perfekter."
|
||||||
|
|
||||||
|
Ein Agentur-Event ist ein Wettbewerb mit Bedingungen -- „jeden
|
||||||
|
Tag live", „22 Live-Stunden", „33k Diamanten". Bis heute stand
|
||||||
|
das als Fliesstext auf der Karte, und jede Creatorin musste
|
||||||
|
sich selbst merken, wo sie steht. Genau daran stirbt eine
|
||||||
|
Aktion: nicht am Aufruf, sondern daran, dass niemand seinen
|
||||||
|
eigenen Stand sieht.
|
||||||
|
|
||||||
|
EINE ZEILE IST EIN HAKEN -- eine Person, ein Punkt. Kein Feld
|
||||||
|
am Eintrag mit einer Liste darin: „jeder fuer sich" heisst,
|
||||||
|
dass zwanzig Personen am SELBEN Event verschiedene Haken
|
||||||
|
haben. Dieselbe Ueberlegung steht schon bei termin_wecker.
|
||||||
|
|
||||||
|
WARUM EIN SCHLUESSEL AUS DEM TEXT UND KEINE ZEILENNUMMER:
|
||||||
|
Die Aufgaben stehen als Text in der Spalte
|
||||||
|
event_aufgaben;
|
||||||
|
DogFather kann sie jederzeit umschreiben. Haengt der Haken an
|
||||||
|
„Zeile 2", wandert er beim Einfuegen einer Zeile darueber
|
||||||
|
stillschweigend auf eine andere Aufgabe -- und jemand hat
|
||||||
|
plotzlich etwas abgehakt, was er nie gemacht hat. Das ist der
|
||||||
|
schlimmere Ausgang, weil es niemandem auffaellt.
|
||||||
|
|
||||||
|
Haengt er dagegen am TEXT der Zeile, gilt: Zeilen umsortieren
|
||||||
|
oder daruebersetzen aendert nichts; wird die Aufgabe selbst
|
||||||
|
umgeschrieben, faellt ihr Haken weg. Letzteres ist richtig --
|
||||||
|
eine geaenderte Bedingung ist eine andere Bedingung, und ein
|
||||||
|
Haken daran waere eine Falschauskunft.
|
||||||
|
|
||||||
|
Der Schluessel wird in workspace-bereiche.js gebildet
|
||||||
|
(punktSchluessel); hier steht er nur als Text. Eine zweite
|
||||||
|
Rechenvorschrift in der Datenbank waere die, die auslaeuft.
|
||||||
|
|
||||||
|
ON DELETE CASCADE an beiden Seiten: Ein Haken ohne Event ist
|
||||||
|
nichts, und einer ohne Person auch nicht. */
|
||||||
|
CREATE TABLE IF NOT EXISTS event_punkte (
|
||||||
|
eintrag_id INTEGER NOT NULL REFERENCES eintraege(id) ON DELETE CASCADE,
|
||||||
|
person_id INTEGER NOT NULL REFERENCES personen(id) ON DELETE CASCADE,
|
||||||
|
punkt TEXT NOT NULL,
|
||||||
|
gesetzt TEXT NOT NULL,
|
||||||
|
PRIMARY KEY (eintrag_id, person_id, punkt)
|
||||||
|
);
|
||||||
|
/* Fuer „wie weit ist mein Team?" -- die Abfrage geht ueber das
|
||||||
|
Event, nicht ueber die Person. */
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_event_punkte_eintrag
|
||||||
|
ON event_punkte (eintrag_id);
|
||||||
|
|
||||||
/* Die Tabellen des Rudels folgen weiter unten, gleich nachdem
|
/* Die Tabellen des Rudels folgen weiter unten, gleich nachdem
|
||||||
dieser Bauplan durch ist -- sie haengen an eintraege und
|
dieser Bauplan durch ist -- sie haengen an eintraege und
|
||||||
personen und koennen deshalb nicht davor stehen. Ihr SQL steht
|
personen und koennen deshalb nicht davor stehen. Ihr SQL steht
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
verdeckt. Gefunden hat es pruef-struktur.
|
verdeckt. Gefunden hat es pruef-struktur.
|
||||||
|
|
||||||
Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. -->
|
Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. -->
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
<!-- Ohne diese drei nimmt ein iPhone einen Bildschirmausschnitt als
|
<!-- Ohne diese drei nimmt ein iPhone einen Bildschirmausschnitt als
|
||||||
Symbol, Android zeichnet die Leiste weiss, und die Seite oeffnet
|
Symbol, Android zeichnet die Leiste weiss, und die Seite oeffnet
|
||||||
ausserhalb der App -- auf einer Seite, die genau erklaeren soll,
|
ausserhalb der App -- auf einer Seite, die genau erklaeren soll,
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
schreibt jede Seite app.webmanifest -- auch die hier. -->
|
schreibt jede Seite app.webmanifest -- auch die hier. -->
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<style>
|
<style>
|
||||||
/* Bewusst in der Seite und nicht in einer eigenen Datei: Diese Seite
|
/* Bewusst in der Seite und nicht in einer eigenen Datei: Diese Seite
|
||||||
soll auch dann noch etwas anzeigen, wenn genau das schiefgeht,
|
soll auch dann noch etwas anzeigen, wenn genau das schiefgeht,
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/anruf-probe.js?v=202610031525" defer></script>
|
<script src="assets/js/anruf-probe.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -23,25 +23,25 @@
|
|||||||
},
|
},
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/workspace-192.png?v=202610031525",
|
"src": "/assets/img/app-symbole/workspace-192.png?v=202610031857",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/workspace-512.png?v=202610031525",
|
"src": "/assets/img/app-symbole/workspace-512.png?v=202610031857",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202610031525",
|
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202610031857",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202610031525",
|
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202610031857",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
|
|||||||
@@ -543,85 +543,28 @@
|
|||||||
Zustand zusaetzlich als WORT da ("läuft bis 30.09.2026").
|
Zustand zusaetzlich als WORT da ("läuft bis 30.09.2026").
|
||||||
===================================================================== */
|
===================================================================== */
|
||||||
|
|
||||||
.event-zeitraum {
|
/* ---------------------------------------------------------------------
|
||||||
display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
|
DIE ALTEN BAUSTEINE SIND AM 03.10.2026 WEGGEFALLEN.
|
||||||
margin: 2px 0 10px;
|
|
||||||
font-size: .82rem;
|
|
||||||
}
|
|
||||||
.event-zeitraum__marke {
|
|
||||||
--f: var(--k-neutral);
|
|
||||||
display: inline-flex; align-items: center; gap: 6px;
|
|
||||||
padding: 3px 10px;
|
|
||||||
border: 1px solid color-mix(in srgb, var(--f) 34%, transparent);
|
|
||||||
border-radius: 999px;
|
|
||||||
background: color-mix(in srgb, var(--f) 12%, transparent);
|
|
||||||
color: color-mix(in srgb, var(--f) 82%, #fff);
|
|
||||||
font-weight: 600; letter-spacing: .01em;
|
|
||||||
font-variant-numeric: tabular-nums;
|
|
||||||
}
|
|
||||||
/* Der Punkt davor ist reine Zierde und darf deshalb NICHT vorgelesen
|
|
||||||
werden -- ein Screenreader saehe sonst ein Aufzaehlungszeichen mitten
|
|
||||||
im Satz. */
|
|
||||||
.event-zeitraum__marke::before {
|
|
||||||
content: ""; width: 7px; height: 7px; border-radius: 50%;
|
|
||||||
background: var(--f); flex: none;
|
|
||||||
}
|
|
||||||
.event-zeitraum[data-stand="laeuft"] .event-zeitraum__marke { --f: var(--k-gut); }
|
|
||||||
.event-zeitraum[data-stand="kommt"] .event-zeitraum__marke { --f: var(--k-mittel); }
|
|
||||||
.event-zeitraum[data-stand="vorbei"] .event-zeitraum__marke { --f: var(--k-neutral); }
|
|
||||||
.event-zeitraum__spanne {
|
|
||||||
color: var(--text-leise);
|
|
||||||
font-variant-numeric: tabular-nums;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ein vorbeigelaufenes Event bleibt lesbar, tritt aber zurueck. Kein
|
Hier standen `.event-zeitraum*` und `.event-block*` -- die
|
||||||
display:none -- was gelaufen ist, will man nachschlagen koennen.
|
Zeitraumzeile ueber der Karte und die zwei gleich aussehenden
|
||||||
Gedaempft wird nur die Flaeche, nicht die Schrift: Text unter 4.5:1
|
grauen Kaesten fuer Aufgaben und Regeln. Beide erzeugt bereich.js
|
||||||
waere nicht mehr lesbar, und "alt" ist kein Grund, jemanden
|
nicht mehr: Der Zeitraum steht jetzt auf der Buehne (einmal statt
|
||||||
auszuschliessen. */
|
dreimal), und aus den Kaesten sind Listen geworden, die man abhaken
|
||||||
.eintrag-karte[data-event="vorbei"] { opacity: .82; }
|
kann. Die neuen Regeln stehen weiter unten unter "AGENTUR-EVENTS:
|
||||||
|
DIE KARTE ALS AUSHANG".
|
||||||
|
|
||||||
.event-block {
|
SIE WURDEN ENTFERNT UND NICHT AUFGEHOBEN: Eine Regel, die auf nichts
|
||||||
margin: 10px 0 0;
|
mehr zeigt, sieht beim naechsten Lesen aus wie eine, die etwas tut
|
||||||
padding: 10px 12px;
|
-- und man sucht den Fehler dann an einer Stelle, an der nichts
|
||||||
border: 1px solid var(--rand);
|
passiert. Was sie aussagten, steht in der Begruendung der neuen
|
||||||
border-radius: var(--radius-klein);
|
Regeln; die Geschichte selbst steht in git.
|
||||||
background: rgba(255, 255, 255, .022);
|
|
||||||
}
|
|
||||||
.event-block__schild {
|
|
||||||
margin: 0 0 4px;
|
|
||||||
/* .74rem = 11.84 px, nicht .7rem. Die Schriftgroessen-Pruefung zieht
|
|
||||||
die Grenze bei 11.5 px, und sie hat recht: In Grossbuchstaben mit
|
|
||||||
Sperrung wirkt eine Schrift kleiner, als die Zahl sagt -- und das
|
|
||||||
hier ist die Beschriftung, an der man die Regeln vom Aufgabenteil
|
|
||||||
unterscheidet. */
|
|
||||||
font-size: .74rem; font-weight: 700;
|
|
||||||
letter-spacing: .09em; text-transform: uppercase;
|
|
||||||
color: var(--text-still);
|
|
||||||
}
|
|
||||||
.event-block__text {
|
|
||||||
margin: 0;
|
|
||||||
font-size: .87rem; line-height: 1.6; color: var(--text);
|
|
||||||
/* pre-line, nicht pre-wrap: Zeilenumbrueche bleiben (die Aufzaehlung
|
|
||||||
ist der Sinn dieser Felder), aber eine versehentlich eingefuegte
|
|
||||||
Einrueckung aus einer Chatnachricht reisst die Karte nicht auf. */
|
|
||||||
white-space: pre-line;
|
|
||||||
overflow-wrap: anywhere;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .feld-hinweis steht seit dem 07.09.2026 in aufgaben.css -- bei den
|
Ebenfalls weg: `.eintrag-karte[data-event="vorbei"] { opacity: .82 }`.
|
||||||
uebrigen Formularstilen. Grund: Die Dashboard-Seite braucht ihn jetzt
|
Ein abgelaufenes Event war damit kaum von einem laufenden zu
|
||||||
auch (Creator anlegen), laedt aber diese Datei hier nicht. Ein
|
unterscheiden, und der Text wurde schlechter lesbar, ohne dass es
|
||||||
Formularbaustein, der in der Bereichsdatei liegt, ist nur so lange
|
etwas brachte. Jetzt tritt nur das BILD zurueck.
|
||||||
richtig, wie ihn keine zweite Seite braucht. */
|
--------------------------------------------------------------------- */
|
||||||
|
|
||||||
@media (max-width: 560px) {
|
|
||||||
/* Auf dem Handy untereinander: Marke und Spanne nebeneinander
|
|
||||||
ergaeben bei "vorbei seit 30.09.2026" einen Umbruch mitten im
|
|
||||||
Datum. */
|
|
||||||
.event-zeitraum { gap: 6px; }
|
|
||||||
.event-zeitraum__spanne { flex-basis: 100%; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* =====================================================================
|
/* =====================================================================
|
||||||
RÜCKMELDUNG: „fürs Team" oder „nur an DogFather" (10.09.2026)
|
RÜCKMELDUNG: „fürs Team" oder „nur an DogFather" (10.09.2026)
|
||||||
@@ -2195,3 +2138,880 @@ body[data-ton] .kopf-zeile::before {
|
|||||||
display: grid; gap: 10px;
|
display: grid; gap: 10px;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
AGENTUR-EVENTS: DIE KARTE ALS AUSHANG (03.10.2026)
|
||||||
|
|
||||||
|
Filipe, mit einem Bildschirmfoto des Oktober-Events: "ich will das
|
||||||
|
viel geiler viel perfekter. und auch wenn man die eintraegt und so
|
||||||
|
soll viel mehr perfektioniert und uebersichtlicher sein. mach was
|
||||||
|
hoch profissionelles bitte."
|
||||||
|
|
||||||
|
WAS VORHER GEMESSEN WURDE (1280 px, eine einzige Karte):
|
||||||
|
|
||||||
|
Kartenhoehe 1196 px -- Fenster ist 900 px
|
||||||
|
davon Banner 638 px -- 53 %, ohne einen Buchstaben
|
||||||
|
Titel steht bei 1482 px -- zweimal scrollen bis zum Namen
|
||||||
|
Titelgroesse 15,36 px -- 1,4 px mehr als der Fliesstext
|
||||||
|
Etikett 10,88 px -- unter der eigenen Grenze (11,5)
|
||||||
|
Datum 3 x -- in drei Zeilen untereinander
|
||||||
|
Knoepfe 4 x gleich -- "loeschen" wie "zur Aufgabe"
|
||||||
|
|
||||||
|
WAS SICH DARAUS ERGIBT: Das Bild bleibt gross, traegt aber den Titel.
|
||||||
|
Der Zeitraum steht einmal, mit der Antwort davor ("noch 13 Tage").
|
||||||
|
Aufgaben werden zu einer Liste, die man abhaken kann. Und "loeschen"
|
||||||
|
sieht nicht mehr aus wie "zur Aufgabe".
|
||||||
|
|
||||||
|
AUGENSCHONEND BLEIBT ES: keine neuen Signalfarben, kein Leuchten,
|
||||||
|
kein Blinken. Die Toene kommen aus der vorhandenen Palette
|
||||||
|
(--k-gut / --k-mittel / --k-neutral / --akzent), die Bewegung ist
|
||||||
|
dieselbe wie ueberall (--tempo) und faellt bei
|
||||||
|
prefers-reduced-motion ganz weg.
|
||||||
|
===================================================================== */
|
||||||
|
|
||||||
|
/* Eine Eventkarte traegt ihre eigene Polsterung: Die Buehne geht bis an
|
||||||
|
den Rand, der Rest nicht. Deshalb hier null -- die Abstaende setzen
|
||||||
|
die Teile selbst. */
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] {
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
/* Der farbige Streifen links kam von der Dringlichkeit und sagte bei
|
||||||
|
einem Event nichts: Jedes Event stand auf "mittel", also hatte
|
||||||
|
jedes denselben blauen Strich. Den Zustand traegt jetzt die Buehne,
|
||||||
|
und zwar in der Farbe, die ihn bedeutet. */
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------
|
||||||
|
DIE BUEHNE
|
||||||
|
--------------------------------------------------------------------- */
|
||||||
|
.ev-buehne {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
/* DIE HOEHE IST GEDECKELT, UND ZWAR ZWEIFACH.
|
||||||
|
|
||||||
|
aspect-ratio haelt die Form bei schmalen Karten (sonst waere die
|
||||||
|
Buehne auf dem Handy ein Briefschlitz), max-height faengt die
|
||||||
|
breiten ab: Bei 1230 px Kartenbreite waeren 2.6/1 immer noch
|
||||||
|
473 px -- mehr als ein Drittel eines Laptopbildschirms fuer ein
|
||||||
|
Bild, auf dem der Titel steht.
|
||||||
|
|
||||||
|
Gemessen: 638 px vorher, 300 px jetzt. */
|
||||||
|
/* `width: 100%` IST PFLICHT, NICHT ZIERDE (gemessen 03.10.2026).
|
||||||
|
|
||||||
|
Ohne sie schrumpft `aspect-ratio` zusammen mit `max-height` auch
|
||||||
|
die BREITE: In der ersten Fassung war die Buehne 780 px breit in
|
||||||
|
einer 1230 px breiten Karte -- das Banner stand als Kachel links,
|
||||||
|
rechts daneben lag ein Drittel Leere. Das sah aus wie ein
|
||||||
|
Ladefehler und war eine Rechenregel: 300 px Hoehe x 2.6 = 780 px.
|
||||||
|
|
||||||
|
Mit fester Breite berechnet aspect-ratio nur noch die Hoehe
|
||||||
|
(1230 / 2.6 = 473 px), und max-height deckelt sie auf 300. */
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 2.6 / 1;
|
||||||
|
min-height: 170px;
|
||||||
|
max-height: 300px;
|
||||||
|
/* DIE SEITLICHE POLSTERUNG HAT EINEN NAMEN, weil der Schriftgrund
|
||||||
|
darunter sie braucht: Er muss genau bis an den Rand der Buehne
|
||||||
|
reichen und keinen Schritt weiter. Mit einer zweiten festen Zahl
|
||||||
|
ging das schief -- auf dem Handy betraegt die Polsterung 14 px,
|
||||||
|
der Grund rechnete aber weiter mit 20, und die Karte war 6 px
|
||||||
|
breiter als ihr Fenster (gemessen 03.10.2026, scrollWidth gegen
|
||||||
|
clientWidth).
|
||||||
|
Gefunden hat das die Pruefung, nicht das Auge: `overflow: hidden`
|
||||||
|
an der Karte hat den Ueberhang unsichtbar gemacht. Und mein erster
|
||||||
|
Suchlauf nach dem Verursacher kam leer zurueck -- ein ::before ist
|
||||||
|
kein Element, `querySelectorAll("*")` findet es nicht. */
|
||||||
|
--ev-rand: 20px;
|
||||||
|
padding: 44px var(--ev-rand) 16px;
|
||||||
|
background:
|
||||||
|
radial-gradient(120% 140% at 18% 0%,
|
||||||
|
color-mix(in srgb, var(--violett, #8a76ff) 26%, transparent), transparent 62%),
|
||||||
|
linear-gradient(160deg,
|
||||||
|
color-mix(in srgb, var(--akzent, #3fbdf5) 16%, transparent),
|
||||||
|
rgba(255, 255, 255, .02));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OHNE BILD WIRD DIE BUEHNE FLACHER. Ein Farbverlauf braucht keine
|
||||||
|
300 px, um zu wirken -- und eine halbleere Flaeche ueber drei Zeilen
|
||||||
|
Text sieht aus, als fehle etwas. */
|
||||||
|
.ev-buehne:not([data-mitbild="ja"]) {
|
||||||
|
aspect-ratio: auto;
|
||||||
|
min-height: 0;
|
||||||
|
padding-top: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ev-buehne__bild {
|
||||||
|
position: absolute; inset: 0;
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
/* NICHT MITTIG, SONDERN ETWAS HOEHER: Auf einem Event-Banner steht
|
||||||
|
die Aussage meistens im oberen Drittel ("Schaffst du es, ab HEUTE
|
||||||
|
bis zum 16.10.2026"), waehrend unten die Preise stehen. Wird
|
||||||
|
beschnitten, soll die Aussage uebrig bleiben. */
|
||||||
|
object-position: center 38%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DER SCHLEIER MACHT DIE SCHRIFT LESBAR, UND ZWAR IMMER.
|
||||||
|
|
||||||
|
Welches Bild jemand spaeter hochlaedt, weiss heute niemand -- ein
|
||||||
|
helles Banner ergaebe ohne ihn helle Schrift auf Hell. Deshalb kein
|
||||||
|
"nur bei hellen Bildern": Der Verlauf liegt grundsaetzlich darunter.
|
||||||
|
|
||||||
|
Nach oben laeuft er aus, damit das Bild oben unberuehrt bleibt; das
|
||||||
|
ist die Haelfte, die man sehen will. */
|
||||||
|
.ev-buehne__schleier {
|
||||||
|
position: absolute; inset: 0;
|
||||||
|
/* DIE KURVE IST NACHGEMESSEN, NICHT GESCHAETZT (03.10.2026).
|
||||||
|
|
||||||
|
Die erste Fassung lief schon bei 26 % der Hoehe auf .82 Deckung --
|
||||||
|
damit war von einem Banner praktisch nichts mehr uebrig, und genau
|
||||||
|
das Bild, das Filipe hochlaedt, war weg. Jetzt ist der Schleier
|
||||||
|
dort stark, wo die Schrift steht (unterste 30 %), und laeuft
|
||||||
|
darueber schnell aus: Ab der Haelfte sieht man das Banner fast
|
||||||
|
unberuehrt.
|
||||||
|
|
||||||
|
DIE UNTERSTE STUFE BLEIBT KRAEFTIG. Sie ist es, die den Titel auch
|
||||||
|
auf einem weissen Banner lesbar haelt -- und was jemand spaeter
|
||||||
|
hochlaedt, weiss heute niemand. Nachgemessen wird das Ergebnis am
|
||||||
|
Bildpunkt (siehe pruef-eventkarte.mjs), nicht an dieser Zahl. */
|
||||||
|
background: linear-gradient(to top,
|
||||||
|
rgba(5, 8, 14, .92) 0%,
|
||||||
|
rgba(5, 8, 14, .78) 18%,
|
||||||
|
rgba(5, 8, 14, .46) 34%,
|
||||||
|
rgba(5, 8, 14, .16) 52%,
|
||||||
|
rgba(5, 8, 14, .02) 74%,
|
||||||
|
transparent 100%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
/* Ohne Bild gibt es nichts abzudunkeln -- der Verlauf wuerde dann nur
|
||||||
|
den eigenen Farbverlauf zumatschen. */
|
||||||
|
.ev-buehne:not([data-mitbild="ja"]) .ev-buehne__schleier { display: none; }
|
||||||
|
|
||||||
|
/* ==== DIE SCHRIFT BRAUCHT IHREN EIGENEN GRUND (03.10.2026) ==========
|
||||||
|
|
||||||
|
NACHGEMESSEN, UND ZWAR AM HAERTEFALL: Mit einem fast weissen Banner
|
||||||
|
(250,248,252) stand "November Challenge" in heller Schrift auf
|
||||||
|
hellgrauem Grund -- unlesbar. Der Schleier allein reicht dafuer
|
||||||
|
nicht: Er ist ein Verlauf ueber die ganze Buehne und muesste, um
|
||||||
|
auch Weiss zu decken, so kraeftig sein, dass von einem dunklen
|
||||||
|
Banner nichts uebrig bliebe. Ein Wert, der fuer beide Faelle passt,
|
||||||
|
existiert nicht.
|
||||||
|
|
||||||
|
ALSO ZWEI EBENEN STATT EINER:
|
||||||
|
der Schleier -- sanft, fuer das Gesamtbild
|
||||||
|
dieser Grund -- kraeftig, aber nur hinter der Schrift
|
||||||
|
|
||||||
|
Er reicht 34 px ueber den Text hinaus und laeuft nach oben aus,
|
||||||
|
damit keine sichtbare Kante entsteht. Die Deckung unten (.93) ist
|
||||||
|
nicht geschaetzt: Sie ist der Wert, bei dem der Titel auch auf
|
||||||
|
reinem Weiss ueber 4,5:1 kommt -- gemessen am Bildpunkt in
|
||||||
|
pruef-eventkarte.mjs, nicht gerechnet.
|
||||||
|
|
||||||
|
WARUM NICHT EINFACH EIN KASTEN: Eine sichtbare Flaeche unter dem
|
||||||
|
Titel saehe aus wie ein Balken, der ueber dem Bild klebt. Der
|
||||||
|
Verlauf gehoert zur Buehne und faellt nicht auf -- bis man ihn
|
||||||
|
braucht. */
|
||||||
|
/* ---- "Banner ganz" ---------------------------------------------------
|
||||||
|
Oben rechts, klein, und nur dort, wo es ein Bild gibt. Er liegt UEBER
|
||||||
|
dem Schleier (der Schleier hat `pointer-events: none`, trotzdem
|
||||||
|
braucht der Knopf seine eigene Ebene) und bringt seinen eigenen
|
||||||
|
dunklen Grund mit -- auf einem hellen Banner waere er sonst
|
||||||
|
unsichtbar, genau wie es dem Titel erging. */
|
||||||
|
.ev-buehne__ganz {
|
||||||
|
position: absolute; top: 12px; right: 12px;
|
||||||
|
display: inline-flex; align-items: center; gap: 7px;
|
||||||
|
/* 34 px hoch mit 10 px Polsterung: Auf dem Handy wird daraus unten
|
||||||
|
ein 44-px-Ziel. */
|
||||||
|
padding: 7px 11px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, .16);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(8, 11, 18, .72);
|
||||||
|
backdrop-filter: blur(7px);
|
||||||
|
color: #dce7f3;
|
||||||
|
font-size: .74rem; font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: background var(--tempo, .22s), border-color var(--tempo, .22s);
|
||||||
|
}
|
||||||
|
.ev-buehne__ganz:hover {
|
||||||
|
background: rgba(8, 11, 18, .9);
|
||||||
|
border-color: rgba(255, 255, 255, .3);
|
||||||
|
}
|
||||||
|
.ev-buehne__ganz:focus-visible {
|
||||||
|
outline: 2px solid var(--akzent, #3fbdf5);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
/* Die Lupe ist gezeichnet, kein Schriftzeichen: Ein Symbol aus der
|
||||||
|
Schrift faellt auf manchen Systemen aus oder kommt als Kaestchen. */
|
||||||
|
.ev-buehne__ganz-zeichen {
|
||||||
|
flex: none; position: relative;
|
||||||
|
width: 13px; height: 13px;
|
||||||
|
border: 1.5px solid currentColor;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.ev-buehne__ganz-zeichen::before,
|
||||||
|
.ev-buehne__ganz-zeichen::after {
|
||||||
|
content: ""; position: absolute;
|
||||||
|
background: currentColor;
|
||||||
|
}
|
||||||
|
.ev-buehne__ganz-zeichen::before { left: 2.5px; top: 5px; width: 6px; height: 1.4px; }
|
||||||
|
.ev-buehne__ganz-zeichen::after { left: 4.8px; top: 2.7px; width: 1.4px; height: 6px; }
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.ev-buehne__ganz { transition: none; }
|
||||||
|
}
|
||||||
|
@media (max-width: 560px) {
|
||||||
|
.ev-buehne__ganz { top: 9px; right: 9px; padding: 9px 12px; }
|
||||||
|
/* Auf schmalen Schirmen nur die Lupe -- "Banner ganz" neben einem
|
||||||
|
Titel, der ohnehin umbricht, kostet eine Zeile. Die Beschriftung
|
||||||
|
bleibt fuer Vorleseprogramme erhalten (aria-label), sie wird nur
|
||||||
|
nicht gezeigt. */
|
||||||
|
.ev-buehne__ganz-wort {
|
||||||
|
position: absolute; width: 1px; height: 1px;
|
||||||
|
overflow: hidden; clip-path: inset(50%); white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ev-buehne__inhalt { position: relative; }
|
||||||
|
.ev-buehne[data-mitbild="ja"] .ev-buehne__inhalt::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: calc(-1 * var(--ev-rand)); right: calc(-1 * var(--ev-rand));
|
||||||
|
bottom: -16px; top: -34px;
|
||||||
|
background: linear-gradient(to top,
|
||||||
|
rgba(4, 7, 12, .93) 0%,
|
||||||
|
rgba(4, 7, 12, .90) 52%,
|
||||||
|
rgba(4, 7, 12, .62) 82%,
|
||||||
|
rgba(4, 7, 12, 0) 100%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
/* Die Kinder muessen UEBER diesen Grund -- ein absolut gesetztes
|
||||||
|
::before liegt sonst ueber allem, was selbst nicht positioniert ist,
|
||||||
|
und der Titel waere verschwunden. Genau so ist es beim ersten
|
||||||
|
Versuch passiert. */
|
||||||
|
.ev-buehne__kopf, .ev-zeit, .ev-zeitbalken { position: relative; }
|
||||||
|
|
||||||
|
/* ---- Titelzeile auf der Buehne -------------------------------------- */
|
||||||
|
.ev-buehne__kopf { align-items: center; gap: 8px 10px; }
|
||||||
|
|
||||||
|
/* DER TITEL IST DER TITEL (gemessen: vorher 15,36 px, also 1,4 px mehr
|
||||||
|
als der Text darunter -- das liest niemand als Ueberschrift).
|
||||||
|
|
||||||
|
clamp statt fester Zahl: Eine feste Groesse ist eine Rechnung von
|
||||||
|
gestern, sobald die Karte breiter oder schmaler wird. Hier skaliert
|
||||||
|
sie mit der Breite und bleibt zwischen 1,15 rem (18,4 px) und
|
||||||
|
1,55 rem (24,8 px). */
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .eintrag-titel {
|
||||||
|
flex: 1 1 100%;
|
||||||
|
font-size: clamp(1.15rem, 2.4vw, 1.55rem);
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.22;
|
||||||
|
letter-spacing: -.01em;
|
||||||
|
color: #f2f6fb;
|
||||||
|
/* Der Schatten ist keine Zierde: Er haelt den Titel auch dann
|
||||||
|
lesbar, wenn genau an dieser Stelle ein heller Fleck im Banner
|
||||||
|
liegt -- und das sieht man einem Bild vorher nicht an. */
|
||||||
|
text-shadow: 0 2px 10px rgba(0, 0, 0, .75);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DAS ETIKETT: 10,88 px waren unter der projekteigenen Grenze von
|
||||||
|
11,5 px -- angehoben wurde es bisher nur auf dem Handy. Hier gilt
|
||||||
|
dieselbe Groesse auf jedem Geraet; eine Grenze, die nur bei schmalen
|
||||||
|
Fenstern gilt, ist keine Grenze. */
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .marke-art {
|
||||||
|
font-size: .75rem;
|
||||||
|
padding: 2px 10px;
|
||||||
|
background: rgba(10, 14, 22, .62);
|
||||||
|
border: 1px solid rgba(255, 255, 255, .14);
|
||||||
|
backdrop-filter: blur(6px);
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Die Zeitzeile -------------------------------------------------- */
|
||||||
|
.ev-zeit {
|
||||||
|
display: flex; align-items: center; flex-wrap: wrap;
|
||||||
|
gap: 6px 10px;
|
||||||
|
margin: 10px 0 0;
|
||||||
|
font-size: .84rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "noch 13 Tage" -- die Antwort, nicht der Beleg. Deshalb die kraeftige
|
||||||
|
Marke, waehrend das Datum daneben leise bleibt. */
|
||||||
|
.ev-noch {
|
||||||
|
--f: var(--k-neutral, #8e9cb0);
|
||||||
|
display: inline-flex; align-items: center; gap: 7px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border: 1px solid color-mix(in srgb, var(--f) 40%, transparent);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: color-mix(in srgb, var(--f) 16%, rgba(8, 11, 18, .72));
|
||||||
|
color: color-mix(in srgb, var(--f) 72%, #ffffff);
|
||||||
|
font-weight: 650;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.ev-noch::before {
|
||||||
|
content: ""; width: 7px; height: 7px; border-radius: 50%;
|
||||||
|
background: var(--f); flex: none;
|
||||||
|
}
|
||||||
|
.ev-noch[data-stand="laeuft"] { --f: var(--k-gut, #5fc99a); }
|
||||||
|
.ev-noch[data-stand="kommt"] { --f: var(--k-mittel, #e8b877); }
|
||||||
|
.ev-noch[data-stand="vorbei"] { --f: var(--k-neutral, #8e9cb0); }
|
||||||
|
/* DIE LETZTEN TAGE SIND NICHT ROT.
|
||||||
|
|
||||||
|
Signalrot waere hier falsch: Ein auslaufendes Event ist kein Fehler,
|
||||||
|
sondern der Normalfall -- jedes endet. Es wird nur waermer und
|
||||||
|
kraeftiger, damit man es im Vorbeischauen sieht, ohne erschreckt zu
|
||||||
|
werden. */
|
||||||
|
.ev-noch[data-dringend="ja"] {
|
||||||
|
--f: var(--k-mittel, #e8b877);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ev-spanne {
|
||||||
|
color: #c3d2e2;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
text-shadow: 0 1px 6px rgba(0, 0, 0, .7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Der Zeitbalken -------------------------------------------------- */
|
||||||
|
.ev-zeitbalken {
|
||||||
|
position: relative;
|
||||||
|
height: 4px;
|
||||||
|
margin-top: 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(255, 255, 255, .14);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.ev-zeitbalken__fuellung {
|
||||||
|
height: 100%;
|
||||||
|
border-radius: inherit;
|
||||||
|
background: linear-gradient(90deg,
|
||||||
|
color-mix(in srgb, var(--akzent, #3fbdf5) 70%, transparent),
|
||||||
|
color-mix(in srgb, var(--violett, #8a76ff) 80%, transparent));
|
||||||
|
transition: width var(--tempo, .22s) ease;
|
||||||
|
}
|
||||||
|
.ev-buehne[data-stand="vorbei"] .ev-zeitbalken__fuellung {
|
||||||
|
background: rgba(255, 255, 255, .26);
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.ev-zeitbalken__fuellung { transition: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------
|
||||||
|
DER KOERPER: Text, Aufgaben, Regeln
|
||||||
|
--------------------------------------------------------------------- */
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .eintrag-text {
|
||||||
|
margin: 14px 18px 0;
|
||||||
|
color: var(--text-leise);
|
||||||
|
/* EINE ZEILE HAT EINE LESBARE LAENGE. Auf 1280 px lief der
|
||||||
|
Erklaertext ueber 1120 px -- rund 150 Zeichen je Zeile. Das Auge
|
||||||
|
findet den Anfang der naechsten Zeile dann nicht mehr zuverlaessig;
|
||||||
|
die gaengige Empfehlung liegt bei 45 bis 75 Zeichen. 72ch ist das
|
||||||
|
obere Ende davon und passt zu dieser Schriftgroesse. */
|
||||||
|
max-width: 72ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ZWEI SPALTEN, WENN PLATZ IST -- GEMESSEN, NICHT GERECHNET.
|
||||||
|
|
||||||
|
`auto-fit` mit einer Mindestbreite bricht genau dann um, wenn eine
|
||||||
|
Spalte unter 300 px fiele. Das ist der Unterschied zu einer
|
||||||
|
Fensterbreite in einer Zahl: Kommt irgendwann ein dritter Block
|
||||||
|
dazu oder wird die Karte in einer schmaleren Spalte gezeigt, stimmt
|
||||||
|
es weiterhin, ohne dass jemand die Zahl nachzieht.
|
||||||
|
|
||||||
|
(Die Lehre dazu steht im Projektgedaechtnis unter dem 06.09.2026:
|
||||||
|
eine feste Schwelle, die beim Hinzufuegen des naechsten Elements
|
||||||
|
nicht nachgezogen wurde, hat zwoelf Seiten lang den falschen Knopf
|
||||||
|
getroffen.) */
|
||||||
|
.ev-bloecke {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 14px;
|
||||||
|
align-items: start;
|
||||||
|
margin: 14px 18px 0;
|
||||||
|
}
|
||||||
|
.ev-bloecke .ev-block { margin: 0; }
|
||||||
|
|
||||||
|
.ev-block {
|
||||||
|
margin: 14px 18px 0;
|
||||||
|
padding: 13px 15px;
|
||||||
|
border: 1px solid var(--rand);
|
||||||
|
border-radius: var(--radius-klein);
|
||||||
|
background: rgba(255, 255, 255, .022);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AUFGABEN UND REGELN SEHEN NICHT MEHR GLEICH AUS.
|
||||||
|
|
||||||
|
Vorher waren es zwei identische graue Kaesten untereinander -- "was
|
||||||
|
ich tun soll" und "was dabei gilt" wirkten damit gleich wichtig.
|
||||||
|
Die Aufgaben sind das, weswegen jemand hier ist; sie bekommen einen
|
||||||
|
Rand in der Hausfarbe. Die Regeln treten zurueck, ohne zu
|
||||||
|
verschwinden. */
|
||||||
|
.ev-block--aufgaben {
|
||||||
|
border-color: color-mix(in srgb, var(--akzent, #3fbdf5) 24%, var(--rand));
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg,
|
||||||
|
color-mix(in srgb, var(--akzent, #3fbdf5) 7%, transparent),
|
||||||
|
transparent 58%),
|
||||||
|
rgba(255, 255, 255, .022);
|
||||||
|
}
|
||||||
|
.ev-block--regeln { background: rgba(255, 255, 255, .012); }
|
||||||
|
/* Alles geschafft: ein ruhiger gruener Rand, kein Konfetti. */
|
||||||
|
.ev-block--aufgaben[data-fertig="ja"] {
|
||||||
|
border-color: color-mix(in srgb, var(--k-gut, #5fc99a) 34%, var(--rand));
|
||||||
|
}
|
||||||
|
|
||||||
|
.ev-block__kopf {
|
||||||
|
display: flex; align-items: baseline;
|
||||||
|
gap: 10px; margin-bottom: 9px;
|
||||||
|
}
|
||||||
|
/* DIE ZAHL GEHOERT ZUR UEBERSCHRIFT, NICHT AN DEN RAND.
|
||||||
|
|
||||||
|
Mit `justify-content: space-between` stand "0 von 3" auf einer
|
||||||
|
1160 px breiten Karte rund einen Meter von dem Wort entfernt, auf
|
||||||
|
das es sich bezieht -- man liest es dann als zwei verschiedene
|
||||||
|
Angaben. Jetzt steht es direkt daneben, abgesetzt durch einen
|
||||||
|
Trennpunkt statt durch Leere. */
|
||||||
|
.ev-zaehler::before {
|
||||||
|
content: "·";
|
||||||
|
margin-right: 8px;
|
||||||
|
color: var(--text-still);
|
||||||
|
opacity: .7;
|
||||||
|
}
|
||||||
|
.ev-block__schild {
|
||||||
|
margin: 0;
|
||||||
|
/* .75rem = 12 px. Nicht kleiner: In Grossbuchstaben mit Sperrung
|
||||||
|
wirkt eine Schrift kleiner, als die Zahl sagt -- die Begruendung
|
||||||
|
steht so schon beim alten .event-block__schild. */
|
||||||
|
font-size: .75rem; font-weight: 700;
|
||||||
|
letter-spacing: .09em; text-transform: uppercase;
|
||||||
|
color: var(--text-leise);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "1 von 3" -- die Zahl gehoert neben die Ueberschrift und nicht
|
||||||
|
darunter: Sie ist die Zusammenfassung der Liste, nicht ihr erster
|
||||||
|
Eintrag. tabular-nums, damit sie beim Hochzaehlen nicht springt. */
|
||||||
|
.ev-zaehler {
|
||||||
|
font-size: .78rem; font-weight: 650;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
color: var(--text-still);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.ev-zaehler[data-voll="ja"] { color: var(--k-gut, #5fc99a); }
|
||||||
|
|
||||||
|
/* ---- Die Liste ------------------------------------------------------- */
|
||||||
|
.ev-liste {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0; padding: 0;
|
||||||
|
display: flex; flex-direction: column; gap: 2px;
|
||||||
|
}
|
||||||
|
.ev-punkt { margin: 0; }
|
||||||
|
|
||||||
|
/* EIN VORBEIGELAUFENES EVENT HAT KEINE KNOEPFE -- und ohne den Knopf
|
||||||
|
fehlte der Zeile seine Polsterung: Beim ersten Lauf klebte
|
||||||
|
"20 Live-Stunden" am linken Rand des Kastens, waehrend dieselbe
|
||||||
|
Liste eine Karte darueber ordentlich eingerueckt stand. Zwei Listen
|
||||||
|
nebeneinander, die verschieden aussehen, liest man als Fehler.
|
||||||
|
|
||||||
|
Deshalb bekommt die reine Anzeigezeile dasselbe Raster wie der
|
||||||
|
Knopf -- nur eben ohne Hintergrund und ohne Zeiger. */
|
||||||
|
.ev-punkt:not(:has(.ev-punkt__knopf)):not(.ev-punkt--regel) {
|
||||||
|
display: flex; align-items: flex-start; gap: 10px;
|
||||||
|
padding: 9px 10px;
|
||||||
|
font-size: .9rem; line-height: 1.45;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DER GANZE PUNKT IST DER KNOPF, nicht nur ein Kaestchen daneben.
|
||||||
|
|
||||||
|
Ein 16-px-Kaestchen ist auf dem Handy ein Ziel von 16 x 16 px -- die
|
||||||
|
gaengige Mindestgroesse liegt bei 44 x 44. Wer danebentippt, denkt,
|
||||||
|
es sei kaputt. Die ganze Zeile zu nehmen loest beides: Das Ziel ist
|
||||||
|
so breit wie die Karte, und man muss nicht zielen. */
|
||||||
|
.ev-punkt__knopf {
|
||||||
|
display: flex; align-items: flex-start; gap: 10px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 9px 10px;
|
||||||
|
margin: 0;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text);
|
||||||
|
font: inherit;
|
||||||
|
font-size: .9rem;
|
||||||
|
line-height: 1.45;
|
||||||
|
text-align: left;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background var(--tempo, .22s), border-color var(--tempo, .22s);
|
||||||
|
}
|
||||||
|
.ev-punkt__knopf:hover {
|
||||||
|
background: rgba(255, 255, 255, .04);
|
||||||
|
border-color: var(--rand);
|
||||||
|
}
|
||||||
|
.ev-punkt__knopf:focus-visible {
|
||||||
|
outline: 2px solid var(--akzent, #3fbdf5);
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
.ev-punkt__knopf[disabled] { opacity: .6; cursor: progress; }
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.ev-punkt__knopf { transition: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Das Kaestchen. Leer ein Rahmen, voll ein Haken -- und der Haken ist
|
||||||
|
gezeichnet (clip-path), kein Schriftzeichen: Ein Haken aus der
|
||||||
|
Schrift sieht auf jedem System anders aus und faellt auf manchen
|
||||||
|
ganz aus. */
|
||||||
|
.ev-punkt__kaestchen {
|
||||||
|
flex: none;
|
||||||
|
width: 19px; height: 19px;
|
||||||
|
margin-top: 1px;
|
||||||
|
/* 62 % waren im Bildschirmfoto kaum auszumachen -- ein Kaestchen,
|
||||||
|
das man suchen muss, laedt nicht zum Anfassen ein. Auf 92 %
|
||||||
|
angehoben und mit etwas mehr Fuellung dahinter. */
|
||||||
|
border: 1.5px solid color-mix(in srgb, var(--text-still) 92%, transparent);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: rgba(255, 255, 255, .055);
|
||||||
|
position: relative;
|
||||||
|
transition: background var(--tempo, .22s), border-color var(--tempo, .22s);
|
||||||
|
}
|
||||||
|
.ev-punkt__kaestchen::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute; left: 4px; top: 4px;
|
||||||
|
width: 9px; height: 5px;
|
||||||
|
border-left: 2px solid #07101a;
|
||||||
|
border-bottom: 2px solid #07101a;
|
||||||
|
transform: rotate(-45deg) scale(.6);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity var(--tempo, .22s), transform var(--tempo, .22s);
|
||||||
|
}
|
||||||
|
.ev-punkt[data-abgehakt="ja"] .ev-punkt__kaestchen {
|
||||||
|
background: var(--k-gut, #5fc99a);
|
||||||
|
border-color: var(--k-gut, #5fc99a);
|
||||||
|
}
|
||||||
|
.ev-punkt[data-abgehakt="ja"] .ev-punkt__kaestchen::after {
|
||||||
|
opacity: 1; transform: rotate(-45deg) scale(1);
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.ev-punkt__kaestchen, .ev-punkt__kaestchen::after { transition: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ABGEHAKT WIRD NICHT DURCHGESTRICHEN.
|
||||||
|
|
||||||
|
Durchgestrichener Text ist schlecht lesbar, und man will ihn
|
||||||
|
weiterhin lesen koennen -- "22 Live-Stunden" bleibt die Bedingung,
|
||||||
|
auch wenn sie erfuellt ist. Der Haken sagt es bereits; die Schrift
|
||||||
|
tritt nur leicht zurueck. */
|
||||||
|
.ev-punkt[data-abgehakt="ja"] .ev-punkt__text { color: var(--text-leise); }
|
||||||
|
.ev-punkt__text { flex: 1 1 auto; overflow-wrap: anywhere; }
|
||||||
|
|
||||||
|
/* Die Regelliste: dasselbe Raster, aber ein Strich statt eines
|
||||||
|
Kaestchens -- man sieht auf einen Blick, dass hier nichts zu tun
|
||||||
|
ist. */
|
||||||
|
.ev-punkt--regel {
|
||||||
|
display: flex; align-items: flex-start; gap: 10px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
font-size: .87rem; line-height: 1.5;
|
||||||
|
color: var(--text-leise);
|
||||||
|
}
|
||||||
|
.ev-punkt__zeichen {
|
||||||
|
flex: none;
|
||||||
|
width: 19px; height: 19px;
|
||||||
|
margin-top: 1px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.ev-punkt__zeichen::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute; left: 3px; top: 9px;
|
||||||
|
width: 11px; height: 1.5px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: color-mix(in srgb, var(--text-still) 52%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Der Rueckfall, wenn der Server keine Punkteliste schickt. */
|
||||||
|
.ev-rohtext {
|
||||||
|
margin: 0;
|
||||||
|
font-size: .87rem; line-height: 1.6; color: var(--text);
|
||||||
|
white-space: pre-line;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Wer macht mit (nur fuer die Leitung) ---------------------------- */
|
||||||
|
.ev-mitmacher {
|
||||||
|
display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
|
||||||
|
margin-top: 11px; padding-top: 10px;
|
||||||
|
border-top: 1px solid var(--rand);
|
||||||
|
}
|
||||||
|
.ev-mitmacher__schild {
|
||||||
|
font-size: .7rem; font-weight: 700;
|
||||||
|
letter-spacing: .08em; text-transform: uppercase;
|
||||||
|
color: var(--text-still);
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
.ev-mitmacher__person {
|
||||||
|
padding: 2px 9px;
|
||||||
|
border: 1px solid var(--rand);
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(255, 255, 255, .03);
|
||||||
|
font-size: .76rem;
|
||||||
|
color: var(--text-leise);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
.ev-mitmacher__person[data-voll="ja"] {
|
||||||
|
border-color: color-mix(in srgb, var(--k-gut, #5fc99a) 40%, transparent);
|
||||||
|
color: color-mix(in srgb, var(--k-gut, #5fc99a) 80%, #ffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------
|
||||||
|
DER FUSS
|
||||||
|
--------------------------------------------------------------------- */
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .eintrag-fuss {
|
||||||
|
margin: 16px 0 0;
|
||||||
|
padding: 12px 18px 15px;
|
||||||
|
border-top: 1px solid var(--rand);
|
||||||
|
background: rgba(255, 255, 255, .012);
|
||||||
|
}
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .ampel {
|
||||||
|
margin: 0; padding: 11px 18px 14px;
|
||||||
|
border-top: 1px solid var(--rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LOESCHEN SIEHT NICHT MEHR AUS WIE "ZUR AUFGABE".
|
||||||
|
|
||||||
|
Gemessen waren es vier gleich grosse, gleich graue Pillen
|
||||||
|
nebeneinander -- darunter die eine, die man nicht rueckgaengig
|
||||||
|
machen kann. Sie rutscht jetzt mit einem Abstand nach rechts weg und
|
||||||
|
bekommt einen warmen Ton. KEIN Signalrot und keine Fuellung: Der
|
||||||
|
Knopf soll sich unterscheiden, nicht drohen; erst beim Ueberfahren
|
||||||
|
wird er deutlicher. */
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .schritt--gefahr {
|
||||||
|
margin-left: 10px;
|
||||||
|
color: color-mix(in srgb, var(--warn, #ff9aa2) 72%, var(--text-still));
|
||||||
|
border-color: color-mix(in srgb, var(--warn, #ff9aa2) 26%, transparent);
|
||||||
|
}
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .schritt--gefahr:hover {
|
||||||
|
color: var(--warn, #ff9aa2);
|
||||||
|
border-color: color-mix(in srgb, var(--warn, #ff9aa2) 52%, transparent);
|
||||||
|
background: color-mix(in srgb, var(--warn, #ff9aa2) 10%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------
|
||||||
|
EIN VORBEIGELAUFENES EVENT
|
||||||
|
--------------------------------------------------------------------- */
|
||||||
|
/* Die alte Regel dimmte die ganze Karte auf .82 -- damit war ein
|
||||||
|
abgelaufenes Event kaum von einem laufenden zu unterscheiden, und der
|
||||||
|
Text wurde schlechter lesbar, ohne dass es etwas brachte.
|
||||||
|
|
||||||
|
Jetzt tritt nur das BILD zurueck (entsaettigt und abgedunkelt). Der
|
||||||
|
Text behaelt seinen vollen Kontrast: "alt" ist kein Grund, jemanden
|
||||||
|
vom Lesen auszuschliessen. */
|
||||||
|
.eintrag-karte[data-eventkarte="ja"][data-event="vorbei"] { opacity: 1; }
|
||||||
|
.ev-buehne[data-stand="vorbei"] .ev-buehne__bild {
|
||||||
|
filter: saturate(.35) brightness(.62);
|
||||||
|
}
|
||||||
|
.ev-buehne[data-stand="vorbei"] { aspect-ratio: 3.6 / 1; max-height: 190px; }
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------
|
||||||
|
AUF DEM HANDY
|
||||||
|
--------------------------------------------------------------------- */
|
||||||
|
@media (max-width: 560px) {
|
||||||
|
.ev-buehne {
|
||||||
|
aspect-ratio: 1.9 / 1;
|
||||||
|
min-height: 150px; max-height: 230px;
|
||||||
|
--ev-rand: 14px;
|
||||||
|
padding: 38px var(--ev-rand) 13px;
|
||||||
|
}
|
||||||
|
.ev-buehne[data-stand="vorbei"] { aspect-ratio: 2.6 / 1; max-height: 160px; }
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .eintrag-text { margin: 12px 14px 0; }
|
||||||
|
.ev-bloecke { margin: 12px 14px 0; gap: 12px; }
|
||||||
|
.ev-block { margin: 12px 14px 0; padding: 12px 12px; }
|
||||||
|
.ev-bloecke .ev-block { margin: 0; }
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .eintrag-fuss { padding: 12px 14px 14px; }
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .ampel { padding: 11px 14px 13px; }
|
||||||
|
/* Das Beruehrziel: 9 px Polsterung plus 19 px Kaestchen ergaeben
|
||||||
|
37 px. Auf dem Handy wird daraus 44 -- dieselbe Zahl wie bei allen
|
||||||
|
anderen Knoepfen des Hauses. */
|
||||||
|
.ev-punkt__knopf { min-height: 44px; align-items: center; }
|
||||||
|
/* Der Loeschknopf steht auf dem Handy in einer eigenen Zeile; ein
|
||||||
|
Abstand nach links wuerde ihn dort nur einruecken. */
|
||||||
|
.eintrag-karte[data-eventkarte="ja"] .schritt--gefahr { margin-left: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hoher Kontrast: Die Zustandsfarben verschwinden dort, also muss die
|
||||||
|
Form sprechen. */
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
.ev-buehne__schleier { display: none; }
|
||||||
|
.ev-punkt__kaestchen { border: 2px solid CanvasText; }
|
||||||
|
.ev-punkt[data-abgehakt="ja"] .ev-punkt__kaestchen { background: Highlight; }
|
||||||
|
.ev-zeitbalken { border: 1px solid CanvasText; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DER ZEILEN-EDITOR UND DIE VORSCHAU (03.10.2026)
|
||||||
|
|
||||||
|
Die Begruendung, warum es ihn gibt, steht bei zeilenEditor() in
|
||||||
|
bereich.js: Ein leeres Textfeld zwingt den Menschen, die
|
||||||
|
Aufzaehlungszeichen selbst zu tippen -- und dann sehen drei Zeilen
|
||||||
|
auf drei Arten aus. Hier steht nur, wie er aussieht.
|
||||||
|
===================================================================== */
|
||||||
|
|
||||||
|
.zeileneditor {
|
||||||
|
display: flex; flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.zeileneditor__liste {
|
||||||
|
display: flex; flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.zeileneditor__zeile {
|
||||||
|
display: flex; align-items: center; gap: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Das Aufzaehlungszeichen steht VOR dem Feld und nicht darin: So sieht
|
||||||
|
man schon beim Tippen, dass es gesetzt wird -- und man kommt gar
|
||||||
|
nicht erst auf die Idee, selbst eines zu tippen. */
|
||||||
|
.zeileneditor__zeichen {
|
||||||
|
flex: none;
|
||||||
|
width: 16px; height: 16px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.zeileneditor__zeichen::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute; left: 4px; top: 6px;
|
||||||
|
width: 6px; height: 6px; border-radius: 50%;
|
||||||
|
background: color-mix(in srgb, var(--akzent, #3fbdf5) 58%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.zeileneditor__feld {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
/* Dieselben Masse wie alle Felder des Hauses (--feld-ziel usw. in
|
||||||
|
start.css) -- ein Eingabefeld, das sich von den anderen
|
||||||
|
unterscheidet, sieht nach einem Fremdkoerper aus. */
|
||||||
|
min-height: 40px;
|
||||||
|
padding: 8px 11px;
|
||||||
|
border: 1px solid var(--rand);
|
||||||
|
border-radius: 9px;
|
||||||
|
background: rgba(255, 255, 255, .035);
|
||||||
|
color: var(--text);
|
||||||
|
font: inherit;
|
||||||
|
font-size: .9rem;
|
||||||
|
}
|
||||||
|
.zeileneditor__feld:focus-visible {
|
||||||
|
outline: 2px solid var(--akzent, #3fbdf5);
|
||||||
|
outline-offset: 1px;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Der Wegnehmen-Knopf: ein Kreuz, gezeichnet statt getippt -- ein
|
||||||
|
Mal-Zeichen aus der Schrift sitzt je nach System anders. */
|
||||||
|
.zeileneditor__weg {
|
||||||
|
flex: none;
|
||||||
|
width: 34px; height: 34px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-still);
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
transition: color var(--tempo, .22s), background var(--tempo, .22s),
|
||||||
|
border-color var(--tempo, .22s);
|
||||||
|
}
|
||||||
|
.zeileneditor__weg::before,
|
||||||
|
.zeileneditor__weg::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute; left: 10px; top: 16px;
|
||||||
|
width: 12px; height: 1.6px; border-radius: 2px;
|
||||||
|
background: currentColor;
|
||||||
|
}
|
||||||
|
.zeileneditor__weg::before { transform: rotate(45deg); }
|
||||||
|
.zeileneditor__weg::after { transform: rotate(-45deg); }
|
||||||
|
.zeileneditor__weg:hover {
|
||||||
|
color: var(--warn, #ff9aa2);
|
||||||
|
background: color-mix(in srgb, var(--warn, #ff9aa2) 9%, transparent);
|
||||||
|
border-color: color-mix(in srgb, var(--warn, #ff9aa2) 24%, transparent);
|
||||||
|
}
|
||||||
|
.zeileneditor__weg:focus-visible {
|
||||||
|
outline: 2px solid var(--akzent, #3fbdf5);
|
||||||
|
outline-offset: 1px;
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.zeileneditor__weg { transition: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.zeileneditor__fuss {
|
||||||
|
display: flex; align-items: center; gap: 10px;
|
||||||
|
margin-top: 7px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.zeileneditor__mehr {
|
||||||
|
padding: 7px 14px;
|
||||||
|
min-height: 36px;
|
||||||
|
border: 1px dashed color-mix(in srgb, var(--akzent, #3fbdf5) 34%, var(--rand));
|
||||||
|
border-radius: 9px;
|
||||||
|
background: transparent;
|
||||||
|
color: color-mix(in srgb, var(--akzent, #3fbdf5) 72%, #cfe0f0);
|
||||||
|
font: inherit; font-size: .84rem; font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background var(--tempo, .22s), border-color var(--tempo, .22s);
|
||||||
|
}
|
||||||
|
.zeileneditor__mehr:hover {
|
||||||
|
background: color-mix(in srgb, var(--akzent, #3fbdf5) 10%, transparent);
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
.zeileneditor__mehr:focus-visible {
|
||||||
|
outline: 2px solid var(--akzent, #3fbdf5);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.zeileneditor__mehr { transition: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Der Weg zurueck zum Textfeld steht LEISE daneben: Der Normalfall ist
|
||||||
|
die Liste, das Textfeld ist der Ausweg fuer den Sonderfall. */
|
||||||
|
.zeileneditor__wechsel {
|
||||||
|
padding: 6px 2px;
|
||||||
|
min-height: 36px;
|
||||||
|
border: 0; background: transparent;
|
||||||
|
color: var(--text-still);
|
||||||
|
font: inherit; font-size: .79rem;
|
||||||
|
text-decoration: underline;
|
||||||
|
text-underline-offset: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.zeileneditor__wechsel:hover { color: var(--text-leise); }
|
||||||
|
.zeileneditor__wechsel:focus-visible {
|
||||||
|
outline: 2px solid var(--akzent, #3fbdf5);
|
||||||
|
outline-offset: 2px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Der Hinweis "Läuft 14 Tage." -- und die Warnung, wenn das Ende vor
|
||||||
|
dem Anfang liegt. Die Warnung ist ein WORT und nicht nur eine Farbe:
|
||||||
|
Wer Farben schlecht unterscheidet, saehe sonst gar nichts. */
|
||||||
|
#hinweis-dauer[data-warnung="ja"] {
|
||||||
|
color: var(--warn, #ff9aa2);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------
|
||||||
|
DIE VORSCHAU
|
||||||
|
--------------------------------------------------------------------- */
|
||||||
|
.ev-vorschau {
|
||||||
|
margin: 18px 0 4px;
|
||||||
|
padding: 14px;
|
||||||
|
border: 1px dashed var(--rand);
|
||||||
|
border-radius: var(--radius-klein);
|
||||||
|
background: rgba(255, 255, 255, .012);
|
||||||
|
}
|
||||||
|
.ev-vorschau__schild {
|
||||||
|
margin: 0 0 10px;
|
||||||
|
font-size: .72rem; font-weight: 700;
|
||||||
|
letter-spacing: .09em; text-transform: uppercase;
|
||||||
|
color: var(--text-still);
|
||||||
|
}
|
||||||
|
/* Die Vorschau zeigt nur die Buehne -- der Rest der Karte haengt an
|
||||||
|
Daten, die es vor dem Speichern noch nicht gibt (Knoepfe, Ampel,
|
||||||
|
Rueckmeldungen). Eine Vorschau, die etwas zeigt, das hinterher
|
||||||
|
fehlt, ist schlimmer als eine kurze. */
|
||||||
|
.ev-vorschau .eintrag-karte { margin-bottom: 0; }
|
||||||
|
|||||||
+817
-30
@@ -374,6 +374,79 @@
|
|||||||
return { schluessel: 'laeuft', text: von === bis ? 'heute' : 'läuft bis ' + datum(bis) };
|
return { schluessel: 'laeuft', text: von === bis ? 'heute' : 'läuft bis ' + datum(bis) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
WIE LANGE NOCH? (03.10.2026)
|
||||||
|
|
||||||
|
Die eine Frage, die bei einem Wettbewerb wirklich zaehlt -- und
|
||||||
|
die Karte hat sie bis heute nicht beantwortet. Dort stand dreimal
|
||||||
|
dasselbe Datum ("laeuft bis 16.10.2026", "03.10.2026 - 16.10.2026",
|
||||||
|
"Im Kalender am 03.10.2026") und nirgends die Zahl, die man
|
||||||
|
eigentlich wissen will.
|
||||||
|
|
||||||
|
IN TAGEN, NICHT IN STUNDEN. Ein Event laeuft ueber Wochen; "noch
|
||||||
|
312 Stunden" muss man erst umrechnen. Am LETZTEN Tag wechselt der
|
||||||
|
Ton: Dann ist "heute ist der letzte Tag" die Auskunft, und sie
|
||||||
|
gehoert hervorgehoben.
|
||||||
|
|
||||||
|
GERECHNET WIRD AUF TAGEN, nicht auf Zeitpunkten. Ein Event endet
|
||||||
|
am 16.10. -- also mit dem Ablauf dieses Tages, nicht um 00:00 Uhr.
|
||||||
|
Wer mit Date.now() rechnet, meldet am Morgen des letzten Tages
|
||||||
|
"vorbei".
|
||||||
|
*/
|
||||||
|
const TAG_MS = 86400000;
|
||||||
|
const alsTag = (iso) => {
|
||||||
|
const t = String(iso || '').slice(0, 10);
|
||||||
|
return /^\d{4}-\d{2}-\d{2}$/.test(t) ? new Date(t + 'T00:00:00').getTime() : null;
|
||||||
|
};
|
||||||
|
const tageZwischen = (a, b) => Math.round((b - a) / TAG_MS);
|
||||||
|
|
||||||
|
/** Der Satz unter dem Titel: "noch 13 Tage", "letzter Tag",
|
||||||
|
* "startet morgen", "vorbei seit 12 Tagen". */
|
||||||
|
function eventNoch(e) {
|
||||||
|
const heuteIso = window.heuteLokal ? window.heuteLokal()
|
||||||
|
: new Date().toISOString().slice(0, 10);
|
||||||
|
const heute = alsTag(heuteIso);
|
||||||
|
const von = alsTag(e.datum);
|
||||||
|
const bis = alsTag(e.event_ende || e.datum);
|
||||||
|
if (heute === null || von === null || bis === null) return null;
|
||||||
|
|
||||||
|
if (heute < von) {
|
||||||
|
const n = tageZwischen(heute, von);
|
||||||
|
return { wort: n === 1 ? 'startet morgen' : `startet in ${n} Tagen`, dringend: n <= 1 };
|
||||||
|
}
|
||||||
|
if (heute > bis) {
|
||||||
|
const n = tageZwischen(bis, heute);
|
||||||
|
return { wort: n === 1 ? 'seit gestern vorbei' : `vorbei seit ${n} Tagen`, dringend: false };
|
||||||
|
}
|
||||||
|
const n = tageZwischen(heute, bis);
|
||||||
|
if (n === 0) return { wort: 'heute ist der letzte Tag', dringend: true };
|
||||||
|
if (n === 1) return { wort: 'noch 1 Tag', dringend: true };
|
||||||
|
/* "Noch 2 Tage" ist knapp, "noch 3" ist es nicht mehr -- die Grenze
|
||||||
|
ist gesetzt und nicht gemessen, aber sie steht an EINER Stelle. */
|
||||||
|
return { wort: `noch ${n} Tage`, dringend: n <= 2 };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Wie viel des Zeitraums ist herum? 0 bis 1, oder null.
|
||||||
|
*
|
||||||
|
* FUER EINEN BALKEN, nicht fuer eine Zahl. "Wie viel Zeit ist noch"
|
||||||
|
* sieht man an einer Laenge sofort und muss sie nicht lesen -- genau
|
||||||
|
* wie beim Rangbalken der Wunschliste darueber.
|
||||||
|
*
|
||||||
|
* EIN EINTAEGIGES EVENT hat keinen Verlauf (von === bis, Division
|
||||||
|
* durch null). Dann gibt es keinen Balken: Ein Balken, der bei einem
|
||||||
|
* Tagesevent immer voll oder immer leer stuende, sagt nichts. */
|
||||||
|
function eventFortschritt(e) {
|
||||||
|
const heuteIso = window.heuteLokal ? window.heuteLokal()
|
||||||
|
: new Date().toISOString().slice(0, 10);
|
||||||
|
const heute = alsTag(heuteIso);
|
||||||
|
const von = alsTag(e.datum);
|
||||||
|
const bis = alsTag(e.event_ende || e.datum);
|
||||||
|
if (heute === null || von === null || bis === null || bis <= von) return null;
|
||||||
|
const anteil = (heute - von) / (bis - von);
|
||||||
|
return Math.max(0, Math.min(1, anteil));
|
||||||
|
}
|
||||||
|
|
||||||
/* Der Abruf steht seit dem 22.09.2026 in assets/js/holen.js.
|
/* Der Abruf steht seit dem 22.09.2026 in assets/js/holen.js.
|
||||||
Er stand ACHTMAL da, Zeichen fuer Zeichen gleich -- und als
|
Er stand ACHTMAL da, Zeichen fuer Zeichen gleich -- und als
|
||||||
die Regel darin sich als falsch herausstellte (jeder 404
|
die Regel darin sich als falsch herausstellte (jeder 404
|
||||||
@@ -428,8 +501,14 @@
|
|||||||
feld.click();
|
feld.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
function tuKnopf(text, tu) {
|
/* `klasse` kam am 03.10.2026 dazu, fuer den Loeschknopf an der
|
||||||
const b = el('button', 'schritt', text);
|
Eventkarte. Vorher sahen dort vier Knoepfe gleich aus -- darunter
|
||||||
|
der eine, den man nicht zuruecknehmen kann. Die Unterscheidung
|
||||||
|
gehoert an den Knopf und nicht in eine Regel, die ihn ueber seine
|
||||||
|
Stellung in der Reihe sucht: Kommt ein fuenfter dazu, trifft so
|
||||||
|
eine Regel den Falschen. */
|
||||||
|
function tuKnopf(text, tu, klasse) {
|
||||||
|
const b = el('button', 'schritt' + (klasse ? ' ' + klasse : ''), text);
|
||||||
b.type = 'button';
|
b.type = 'button';
|
||||||
b.addEventListener('click', async () => {
|
b.addEventListener('click', async () => {
|
||||||
b.disabled = true; melde('');
|
b.disabled = true; melde('');
|
||||||
@@ -509,10 +588,319 @@
|
|||||||
if (ton) document.body.dataset.ton = String(ton);
|
if (ton) document.body.dataset.ton = String(ton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DIE BUEHNE EINES EVENTS (03.10.2026)
|
||||||
|
|
||||||
|
Filipe: "ich will das viel geiler viel perfekter."
|
||||||
|
|
||||||
|
GEMESSEN, WARUM: Auf 1280 px war eine Eventkarte 1196 px hoch --
|
||||||
|
hoeher als das Fenster. 638 px davon, also 53 %, waren das Banner,
|
||||||
|
und zwar leeres Banner: Der Titel stand DARUNTER, bei 1482 px auf
|
||||||
|
der Seite. Man musste zweimal scrollen, um zu erfahren, wie das
|
||||||
|
Event ueberhaupt heisst. Dazu war der Titel 15,36 px gross -- 1,4 px
|
||||||
|
mehr als der Fliesstext, der darunter stand.
|
||||||
|
|
||||||
|
ALSO STEHT DER TITEL JETZT AUF DEM BILD. Das Banner ist kein Anhang
|
||||||
|
mehr, sondern der Hintergrund des Kopfes: Es behaelt seine Wirkung,
|
||||||
|
verliert aber die Hoehe, die es ohne Inhalt verbraucht hat. Die
|
||||||
|
Hoehe ist gedeckelt (CSS), damit ein hochkantes Bild die Karte
|
||||||
|
nicht erneut aufreisst.
|
||||||
|
|
||||||
|
OHNE BANNER GIBT ES TROTZDEM EINE BUEHNE -- dann aus Farbe. Eine
|
||||||
|
Karte, die je nach Bild zwei voellig verschiedene Formen hat, liest
|
||||||
|
man als Unordnung; und ein Event ohne Bild ist kein Event zweiter
|
||||||
|
Klasse.
|
||||||
|
|
||||||
|
DIE LESBARKEIT KOMMT NICHT VOM ZUFALL: Ueber dem Bild liegt ein
|
||||||
|
Verlauf von unten (siehe .ev-buehne__schleier im CSS). Ein heller
|
||||||
|
Banner wuerde sonst weisse Schrift auf Weiss ergeben -- und genau
|
||||||
|
das kann man einem Bild, das jemand spaeter hochlaedt, nicht
|
||||||
|
ansehen. Der Schleier gilt deshalb immer, nicht nur bei dunklen
|
||||||
|
Bildern. */
|
||||||
|
function eventBuehne(e, stand, kopf) {
|
||||||
|
const b = el('header', 'ev-buehne');
|
||||||
|
b.dataset.stand = stand.schluessel;
|
||||||
|
|
||||||
|
const bild = (e.bilder || [])[0];
|
||||||
|
if (bild) {
|
||||||
|
b.dataset.mitbild = 'ja';
|
||||||
|
const img = el('img', 'ev-buehne__bild');
|
||||||
|
img.src = '/workspace/api/dateien/' + bild.id + '/bild';
|
||||||
|
/* LEERES alt IST HIER RICHTIG: Das Banner ist Schmuck hinter dem
|
||||||
|
Titel, der direkt darauf steht. Ein zweites Mal "Bild zu
|
||||||
|
Oktober Event" vorgelesen zu bekommen, nachdem der Titel schon
|
||||||
|
kam, ist Laerm, keine Auskunft. */
|
||||||
|
img.alt = '';
|
||||||
|
img.loading = 'lazy';
|
||||||
|
img.decoding = 'async';
|
||||||
|
/* Faellt das Bild aus, bleibt die Buehne stehen -- nur eben als
|
||||||
|
Farbe. Ein kaputtes Bildsymbol mitten im Kopf saehe aus, als
|
||||||
|
sei die Seite defekt. */
|
||||||
|
img.addEventListener('error', () => { img.remove(); delete b.dataset.mitbild; });
|
||||||
|
b.append(img);
|
||||||
|
|
||||||
|
/* ==== DAS BANNER IN VOLLER GROESSE (03.10.2026) ==============
|
||||||
|
|
||||||
|
EINE VERSCHLECHTERUNG, DIE BEIM NACHSEHEN AUFFIEL: Vorher war
|
||||||
|
das Bild ein Verweis -- ein Klick zeigte es ganz. Als es zur
|
||||||
|
Buehne wurde, fiel dieser Weg weg, und das ist bei genau
|
||||||
|
diesen Bildern der falsche Verlust: Auf Filipes Oktober-Banner
|
||||||
|
steht die eigentliche Ansage IM Bild ("Schaffst du es, ab
|
||||||
|
HEUTE bis zum 16.10.2026") samt der drei Bedingungen. Die
|
||||||
|
Buehne zeigt davon einen Ausschnitt -- sie muss, sonst waere
|
||||||
|
sie wieder 638 px hoch.
|
||||||
|
|
||||||
|
DESHALB EIN EIGENER KNOPF und nicht die ganze Flaeche: Auf der
|
||||||
|
Buehne stehen Titel und Zeitangabe, und Text, den man nicht
|
||||||
|
markieren kann, ohne dass sich ein Fenster oeffnet, ist
|
||||||
|
aergerlich. Ein kleiner Knopf oben rechts ist eindeutig --
|
||||||
|
und er sagt mit Worten, was er tut, nicht nur mit einem
|
||||||
|
Symbol. */
|
||||||
|
const auf = el('a', 'ev-buehne__ganz');
|
||||||
|
auf.href = '/workspace/api/dateien/' + bild.id + '/bild';
|
||||||
|
auf.target = '_blank';
|
||||||
|
auf.rel = 'noopener';
|
||||||
|
auf.append(el('span', 'ev-buehne__ganz-zeichen'));
|
||||||
|
auf.append(el('span', 'ev-buehne__ganz-wort', 'Banner ganz'));
|
||||||
|
auf.title = 'Zeigt das Banner in voller Größe in einem neuen Fenster';
|
||||||
|
b.append(auf);
|
||||||
|
}
|
||||||
|
b.append(el('div', 'ev-buehne__schleier'));
|
||||||
|
|
||||||
|
const inhalt = el('div', 'ev-buehne__inhalt');
|
||||||
|
kopf.classList.add('ev-buehne__kopf');
|
||||||
|
inhalt.append(kopf);
|
||||||
|
|
||||||
|
/* DIE ZEITZEILE -- einmal, nicht dreimal.
|
||||||
|
|
||||||
|
"noch 13 Tage" steht VOR dem Datum: Es ist die Antwort, das
|
||||||
|
Datum ist der Beleg dazu. Und ein Zeitraum gehoert als Spanne
|
||||||
|
gelesen, nicht als zwei Einzeldaten -- deshalb ein Gedankenstrich
|
||||||
|
und kein zweites Feld. */
|
||||||
|
const zeit = el('p', 'ev-zeit');
|
||||||
|
const noch = eventNoch(e);
|
||||||
|
if (noch) {
|
||||||
|
const m = el('span', 'ev-noch', noch.wort);
|
||||||
|
m.dataset.stand = stand.schluessel;
|
||||||
|
if (noch.dringend) m.dataset.dringend = 'ja';
|
||||||
|
zeit.append(m);
|
||||||
|
}
|
||||||
|
const von = datum(e.datum);
|
||||||
|
const bis = e.event_ende && e.event_ende !== e.datum ? datum(e.event_ende) : null;
|
||||||
|
zeit.append(el('span', 'ev-spanne', bis ? von + ' – ' + bis : von));
|
||||||
|
inhalt.append(zeit);
|
||||||
|
|
||||||
|
/* DER ZEITBALKEN. "Wie viel ist herum" sieht man an einer Laenge
|
||||||
|
sofort; als Zahl muesste man sie lesen und umrechnen. Fuer
|
||||||
|
Vorleseprogramme steht derselbe Inhalt als Satz da -- ein Balken
|
||||||
|
ohne Beschriftung ist fuer sie gar nicht vorhanden. */
|
||||||
|
const anteil = eventFortschritt(e);
|
||||||
|
if (anteil !== null && stand.schluessel !== 'kommt') {
|
||||||
|
const bal = el('div', 'ev-zeitbalken');
|
||||||
|
const f = el('div', 'ev-zeitbalken__fuellung');
|
||||||
|
f.style.width = Math.round(anteil * 100) + '%';
|
||||||
|
bal.append(f);
|
||||||
|
bal.setAttribute('role', 'img');
|
||||||
|
bal.setAttribute('aria-label', noch
|
||||||
|
? 'Zeitraum: ' + noch.wort
|
||||||
|
: Math.round(anteil * 100) + ' Prozent des Zeitraums vorbei');
|
||||||
|
inhalt.append(bal);
|
||||||
|
}
|
||||||
|
|
||||||
|
b.append(inhalt);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DIE AUFGABEN ZUM ABHAKEN (03.10.2026)
|
||||||
|
|
||||||
|
Bisher stand hier ein Absatz mit white-space: pre-line -- also
|
||||||
|
genau das, was DogFather getippt hatte, Zeichen fuer Zeichen. Im
|
||||||
|
echten Oktober-Event sah das so aus:
|
||||||
|
|
||||||
|
.Jeden Tag Live gehen
|
||||||
|
.22-Live-Stunden erreichen
|
||||||
|
. 33k Diamanten erreichen
|
||||||
|
|
||||||
|
Einmal mit Leerzeichen, zweimal ohne. Das ist keine Schlamperei,
|
||||||
|
sondern die unvermeidliche Folge davon, dass die Aufzaehlungs-
|
||||||
|
zeichen von Hand getippt werden. Jetzt setzt die Liste sie selbst
|
||||||
|
(siehe punkteAusText im Server), und die Einrueckung stimmt
|
||||||
|
zwangslaeufig.
|
||||||
|
|
||||||
|
JEDER HAKT FUER SICH AB. Der Haken ist eine Selbstauskunft: "diese
|
||||||
|
Bedingung habe ich erfuellt". Niemand kann ihn bei jemand anderem
|
||||||
|
setzen, auch die Leitung nicht -- sonst waere es eine Bewertung.
|
||||||
|
|
||||||
|
DIE ZAHL KOMMT VOM SERVER, auch nach dem Klicken. Im Browser
|
||||||
|
weiterzuzaehlen ("war 1, jetzt 2") geht schief, sobald zwei
|
||||||
|
Fenster offen sind oder eine Aufgabe inzwischen umgeschrieben
|
||||||
|
wurde. Angezeigt wird sie trotzdem sofort -- bei einem Haken ist
|
||||||
|
eine halbe Sekunde Wartezeit der Unterschied zwischen "hat
|
||||||
|
geklappt" und "hab ich das jetzt gedrueckt?". Antwortet der Server
|
||||||
|
anders, gilt seine Zahl. Dieselbe Ueberlegung steht schon beim
|
||||||
|
Knopf "Will ich auch".
|
||||||
|
|
||||||
|
EIN VORBEIGELAUFENES EVENT WIRD NICHT MEHR ABGEHAKT. Der Haken
|
||||||
|
waere eine Behauptung ueber etwas, das nicht mehr stattfindet --
|
||||||
|
und die Liste bleibt trotzdem lesbar, damit man nachschlagen kann,
|
||||||
|
worum es ging. */
|
||||||
|
function eventAufgaben(e, stand) {
|
||||||
|
const punkte = Array.isArray(e.event_punkte) ? e.event_punkte : [];
|
||||||
|
if (!punkte.length) return null;
|
||||||
|
|
||||||
|
const block = el('section', 'ev-block ev-block--aufgaben');
|
||||||
|
const kopf = el('div', 'ev-block__kopf');
|
||||||
|
kopf.append(el('h4', 'ev-block__schild', 'Aufgaben'));
|
||||||
|
|
||||||
|
const offen = stand.schluessel !== 'vorbei';
|
||||||
|
let geschafft = punkte.filter((p) => p.meiner).length;
|
||||||
|
|
||||||
|
const zaehler = el('span', 'ev-zaehler');
|
||||||
|
const zahlMalen = () => {
|
||||||
|
zaehler.textContent = geschafft + ' von ' + punkte.length;
|
||||||
|
const voll = punkte.length > 0 && geschafft === punkte.length;
|
||||||
|
zaehler.dataset.voll = voll ? 'ja' : '';
|
||||||
|
block.dataset.fertig = voll ? 'ja' : '';
|
||||||
|
};
|
||||||
|
zahlMalen();
|
||||||
|
kopf.append(zaehler);
|
||||||
|
block.append(kopf);
|
||||||
|
|
||||||
|
const liste = el('ul', 'ev-liste');
|
||||||
|
for (const p of punkte) {
|
||||||
|
const zeile = el('li', 'ev-punkt');
|
||||||
|
if (!offen) {
|
||||||
|
/* Ohne Knopf, aber mit demselben Zeichen davor: Die Liste soll
|
||||||
|
gleich aussehen, nur eben nicht mehr bedienbar. */
|
||||||
|
zeile.dataset.abgehakt = p.meiner ? 'ja' : '';
|
||||||
|
zeile.append(el('span', 'ev-punkt__kaestchen'));
|
||||||
|
zeile.append(el('span', 'ev-punkt__text', p.text));
|
||||||
|
liste.append(zeile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const knopf = el('button', 'ev-punkt__knopf');
|
||||||
|
knopf.type = 'button';
|
||||||
|
let meiner = !!p.meiner;
|
||||||
|
const malen = () => {
|
||||||
|
knopf.setAttribute('aria-pressed', String(meiner));
|
||||||
|
zeile.dataset.abgehakt = meiner ? 'ja' : '';
|
||||||
|
};
|
||||||
|
knopf.append(el('span', 'ev-punkt__kaestchen'));
|
||||||
|
knopf.append(el('span', 'ev-punkt__text', p.text));
|
||||||
|
malen();
|
||||||
|
knopf.addEventListener('click', async () => {
|
||||||
|
knopf.disabled = true;
|
||||||
|
meiner = !meiner;
|
||||||
|
geschafft += meiner ? 1 : -1;
|
||||||
|
malen(); zahlMalen();
|
||||||
|
try {
|
||||||
|
const a = await hole('/workspace/api/eintrag/' + e.id + '/punkt/' + p.schluessel,
|
||||||
|
meiner
|
||||||
|
? { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: '{}' }
|
||||||
|
: { method: 'DELETE' });
|
||||||
|
if (a.ok) {
|
||||||
|
const j = await a.json();
|
||||||
|
geschafft = j.geschafft;
|
||||||
|
const frisch = (j.punkte || []).find((x) => x.schluessel === p.schluessel);
|
||||||
|
if (frisch) meiner = !!frisch.meiner;
|
||||||
|
malen(); zahlMalen();
|
||||||
|
} else {
|
||||||
|
/* ZURUECKDREHEN UND SAGEN, WORAN ES LAG. Ein Haken, der
|
||||||
|
aussieht wie gesetzt und keiner ist, ist schlimmer als
|
||||||
|
ein Klick, der sichtbar nicht geklappt hat. */
|
||||||
|
meiner = !meiner;
|
||||||
|
geschafft += meiner ? 1 : -1;
|
||||||
|
malen(); zahlMalen();
|
||||||
|
melde(sagWas((await a.json().catch(() => ({}))).fehler,
|
||||||
|
'Das Abhaken hat nicht geklappt.'));
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
/* umgeleitet -- holen.js schickt bei 401 zur Anmeldung */
|
||||||
|
} finally { knopf.disabled = false; }
|
||||||
|
});
|
||||||
|
zeile.append(knopf);
|
||||||
|
liste.append(zeile);
|
||||||
|
}
|
||||||
|
block.append(liste);
|
||||||
|
|
||||||
|
/* WER MACHT MIT? Nur fuer die Leitung (der Server schickt das Feld
|
||||||
|
sonst gar nicht), und nur, wenn ueberhaupt jemand angefangen hat.
|
||||||
|
Eine Ueberschrift "Dabei" ueber einer leeren Flaeche sieht aus,
|
||||||
|
als sei die Abfrage kaputt. */
|
||||||
|
if (Array.isArray(e.event_stand) && e.event_stand.length) {
|
||||||
|
const wer = el('div', 'ev-mitmacher');
|
||||||
|
wer.append(el('span', 'ev-mitmacher__schild', 'Dabei'));
|
||||||
|
for (const m of e.event_stand) {
|
||||||
|
const x = el('span', 'ev-mitmacher__person',
|
||||||
|
(m.name || 'jemand') + ' · ' + m.geschafft + '/' + punkte.length);
|
||||||
|
if (m.geschafft >= punkte.length) x.dataset.voll = 'ja';
|
||||||
|
wer.append(x);
|
||||||
|
}
|
||||||
|
block.append(wer);
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Die Regeln -- dieselbe Liste, aber ohne Haken.
|
||||||
|
*
|
||||||
|
* BEWUSST ANDERS ALS DIE AUFGABEN. Vorher waren beide derselbe graue
|
||||||
|
* Kasten mit derselben Ueberschriftzeile; nebeneinander sahen "was
|
||||||
|
* ich tun soll" und "was dabei gilt" gleich wichtig aus. Eine Regel
|
||||||
|
* ist aber kein Schritt: Man hakt sie nicht ab, man haelt sie ein. */
|
||||||
|
function eventRegeln(e) {
|
||||||
|
const punkte = Array.isArray(e.event_regelpunkte) ? e.event_regelpunkte : [];
|
||||||
|
if (!punkte.length) return null;
|
||||||
|
const block = el('section', 'ev-block ev-block--regeln');
|
||||||
|
const kopf = el('div', 'ev-block__kopf');
|
||||||
|
kopf.append(el('h4', 'ev-block__schild', 'Regeln'));
|
||||||
|
block.append(kopf);
|
||||||
|
const liste = el('ul', 'ev-liste ev-liste--still');
|
||||||
|
for (const p of punkte) {
|
||||||
|
const zeile = el('li', 'ev-punkt ev-punkt--regel');
|
||||||
|
zeile.append(el('span', 'ev-punkt__zeichen'));
|
||||||
|
zeile.append(el('span', 'ev-punkt__text', p.text));
|
||||||
|
liste.append(zeile);
|
||||||
|
}
|
||||||
|
block.append(liste);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Der dritte Ausgang fuer die Event-Bloecke.
|
||||||
|
*
|
||||||
|
* Kommt vom Server keine Punkteliste (alte Fassung im Netz, Feld
|
||||||
|
* leer geblieben, Abfrage gescheitert), stand hier sonst GAR NICHTS
|
||||||
|
* -- die Aufgaben eines laufenden Wettbewerbs waeren wortlos
|
||||||
|
* verschwunden. Das ist der schlimmere Ausgang: Eine schlichte
|
||||||
|
* Liste ist ein kleiner Schoenheitsfehler, eine fehlende Bedingung
|
||||||
|
* ein inhaltlicher Verlust.
|
||||||
|
*
|
||||||
|
* Es ist bewusst dieselbe Form wie frueher (Absatz mit erhaltenen
|
||||||
|
* Zeilenumbruechen), nur im neuen Rahmen. */
|
||||||
|
function eventRueckfall(name, text) {
|
||||||
|
const block = el('section', 'ev-block ev-block--roh');
|
||||||
|
const kopf = el('div', 'ev-block__kopf');
|
||||||
|
kopf.append(el('h4', 'ev-block__schild', name));
|
||||||
|
block.append(kopf);
|
||||||
|
block.append(el('p', 'ev-rohtext', text));
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
function karte(e) {
|
function karte(e) {
|
||||||
const k = el('article', 'eintrag-karte');
|
const k = el('article', 'eintrag-karte');
|
||||||
k.dataset.dringlich = e.dringlichkeit;
|
k.dataset.dringlich = e.dringlichkeit;
|
||||||
k.dataset.status = e.status;
|
k.dataset.status = e.status;
|
||||||
|
|
||||||
|
/* IST DAS EIN EVENT? Dann sieht diese Karte anders aus -- Buehne
|
||||||
|
statt Bildstreifen, Listen statt Textbloecke, der Zeitraum einmal
|
||||||
|
statt dreimal. Die Frage wird HIER gestellt und nicht erst unten
|
||||||
|
bei den Bloecken: Davon haengt auch ab, ob das Bild oben als
|
||||||
|
Streifen erscheint (bei einem Event ist es der Hintergrund des
|
||||||
|
Kopfes) -- und diese Entscheidung faellt weiter oben als die
|
||||||
|
bisherige Zeile `const stand = ...`. */
|
||||||
|
const evStand = istEventArt(e.art) ? eventStand(e) : null;
|
||||||
|
if (evStand) k.dataset.eventkarte = 'ja';
|
||||||
/* DIE ART GEHOERT AN DIE KARTE (22.09.2026).
|
/* DIE ART GEHOERT AN DIE KARTE (22.09.2026).
|
||||||
|
|
||||||
Am Anschlagbrett traegt sie die Farbe: Ansage, Neue Regel,
|
Am Anschlagbrett traegt sie die Farbe: Ansage, Neue Regel,
|
||||||
@@ -701,7 +1089,11 @@
|
|||||||
nicht-anspringbaren Kacheln ist keine Galerie. Deshalb ein
|
nicht-anspringbaren Kacheln ist keine Galerie. Deshalb ein
|
||||||
echter Verweis mit Beschriftung -- das kann die Tastatur, ohne
|
echter Verweis mit Beschriftung -- das kann die Tastatur, ohne
|
||||||
eine Zeile JavaScript. */
|
eine Zeile JavaScript. */
|
||||||
if (Array.isArray(e.bilder) && e.bilder.length) {
|
/* BEI EINEM EVENT NICHT HIER: Das erste Bild wird zur Buehne
|
||||||
|
hinter dem Titel (siehe eventBuehne). Ein Streifen DARUEBER und
|
||||||
|
dasselbe Bild nochmal dahinter waere die Doppelung, die diese
|
||||||
|
Karte gerade verloren hat. */
|
||||||
|
if (!evStand && Array.isArray(e.bilder) && e.bilder.length) {
|
||||||
const bg = el('div', 'bildstreifen');
|
const bg = el('div', 'bildstreifen');
|
||||||
if (e.bilder.length > 1) bg.dataset.mehrere = 'ja';
|
if (e.bilder.length > 1) bg.dataset.mehrere = 'ja';
|
||||||
for (const b of e.bilder) {
|
for (const b of e.bilder) {
|
||||||
@@ -745,7 +1137,12 @@
|
|||||||
k.append(bg);
|
k.append(bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
k.append(kopf);
|
/* Beim Event wandert derselbe Kopf auf die Buehne -- mit allem,
|
||||||
|
was darin steckt (Etikett, Titel, "nur DogFather", Bewertung).
|
||||||
|
Ihn dort neu zu bauen hiesse, jede dieser Sonderregeln ein
|
||||||
|
zweites Mal zu pflegen. */
|
||||||
|
if (evStand) k.append(eventBuehne(e, evStand, kopf));
|
||||||
|
else k.append(kopf);
|
||||||
|
|
||||||
/* ---- DAS VIDEO (17.09.2026), Stufe A des Video-Plans ----------
|
/* ---- DAS VIDEO (17.09.2026), Stufe A des Video-Plans ----------
|
||||||
Der Knopf ist die Antwort auf "und dann liken": Er fuehrt
|
Der Knopf ist die Antwort auf "und dann liken": Er fuehrt
|
||||||
@@ -874,18 +1271,12 @@
|
|||||||
-- da, wo bei allen anderen Karten das Datum steht --, liest man
|
-- da, wo bei allen anderen Karten das Datum steht --, liest man
|
||||||
erst die Aufgaben und danach, dass es seit einer Woche vorbei
|
erst die Aufgaben und danach, dass es seit einer Woche vorbei
|
||||||
ist. */
|
ist. */
|
||||||
const stand = istEventArt(e.art) ? eventStand(e) : null;
|
const stand = evStand;
|
||||||
if (stand) {
|
/* Der Zustand bleibt als Merkmal an der Karte -- daran haengt im
|
||||||
k.dataset.event = stand.schluessel;
|
CSS, wie ein vorbeigelaufenes Event zuruecktritt. Die ZEILE, die
|
||||||
const zeile = el('p', 'event-zeitraum');
|
hier frueher stand ("laeuft bis 16.10.2026" plus Spanne), ist
|
||||||
zeile.dataset.stand = stand.schluessel;
|
weg: Sie steht jetzt in der Buehne, und zwar einmal. */
|
||||||
zeile.append(el('span', 'event-zeitraum__marke', stand.text));
|
if (stand) k.dataset.event = stand.schluessel;
|
||||||
zeile.append(el('span', 'event-zeitraum__spanne',
|
|
||||||
e.event_ende && e.event_ende !== e.datum
|
|
||||||
? `${datum(e.datum)} – ${datum(e.event_ende)}`
|
|
||||||
: datum(e.datum)));
|
|
||||||
k.append(zeile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.text) {
|
if (e.text) {
|
||||||
const t = el('p', 'eintrag-text');
|
const t = el('p', 'eintrag-text');
|
||||||
@@ -894,15 +1285,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stand) {
|
if (stand) {
|
||||||
for (const [feld, name] of [['event_aufgaben', 'Aufgaben'], ['event_regeln', 'Regeln']]) {
|
/* DIE ZERLEGUNG MACHT DER SERVER (event_punkte /
|
||||||
if (!e[feld]) continue;
|
event_regelpunkte). Sie hier zu wiederholen hiesse, die
|
||||||
const block = el('div', 'event-block');
|
Rechenvorschrift fuer den Schluessel eines Punktes an zwei
|
||||||
block.append(el('h4', 'event-block__schild', name));
|
Stellen zu haben -- und ein Haken, der nach einem Umbau am
|
||||||
/* Zeilenumbrueche bleiben stehen (white-space: pre-line im CSS).
|
falschen Punkt haengt, faellt niemandem auf.
|
||||||
Eine Aufzaehlung, die zu einem Absatz zusammenlaeuft, ist
|
|
||||||
genau das, was diese beiden Felder verhindern sollen. */
|
FAELLT DIE AUSKUNFT AUS (alte Serverfassung, leeres Feld),
|
||||||
block.append(el('p', 'event-block__text', e[feld]));
|
bleibt der Textblock als Rueckfall stehen. Lieber eine
|
||||||
k.append(block);
|
schlichte Liste als eine Karte, auf der die Aufgaben fehlen. */
|
||||||
|
const auf = eventAufgaben(e, stand)
|
||||||
|
|| (e.event_aufgaben ? eventRueckfall('Aufgaben', e.event_aufgaben) : null);
|
||||||
|
const reg = eventRegeln(e)
|
||||||
|
|| (e.event_regeln ? eventRueckfall('Regeln', e.event_regeln) : null);
|
||||||
|
/* BEIDE IN EINE REIHE, nicht untereinander an die Karte.
|
||||||
|
|
||||||
|
Auf 1280 px ist eine Karte rund 1160 px breit. "30
|
||||||
|
Live-Stunden" ueber diese Breite zu ziehen und darunter noch
|
||||||
|
einmal "Nur eigene Konten" verschenkt zwei Drittel der Flaeche
|
||||||
|
und macht die Karte unnoetig lang.
|
||||||
|
|
||||||
|
Wie viele Spalten daraus werden, entscheidet das CSS -- und
|
||||||
|
zwar durch MESSEN (auto-fit mit Mindestbreite), nicht durch
|
||||||
|
eine Fensterbreite in einer Zahl. Eine feste Schwelle waere
|
||||||
|
beim naechsten zusaetzlichen Block wieder falsch. */
|
||||||
|
if (auf || reg) {
|
||||||
|
const reihe = el('div', 'ev-bloecke');
|
||||||
|
if (auf) reihe.append(auf);
|
||||||
|
if (reg) reihe.append(reg);
|
||||||
|
k.append(reihe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -922,7 +1333,12 @@
|
|||||||
|
|
||||||
ES IST EIN LINK, keine Marke. Wer liest „steht im Kalender",
|
ES IST EIN LINK, keine Marke. Wer liest „steht im Kalender",
|
||||||
will als Naechstes nachsehen, was noch an dem Tag ist. */
|
will als Naechstes nachsehen, was noch an dem Tag ist. */
|
||||||
if (e.termin) {
|
/* BEIM EVENT NICHT: Dort steht der Zeitraum schon in der Buehne.
|
||||||
|
"Im Kalender am 03.10.2026" waere die DRITTE Zeile mit demselben
|
||||||
|
Datum gewesen -- gemessen am echten Oktober-Event standen dort
|
||||||
|
"laeuft bis 16.10.", "03.10. - 16.10." und "Im Kalender am
|
||||||
|
03.10." untereinander. */
|
||||||
|
if (e.termin && !evStand) {
|
||||||
/* LINK NUR, WENN DER KALENDER FUER MICH OFFEN IST (19.09.2026).
|
/* LINK NUR, WENN DER KALENDER FUER MICH OFFEN IST (19.09.2026).
|
||||||
|
|
||||||
Fuer die Community ist er es nicht -- `kalender.html` steht in
|
Fuer die Community ist er es nicht -- `kalender.html` steht in
|
||||||
@@ -1459,7 +1875,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await laden();
|
await laden();
|
||||||
}));
|
}, 'schritt--gefahr'));
|
||||||
}
|
}
|
||||||
fuss.append(knoepfe);
|
fuss.append(knoepfe);
|
||||||
k.append(fuss);
|
k.append(fuss);
|
||||||
@@ -2775,6 +3191,333 @@
|
|||||||
Oeffnen zu schalten waere der bequeme Fehler: Man oeffnet mit
|
Oeffnen zu schalten waere der bequeme Fehler: Man oeffnet mit
|
||||||
"Schulung", waehlt "Agentur-Events" und fuellt ein Formular aus,
|
"Schulung", waehlt "Agentur-Events" und fuellt ein Formular aus,
|
||||||
das noch nach der alten Art fragt. */
|
das noch nach der alten Art fragt. */
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DAS EVENT-FORMULAR (03.10.2026)
|
||||||
|
|
||||||
|
Filipe: "und auch wenn man die eintraegt und so soll viel mehr
|
||||||
|
perfektioniert und uebersichtlicher sein."
|
||||||
|
|
||||||
|
WORAN ES LAG, SIEHT MAN AM ERGEBNIS. Im echten Oktober-Event stand
|
||||||
|
auf der Karte:
|
||||||
|
|
||||||
|
.Jeden Tag Live gehen
|
||||||
|
.22-Live-Stunden erreichen
|
||||||
|
. 33k Diamanten erreichen
|
||||||
|
|
||||||
|
Einmal mit Leerzeichen hinter dem Punkt, zweimal ohne. Das ist
|
||||||
|
keine Unachtsamkeit, sondern die zwangslaeufige Folge eines leeren
|
||||||
|
Textfeldes: Wer eine Aufzaehlung tippt, setzt die Zeichen selbst --
|
||||||
|
und dann sehen drei Zeilen auf drei Arten aus.
|
||||||
|
|
||||||
|
DIE LOESUNG IST NICHT, DAS ERGEBNIS ZU PUTZEN, sondern die Eingabe
|
||||||
|
zu aendern: EINE ZEILE, EIN FELD. Das Aufzaehlungszeichen setzt
|
||||||
|
das Formular, nicht der Mensch.
|
||||||
|
|
||||||
|
DAS TEXTFELD BLEIBT TROTZDEM DIE WAHRHEIT. Abgeschickt wird
|
||||||
|
weiterhin `event_aufgaben` als Text -- der Server bleibt
|
||||||
|
unveraendert, und wer lieber tippt (oder etwas aus einer Nachricht
|
||||||
|
einfuegt), schaltet mit einem Knopf zurueck. Ein Editor, der den
|
||||||
|
einzigen Weg darstellt, ist eine Sackgasse, sobald er einen Fall
|
||||||
|
nicht kann.
|
||||||
|
|
||||||
|
EINGEFUEGTER MEHRZEILIGER TEXT WIRD AUFGETEILT. Der haeufigste
|
||||||
|
Weg, wie so eine Liste entsteht, ist Kopieren aus einer Nachricht.
|
||||||
|
Landete das alles in einem Feld, waere der Editor genau dort im
|
||||||
|
Weg, wo er helfen soll.
|
||||||
|
===================================================================== */
|
||||||
|
|
||||||
|
/** Blendet die Textgestaltungs-Leiste (F K U S) mit ihrem Feld um.
|
||||||
|
*
|
||||||
|
* SIE GEHOERT ZUM TEXTFELD, NICHT ZUM FORMULAR. Solange der
|
||||||
|
* Zeilen-Editor dran ist, ist das Feld verborgen -- die Leiste
|
||||||
|
* stand aber weiter da und schwebte unter einer Liste, zu der sie
|
||||||
|
* nicht gehoert. Beim ersten Lauf sah man unter "+ Punkt" ein
|
||||||
|
* "F K U S", das nichts bewirkte.
|
||||||
|
*
|
||||||
|
* SIE WIRD JEDES MAL NEU GESUCHT und nicht beim Aufbau gemerkt:
|
||||||
|
* textform.js haengt sie NACH dem Formularaufbau an (sie haengt an
|
||||||
|
* `laden()`), und etwas zu merken, was es noch nicht gibt, ergibt
|
||||||
|
* null. */
|
||||||
|
function textformUmblenden(feld, zeigen) {
|
||||||
|
const l = feld?.parentElement?.querySelector('.textform');
|
||||||
|
if (l) l.hidden = !zeigen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Baut den Zeilen-Editor vor ein Textfeld.
|
||||||
|
* feldId: die Nummer des <textarea>, das die Wahrheit bleibt. */
|
||||||
|
function zeilenEditor(feldId, wort, beispiel) {
|
||||||
|
const feld = $(feldId);
|
||||||
|
if (!feld || feld.dataset.editor === 'ja') return;
|
||||||
|
feld.dataset.editor = 'ja';
|
||||||
|
|
||||||
|
const rahmen = el('div', 'zeileneditor');
|
||||||
|
const liste = el('div', 'zeileneditor__liste');
|
||||||
|
rahmen.append(liste);
|
||||||
|
|
||||||
|
/* Aus dem Feld in den Editor -- beim Oeffnen und beim Zurueck-
|
||||||
|
schalten. Zerlegt wird nach derselben Regel wie im Server
|
||||||
|
(Zeilenumbruch, fuehrendes Aufzaehlungszeichen weg); dass beide
|
||||||
|
dasselbe tun, weist pruef-eventkarte.mjs nach. */
|
||||||
|
const auseinander = (text) => String(text || '')
|
||||||
|
.split(/\r?\n/)
|
||||||
|
.map((z) => z.replace(/^[\s]*[-–—•·*▪◦‣>+]+[\s]*/u, '').trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
/* ... und zurueck. Das Zeichen setzt das Formular, einheitlich. */
|
||||||
|
const zusammen = () => [...liste.querySelectorAll('.zeileneditor__feld')]
|
||||||
|
.map((f) => f.value.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((t) => '· ' + t)
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
const schreiben = () => {
|
||||||
|
feld.value = zusammen();
|
||||||
|
/* Das Ereignis von Hand ausloesen: Die Vorschau haengt daran,
|
||||||
|
und ein Wert, der per Skript gesetzt wird, loest `input` nicht
|
||||||
|
von selbst aus. */
|
||||||
|
feld.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
|
};
|
||||||
|
|
||||||
|
function zeileBauen(wert, fokus) {
|
||||||
|
const z = el('div', 'zeileneditor__zeile');
|
||||||
|
const punkt = el('span', 'zeileneditor__zeichen');
|
||||||
|
punkt.setAttribute('aria-hidden', 'true');
|
||||||
|
const f = el('input', 'zeileneditor__feld');
|
||||||
|
f.type = 'text';
|
||||||
|
f.value = wert || '';
|
||||||
|
f.maxLength = 300;
|
||||||
|
f.setAttribute('aria-label', wort + ': ein Punkt');
|
||||||
|
/* DER PLATZHALTER GEHOERT ZUM FELD. "z. B. 22 Live-Stunden
|
||||||
|
erreichen" stand im ersten Lauf auch unter REGELN -- und ein
|
||||||
|
Beispiel, das zur Ueberschrift darueber nicht passt, ist eine
|
||||||
|
Fehlanleitung, keine Hilfe. */
|
||||||
|
f.placeholder = beispiel;
|
||||||
|
|
||||||
|
f.addEventListener('input', schreiben);
|
||||||
|
|
||||||
|
/* EINFUEGEN AUS EINER NACHRICHT. Der haeufigste Weg, wie so eine
|
||||||
|
Liste entsteht. Ohne das landete der ganze Block in einem
|
||||||
|
Feld -- und der Editor waere genau dort hinderlich, wo er
|
||||||
|
helfen soll. */
|
||||||
|
f.addEventListener('paste', (ev) => {
|
||||||
|
const roh = ev.clipboardData?.getData('text') || '';
|
||||||
|
if (!/\r?\n/.test(roh)) return;
|
||||||
|
ev.preventDefault();
|
||||||
|
const teile = auseinander(roh);
|
||||||
|
if (!teile.length) return;
|
||||||
|
f.value = teile[0];
|
||||||
|
let davor = z;
|
||||||
|
for (const t of teile.slice(1)) {
|
||||||
|
const neu = zeileBauen(t);
|
||||||
|
davor.insertAdjacentElement('afterend', neu);
|
||||||
|
davor = neu;
|
||||||
|
}
|
||||||
|
schreiben();
|
||||||
|
});
|
||||||
|
|
||||||
|
f.addEventListener('keydown', (ev) => {
|
||||||
|
/* ENTER MACHT EINE NEUE ZEILE -- so wie in jeder Liste, die
|
||||||
|
man kennt. Ohne das muesste man nach jedem Punkt zur Maus
|
||||||
|
greifen, und bei fuenf Punkten ist das fuenfmal. */
|
||||||
|
if (ev.key === 'Enter') {
|
||||||
|
ev.preventDefault();
|
||||||
|
const neu = zeileBauen('', true);
|
||||||
|
z.insertAdjacentElement('afterend', neu);
|
||||||
|
schreiben();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* RUECKTASTE IM LEEREN FELD nimmt die Zeile weg und setzt den
|
||||||
|
Schreibzeiger ans Ende der vorigen -- dieselbe Erwartung wie
|
||||||
|
in einem Textfeld. Die letzte Zeile bleibt stehen: ein
|
||||||
|
Editor ohne ein einziges Feld hat keinen Weg zurueck. */
|
||||||
|
if (ev.key === 'Backspace' && !f.value) {
|
||||||
|
const alle = [...liste.querySelectorAll('.zeileneditor__zeile')];
|
||||||
|
if (alle.length <= 1) return;
|
||||||
|
ev.preventDefault();
|
||||||
|
const stelle = alle.indexOf(z);
|
||||||
|
const ziel = alle[stelle - 1] || alle[stelle + 1];
|
||||||
|
z.remove();
|
||||||
|
schreiben();
|
||||||
|
const zf = ziel?.querySelector('.zeileneditor__feld');
|
||||||
|
if (zf) { zf.focus(); zf.setSelectionRange(zf.value.length, zf.value.length); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const weg = el('button', 'zeileneditor__weg');
|
||||||
|
weg.type = 'button';
|
||||||
|
weg.setAttribute('aria-label', 'Diesen Punkt entfernen');
|
||||||
|
weg.title = 'Diesen Punkt entfernen';
|
||||||
|
weg.addEventListener('click', () => {
|
||||||
|
const alle = [...liste.querySelectorAll('.zeileneditor__zeile')];
|
||||||
|
if (alle.length <= 1) { f.value = ''; schreiben(); f.focus(); return; }
|
||||||
|
z.remove();
|
||||||
|
schreiben();
|
||||||
|
});
|
||||||
|
|
||||||
|
z.append(punkt, f, weg);
|
||||||
|
if (fokus) setTimeout(() => f.focus(), 0);
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fuellen = () => {
|
||||||
|
liste.textContent = '';
|
||||||
|
const teile = auseinander(feld.value);
|
||||||
|
if (!teile.length) liste.append(zeileBauen(''));
|
||||||
|
else for (const t of teile) liste.append(zeileBauen(t));
|
||||||
|
};
|
||||||
|
fuellen();
|
||||||
|
|
||||||
|
const fuss = el('div', 'zeileneditor__fuss');
|
||||||
|
const mehr = el('button', 'zeileneditor__mehr', '+ Punkt');
|
||||||
|
mehr.type = 'button';
|
||||||
|
mehr.addEventListener('click', () => {
|
||||||
|
liste.append(zeileBauen('', true));
|
||||||
|
schreiben();
|
||||||
|
});
|
||||||
|
fuss.append(mehr);
|
||||||
|
|
||||||
|
/* DER WEG ZURUECK ZUM TEXTFELD. Er steht leise daneben, nicht als
|
||||||
|
zweiter Hauptknopf: Der Normalfall ist die Liste. */
|
||||||
|
const umschalten = el('button', 'zeileneditor__wechsel', 'als Text bearbeiten');
|
||||||
|
umschalten.type = 'button';
|
||||||
|
umschalten.addEventListener('click', () => {
|
||||||
|
const alsText = rahmen.hidden !== true;
|
||||||
|
if (alsText) {
|
||||||
|
rahmen.hidden = true;
|
||||||
|
feld.hidden = false;
|
||||||
|
textformUmblenden(feld, true);
|
||||||
|
umschalten.textContent = 'als Liste bearbeiten';
|
||||||
|
feld.focus();
|
||||||
|
} else {
|
||||||
|
/* Zurueck in die Liste: neu einlesen, damit auch das ankommt,
|
||||||
|
was im Textfeld getippt wurde. */
|
||||||
|
fuellen();
|
||||||
|
rahmen.hidden = false;
|
||||||
|
feld.hidden = true;
|
||||||
|
textformUmblenden(feld, false);
|
||||||
|
umschalten.textContent = 'als Text bearbeiten';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fuss.append(umschalten);
|
||||||
|
rahmen.append(fuss);
|
||||||
|
|
||||||
|
feld.hidden = true;
|
||||||
|
textformUmblenden(feld, false);
|
||||||
|
feld.insertAdjacentElement('beforebegin', rahmen);
|
||||||
|
/* Der Umschalter gehoert NEBEN beides und nicht in den Rahmen --
|
||||||
|
sonst verschwindet er mit, sobald man zum Textfeld wechselt. */
|
||||||
|
rahmen.insertAdjacentElement('afterend', fuss);
|
||||||
|
|
||||||
|
/* Wird das Feld von aussen gesetzt (Vorlage uebernehmen, Formular
|
||||||
|
zuruecksetzen), muss die Liste nachziehen. */
|
||||||
|
feld.addEventListener('frischfuellen', fuellen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DIE VORSCHAU (03.10.2026)
|
||||||
|
|
||||||
|
Sie zeigt die BUEHNE, und zwar mit genau der Funktion, die sie
|
||||||
|
spaeter auch auf dem Brett baut (eventBuehne). Eine nachgebaute
|
||||||
|
Vorschau waere eine zweite Fassung derselben Sache -- und die
|
||||||
|
zeigt irgendwann etwas, das hinterher anders aussieht. Dann ist
|
||||||
|
sie schlimmer als keine.
|
||||||
|
|
||||||
|
SIE ERSCHEINT ERST, WENN ES ETWAS ZU ZEIGEN GIBT. Eine leere
|
||||||
|
Vorschau ueber einem leeren Formular ist nur ein weiterer Kasten.
|
||||||
|
===================================================================== */
|
||||||
|
function vorschauZeichnen() {
|
||||||
|
const ziel = $('ev-vorschau');
|
||||||
|
if (!ziel) return;
|
||||||
|
const event = istEventArt($('f-art').value);
|
||||||
|
const titel = ($('f-titel')?.value || '').trim();
|
||||||
|
if (!event || !titel) { ziel.hidden = true; ziel.textContent = ''; return; }
|
||||||
|
|
||||||
|
const heute = window.heuteLokal ? window.heuteLokal()
|
||||||
|
: new Date().toISOString().slice(0, 10);
|
||||||
|
const e = {
|
||||||
|
id: 0,
|
||||||
|
titel,
|
||||||
|
art: EVENT_ART,
|
||||||
|
datum: $('f-datum')?.value || heute,
|
||||||
|
event_ende: $('f-ende')?.value || null,
|
||||||
|
bilder: [],
|
||||||
|
};
|
||||||
|
const stand = eventStand(e);
|
||||||
|
if (!stand) { ziel.hidden = true; ziel.textContent = ''; return; }
|
||||||
|
|
||||||
|
ziel.hidden = false;
|
||||||
|
ziel.textContent = '';
|
||||||
|
ziel.append(el('p', 'ev-vorschau__schild', 'So sieht es nachher aus'));
|
||||||
|
|
||||||
|
const karte = el('article', 'eintrag-karte');
|
||||||
|
karte.dataset.eventkarte = 'ja';
|
||||||
|
karte.dataset.event = stand.schluessel;
|
||||||
|
karte.dataset.status = 'offen';
|
||||||
|
|
||||||
|
/* Derselbe Kopf wie auf dem Brett: Etikett und Titel. */
|
||||||
|
const kopf = el('div', 'eintrag-kopf');
|
||||||
|
kopf.append(el('span', 'marke-art', einstellung?.arten?.[EVENT_ART] || 'Agentur-Events'));
|
||||||
|
kopf.append(el('h3', 'eintrag-titel', titel));
|
||||||
|
karte.append(eventBuehne(e, stand, kopf));
|
||||||
|
ziel.append(karte);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Wie lange laeuft das Event? Steht unter dem Zeitraum.
|
||||||
|
*
|
||||||
|
* NICHT NUR ZIERDE: "02.10. bis 15.10." liest man als Spanne, aber
|
||||||
|
* ob das zwei Wochen sind, rechnet man im Kopf nach. Und ein Ende
|
||||||
|
* VOR dem Anfang ist ein Tippfehler, den man sonst erst auf der
|
||||||
|
* Karte sieht -- dort steht dann "vorbei seit 3 Tagen" an einem
|
||||||
|
* Event, das gerade erst angelegt wurde. */
|
||||||
|
function dauerZeigen() {
|
||||||
|
const ziel = $('hinweis-dauer');
|
||||||
|
if (!ziel) return;
|
||||||
|
const event = istEventArt($('f-art').value);
|
||||||
|
const von = $('f-datum')?.value || '';
|
||||||
|
const bis = $('f-ende')?.value || '';
|
||||||
|
if (!event || !von) { ziel.textContent = ''; delete ziel.dataset.warnung; return; }
|
||||||
|
if (!bis) {
|
||||||
|
ziel.textContent = 'Ohne Ende gilt der eine Tag.';
|
||||||
|
delete ziel.dataset.warnung;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const a = new Date(von + 'T00:00:00').getTime();
|
||||||
|
const b = new Date(bis + 'T00:00:00').getTime();
|
||||||
|
if (Number.isNaN(a) || Number.isNaN(b)) { ziel.textContent = ''; return; }
|
||||||
|
if (b < a) {
|
||||||
|
ziel.textContent = 'Das Ende liegt vor dem Anfang.';
|
||||||
|
ziel.dataset.warnung = 'ja';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete ziel.dataset.warnung;
|
||||||
|
/* EINSCHLIESSLICH BEIDER TAGE: Ein Event vom 2. bis zum 15. laeuft
|
||||||
|
14 Tage, nicht 13 -- der letzte Tag zaehlt mit, und genau so
|
||||||
|
rechnet auch eventNoch auf der Karte. */
|
||||||
|
const tage = Math.round((b - a) / 86400000) + 1;
|
||||||
|
ziel.textContent = tage === 1 ? 'Ein Tag.' : `Läuft ${tage} Tage.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Das Formular in den Zustand "frisch" bringen.
|
||||||
|
*
|
||||||
|
* AN EINER STELLE, weil es zwei Anlaesse gibt (Abbrechen und
|
||||||
|
* erfolgreiches Speichern) und beide dasselbe meinen. Vorher gab es
|
||||||
|
* zwei Fassungen, und die kuerzere liess Vorschau und Zeilen-Editor
|
||||||
|
* stehen -- der Unterschied faellt erst auf, wenn jemand zwei
|
||||||
|
* Events nacheinander anlegt. */
|
||||||
|
function formularLeeren() {
|
||||||
|
$('neu').reset();
|
||||||
|
$('neu-fehler').textContent = '';
|
||||||
|
/* `form.reset()` leert die Textfelder, aber die Zeilenfelder davor
|
||||||
|
stehen noch voll da -- und beim naechsten Tippen schrieben sie
|
||||||
|
den alten Stand zurueck. */
|
||||||
|
for (const f of ['f-aufgaben', 'f-regeln']) {
|
||||||
|
$(f)?.dispatchEvent(new Event('frischfuellen'));
|
||||||
|
}
|
||||||
|
/* Und das raeumt Dauerhinweis und Vorschau mit ab. */
|
||||||
|
formularAnpassen();
|
||||||
|
}
|
||||||
|
|
||||||
function formularAnpassen() {
|
function formularAnpassen() {
|
||||||
const event = istEventArt($('f-art').value);
|
const event = istEventArt($('f-art').value);
|
||||||
|
|
||||||
@@ -2791,6 +3534,18 @@
|
|||||||
$('feld-ende').hidden = !event;
|
$('feld-ende').hidden = !event;
|
||||||
$('feld-aufgaben').hidden = !event;
|
$('feld-aufgaben').hidden = !event;
|
||||||
$('feld-regeln').hidden = !event;
|
$('feld-regeln').hidden = !event;
|
||||||
|
|
||||||
|
/* DER ZEILEN-EDITOR WIRD ERST GEBAUT, WENN ER GEBRAUCHT WIRD --
|
||||||
|
und nur einmal (zeilenEditor merkt sich das am Feld). Ihn beim
|
||||||
|
Laden der Seite fuer jedes Brett aufzubauen hiesse, zwei
|
||||||
|
Eingabehilfen vorzuhalten, die auf fuenf von sechs Brettern nie
|
||||||
|
sichtbar werden. */
|
||||||
|
if (event) {
|
||||||
|
zeilenEditor('f-aufgaben', 'Aufgaben', 'z. B. 22 Live-Stunden erreichen');
|
||||||
|
zeilenEditor('f-regeln', 'Regeln', 'z. B. Nur Streams auf dem eigenen Konto');
|
||||||
|
}
|
||||||
|
dauerZeigen();
|
||||||
|
vorschauZeichnen();
|
||||||
if (einstellung?.dringlichkeit) $('feld-dringlich').hidden = event;
|
if (einstellung?.dringlichkeit) $('feld-dringlich').hidden = event;
|
||||||
if (einstellung?.vertraulich) $('feld-vertraulich').hidden = event;
|
if (einstellung?.vertraulich) $('feld-vertraulich').hidden = event;
|
||||||
|
|
||||||
@@ -2845,13 +3600,19 @@
|
|||||||
umschalten(true);
|
umschalten(true);
|
||||||
});
|
});
|
||||||
$('neu-abbrechen').addEventListener('click', () => {
|
$('neu-abbrechen').addEventListener('click', () => {
|
||||||
$('neu').reset(); $('neu-fehler').textContent = ''; formularAnpassen(); umschalten(false);
|
formularLeeren(); umschalten(false);
|
||||||
});
|
});
|
||||||
/* "change" und nicht "input": Die Auswahl wird ueber wahl.js zu einer
|
/* "change" und nicht "input": Die Auswahl wird ueber wahl.js zu einer
|
||||||
Knopfliste umgebaut, und die meldet ihre Wahl als change-Ereignis
|
Knopfliste umgebaut, und die meldet ihre Wahl als change-Ereignis
|
||||||
am urspruenglichen <select> -- ohne dieses Ereignis merkte das
|
am urspruenglichen <select> -- ohne dieses Ereignis merkte das
|
||||||
Formular vom Artwechsel nichts. */
|
Formular vom Artwechsel nichts. */
|
||||||
$('f-art').addEventListener('change', formularAnpassen);
|
$('f-art').addEventListener('change', formularAnpassen);
|
||||||
|
/* Dauer und Vorschau haengen an vier Feldern. Ein einziger Zuhoerer
|
||||||
|
am Formular statt vier einzelnen: Kommt ein fuenftes Feld dazu,
|
||||||
|
ist es automatisch dabei -- eine Liste von Feldnamen waere die,
|
||||||
|
die beim naechsten Umbau nicht nachgezogen wird. */
|
||||||
|
$('neu')?.addEventListener('input', () => { dauerZeigen(); vorschauZeichnen(); });
|
||||||
|
$('neu')?.addEventListener('change', () => { dauerZeigen(); vorschauZeichnen(); });
|
||||||
/* DER HINWEIS ZIEHT MIT. Ohne diese beiden Zeilen stuende er auf dem
|
/* DER HINWEIS ZIEHT MIT. Ohne diese beiden Zeilen stuende er auf dem
|
||||||
Stand vom Oeffnen des Formulars -- also dauerhaft auf „Heute", auch
|
Stand vom Oeffnen des Formulars -- also dauerhaft auf „Heute", auch
|
||||||
nachdem jemand den 24. eingetragen hat. Ein Hinweis, der beim Tippen
|
nachdem jemand den 24. eingetragen hat. Ein Hinweis, der beim Tippen
|
||||||
@@ -2915,7 +3676,22 @@
|
|||||||
$('neu-fehler').textContent = sagWas((await a.json().catch(() => ({}))).fehler, 'Ging nicht.');
|
$('neu-fehler').textContent = sagWas((await a.json().catch(() => ({}))).fehler, 'Ging nicht.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$('neu').reset(); umschalten(false);
|
/* DIESELBE FUNKTION WIE BEIM ABBRECHEN (03.10.2026).
|
||||||
|
|
||||||
|
Hier stand `$('neu').reset()` allein -- also eine ZWEITE
|
||||||
|
Fassung des Zuruecksetzens, die weniger tat als die beim
|
||||||
|
Abbrechen. Gemessen hat das die Pruefung: Nach dem Speichern
|
||||||
|
blieb die Vorschau mit dem gerade angelegten Event stehen
|
||||||
|
(verborgen: false, 81 Zeichen Inhalt), und beim naechsten
|
||||||
|
"Neuer Eintrag" standen die Aufgaben des vorigen Events noch
|
||||||
|
im Editor -- man haette sie versehentlich ein zweites Mal
|
||||||
|
eingetragen.
|
||||||
|
|
||||||
|
`form.reset()` allein kann das gar nicht leisten: Es setzt
|
||||||
|
Formularfelder auf ihre Vorgabe zurueck und weiss nichts von
|
||||||
|
Zeilen-Editoren, Hinweisen oder einer Vorschau, die daneben
|
||||||
|
stehen. */
|
||||||
|
formularLeeren(); umschalten(false);
|
||||||
await laden();
|
await laden();
|
||||||
} catch { /* umgeleitet */ } finally { knopf.disabled = false; }
|
} catch { /* umgeleitet */ } finally { knopf.disabled = false; }
|
||||||
});
|
});
|
||||||
@@ -3233,7 +4009,18 @@
|
|||||||
if (window.Textform) {
|
if (window.Textform) {
|
||||||
for (const id of ['f-text', 'f-aufgaben', 'f-regeln']) {
|
for (const id of ['f-text', 'f-aufgaben', 'f-regeln']) {
|
||||||
const feld = document.getElementById(id);
|
const feld = document.getElementById(id);
|
||||||
if (feld) window.Textform.leiste(feld);
|
if (!feld) continue;
|
||||||
|
window.Textform.leiste(feld);
|
||||||
|
/* ERST DANACH VERSTECKEN. Der Zeilen-Editor steht bei den
|
||||||
|
Event-Feldern schon (er entsteht in formularAnpassen, und
|
||||||
|
das laeuft innerhalb von laden()) -- die Leiste kommt also
|
||||||
|
NACH ihm und waere sonst als einziges Stueck des Textfeldes
|
||||||
|
sichtbar geblieben. Das war im ersten Bildschirmfoto das
|
||||||
|
"F K U S" unter der Punkteliste. */
|
||||||
|
if (feld.dataset.editor === 'ja' && feld.hidden) {
|
||||||
|
const l = feld.parentElement?.querySelector('.textform');
|
||||||
|
if (l) l.hidden = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
+19
-19
@@ -12,19 +12,19 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -430,22 +430,22 @@
|
|||||||
<!-- TEXTFORM ZUERST (21.09.2026): Die Seite fragt beim Zeichnen nach
|
<!-- TEXTFORM ZUERST (21.09.2026): Die Seite fragt beim Zeichnen nach
|
||||||
`window.Textform`. Kaeme sie spaeter, waere der erste Eintrag ohne
|
`window.Textform`. Kaeme sie spaeter, waere der erste Eintrag ohne
|
||||||
Gestaltung. Kein `defer`, damit sie wirklich vorher dasteht. -->
|
Gestaltung. Kein `defer`, damit sie wirklich vorher dasteht. -->
|
||||||
<script src="assets/js/textform.js?v=202610031525"></script>
|
<script src="assets/js/textform.js?v=202610031857"></script>
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610031525" defer></script>
|
<script src="assets/js/hochladen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/zuteilung.js?v=202610031525" defer></script>
|
<script src="assets/js/zuteilung.js?v=202610031857" defer></script>
|
||||||
<!-- Der Vorlagenkatalog stand bis zum 23.09.2026 mitten in
|
<!-- Der Vorlagenkatalog stand bis zum 23.09.2026 mitten in
|
||||||
aufgaben.js. Er bedient jetzt zwei Seiten und hat deshalb eine
|
aufgaben.js. Er bedient jetzt zwei Seiten und hat deshalb eine
|
||||||
eigene Datei; hier zeigt er den Creator-Katalog.
|
eigene Datei; hier zeigt er den Creator-Katalog.
|
||||||
Vor aufgaben.js, weil die Seite ihn beim Start einrichtet. -->
|
Vor aufgaben.js, weil die Seite ihn beim Start einrichtet. -->
|
||||||
<script src="assets/js/vorlagenbrett.js?v=202610031525" defer></script>
|
<script src="assets/js/vorlagenbrett.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/aufgaben.js?v=202610031525" defer></script>
|
<script src="assets/js/aufgaben.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/automation.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/automation.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -168,15 +168,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/automation.js?v=202610031525" defer></script>
|
<script src="assets/js/automation.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-17
@@ -7,14 +7,14 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -197,16 +197,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/befinden.js?v=202610031525" defer></script>
|
<script src="assets/js/befinden.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+36
-22
@@ -12,24 +12,24 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/bereich.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/bereich.css?v=202610031857" />
|
||||||
<!-- Wegen des Blocks „Willst du dazugehoeren?" auf dem Brett
|
<!-- Wegen des Blocks „Willst du dazugehoeren?" auf dem Brett
|
||||||
„Mitmachen". Eine eigene Kopie der Regel hier waere die zweite
|
„Mitmachen". Eine eigene Kopie der Regel hier waere die zweite
|
||||||
Stelle, an der dieselbe Sache anders aussieht. -->
|
Stelle, an der dieselbe Sache anders aussieht. -->
|
||||||
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -128,6 +128,13 @@
|
|||||||
<div id="feld-ende" hidden>
|
<div id="feld-ende" hidden>
|
||||||
<label class="feld-schild" for="f-ende">Bis</label>
|
<label class="feld-schild" for="f-ende">Bis</label>
|
||||||
<input id="f-ende" type="date" />
|
<input id="f-ende" type="date" />
|
||||||
|
<!-- WIE LANGE DAS LAEUFT, STEHT DARUNTER (03.10.2026).
|
||||||
|
"02.10. bis 15.10." liest man als Spanne, aber ob das zwei
|
||||||
|
Wochen sind, rechnet man im Kopf nach. Und ein Ende VOR dem
|
||||||
|
Anfang faellt hier auf statt erst auf der Karte - dort
|
||||||
|
stuende dann "vorbei seit 3 Tagen" an einem Event, das
|
||||||
|
gerade erst angelegt wurde. -->
|
||||||
|
<p class="feld-hinweis" id="hinweis-dauer" aria-live="polite"></p>
|
||||||
</div>
|
</div>
|
||||||
<!-- ZU WELCHEM ACCOUNT GEHOERT DAS? (20.09.2026)
|
<!-- ZU WELCHEM ACCOUNT GEHOERT DAS? (20.09.2026)
|
||||||
|
|
||||||
@@ -226,6 +233,13 @@
|
|||||||
<textarea id="f-regeln" rows="5" maxlength="6000"
|
<textarea id="f-regeln" rows="5" maxlength="6000"
|
||||||
placeholder="z. B. · Nur Streams auf dem eigenen Konto · Punkte zählen bis 23:59 am letzten Tag"></textarea>
|
placeholder="z. B. · Nur Streams auf dem eigenen Konto · Punkte zählen bis 23:59 am letzten Tag"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- DIE VORSCHAU (03.10.2026). Sie zeigt die Buehne mit DERSELBEN
|
||||||
|
Funktion, die sie spaeter auf dem Brett baut - eine nachgebaute
|
||||||
|
Vorschau waere eine zweite Fassung derselben Sache und zeigte
|
||||||
|
irgendwann etwas, das hinterher anders aussieht.
|
||||||
|
`hidden` von Anfang an: Ein leerer Kasten ueber einem leeren
|
||||||
|
Formular ist nur ein weiterer Kasten. -->
|
||||||
|
<section class="ev-vorschau" id="ev-vorschau" hidden aria-live="polite"></section>
|
||||||
<p class="fehler" id="neu-fehler" role="alert" aria-live="polite"></p>
|
<p class="fehler" id="neu-fehler" role="alert" aria-live="polite"></p>
|
||||||
<div class="neu__knoepfe">
|
<div class="neu__knoepfe">
|
||||||
<button type="submit" class="knopf knopf--klein" id="neu-speichern">Eintragen</button>
|
<button type="submit" class="knopf knopf--klein" id="neu-speichern">Eintragen</button>
|
||||||
@@ -304,19 +318,19 @@
|
|||||||
<!-- TEXTFORM ZUERST (21.09.2026): Die Seite fragt beim Zeichnen nach
|
<!-- TEXTFORM ZUERST (21.09.2026): Die Seite fragt beim Zeichnen nach
|
||||||
`window.Textform`. Kaeme sie spaeter, waere der erste Eintrag ohne
|
`window.Textform`. Kaeme sie spaeter, waere der erste Eintrag ohne
|
||||||
Gestaltung. Kein `defer`, damit sie wirklich vorher dasteht. -->
|
Gestaltung. Kein `defer`, damit sie wirklich vorher dasteht. -->
|
||||||
<script src="assets/js/textform.js?v=202610031525"></script>
|
<script src="assets/js/textform.js?v=202610031857"></script>
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/checkliste.js?v=202610031525" defer></script>
|
<script src="assets/js/checkliste.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/ampel.js?v=202610031525" defer></script>
|
<script src="assets/js/ampel.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/schulung.js?v=202610031525" defer></script>
|
<script src="assets/js/schulung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereich.js?v=202610031525" defer></script>
|
<script src="assets/js/bereich.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+19
-19
@@ -7,17 +7,17 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/bereich.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/bereich.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/treff.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/treff.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. -->
|
<!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -108,15 +108,15 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Der Fuß gehört zu jeder Seite - siehe pruef-css-klassen. -->
|
<!-- Der Fuß gehört zu jeder Seite - siehe pruef-css-klassen. -->
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/auskunft.js?v=202610031525" defer></script>
|
<script src="assets/js/auskunft.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bewerben.js?v=202610031525" defer></script>
|
<script src="assets/js/bewerben.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+18
-18
@@ -7,16 +7,16 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. -->
|
<!-- haus.css MUSS die letzte Stilvorlage sein - siehe treff-regeln.html. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -80,16 +80,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/auskunft.js?v=202610031525" defer></script>
|
<script src="assets/js/auskunft.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bewerbungen.js?v=202610031525" defer></script>
|
<script src="assets/js/bewerbungen.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -59,11 +59,11 @@
|
|||||||
<!-- DIE WERBEEINBLENDUNG. Dieselbe Datei wie in der Reaction-Seite:
|
<!-- DIE WERBEEINBLENDUNG. Dieselbe Datei wie in der Reaction-Seite:
|
||||||
Zwei Fassungen altern unterschiedlich, und dann sieht der Stream
|
Zwei Fassungen altern unterschiedlich, und dann sieht der Stream
|
||||||
anders aus als das, worueber geredet wird. -->
|
anders aus als das, worueber geredet wird. -->
|
||||||
<link rel="stylesheet" href="assets/css/werbung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/werbung.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
<body class="obs-buehne">
|
<body class="obs-buehne">
|
||||||
<div id="platz"></div>
|
<div id="platz"></div>
|
||||||
<script src="assets/js/werbung.js?v=202610031525" defer></script>
|
<script src="assets/js/werbung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/buehne.js?v=202610031525" defer></script>
|
<script src="assets/js/buehne.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-17
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/calls.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/calls.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -89,15 +89,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202610031525" defer></script>
|
<script src="assets/js/ki.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/calls.js?v=202610031525" defer></script>
|
<script src="assets/js/calls.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+20
-20
@@ -12,26 +12,26 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<!-- aufgaben.css bringt die Dialog- und Formularstile mit (.dialog,
|
<!-- aufgaben.css bringt die Dialog- und Formularstile mit (.dialog,
|
||||||
.neu__zeile, .dialog__knoepfe). Sie stehen dort seit dem
|
.neu__zeile, .dialog__knoepfe). Sie stehen dort seit dem
|
||||||
Aufgabenbrett; sie hierher zu kopieren hiesse, sie an zwei Stellen
|
Aufgabenbrett; sie hierher zu kopieren hiesse, sie an zwei Stellen
|
||||||
zu pflegen. Dieselbe Lösung nutzen kalender.html und content.html.
|
zu pflegen. Dieselbe Lösung nutzen kalender.html und content.html.
|
||||||
Gemeldet von pruef-css-klassen.mjs, bevor jemand einen ungestylten
|
Gemeldet von pruef-css-klassen.mjs, bevor jemand einen ungestylten
|
||||||
Dialog zu sehen bekam. -->
|
Dialog zu sehen bekam. -->
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/chat.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/chat.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -739,24 +739,24 @@
|
|||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script src="assets/js/bereiche.js?v=202610031525"></script>
|
<script src="assets/js/bereiche.js?v=202610031857"></script>
|
||||||
<!-- TEXTFORM VOR ALLEM ANDEREN (21.09.2026): chat.js und bereich.js
|
<!-- TEXTFORM VOR ALLEM ANDEREN (21.09.2026): chat.js und bereich.js
|
||||||
fragen beim Zeichnen nach `window.Textform`. Kaeme sie spaeter,
|
fragen beim Zeichnen nach `window.Textform`. Kaeme sie spaeter,
|
||||||
waere die erste gezeichnete Nachricht ohne Gestaltung -- und das
|
waere die erste gezeichnete Nachricht ohne Gestaltung -- und das
|
||||||
faellt nur dem auf, der genau hinsieht. KEIN `defer`, damit sie
|
faellt nur dem auf, der genau hinsieht. KEIN `defer`, damit sie
|
||||||
wirklich vor den anderen dasteht. -->
|
wirklich vor den anderen dasteht. -->
|
||||||
<script src="assets/js/textform.js?v=202610031525"></script>
|
<script src="assets/js/textform.js?v=202610031857"></script>
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610031525" defer></script>
|
<script src="assets/js/hochladen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525"></script>
|
<script src="assets/js/kopf.js?v=202610031857"></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525"></script>
|
<script src="assets/js/glocke.js?v=202610031857"></script>
|
||||||
<!-- ANRUF VOR CHAT (18.09.2026): anruf.js stellt `window.anrufStarten`
|
<!-- ANRUF VOR CHAT (18.09.2026): anruf.js stellt `window.anrufStarten`
|
||||||
bereit, und chat.js baut die Knoepfe nur, wenn es das gibt.
|
bereit, und chat.js baut die Knoepfe nur, wenn es das gibt.
|
||||||
Andersherum waere die Reihenfolge eine stille Abhaengigkeit --
|
Andersherum waere die Reihenfolge eine stille Abhaengigkeit --
|
||||||
die Knoepfe fehlten, und niemand wuesste warum. -->
|
die Knoepfe fehlten, und niemand wuesste warum. -->
|
||||||
<script src="assets/js/anruf.js?v=202610031525"></script>
|
<script src="assets/js/anruf.js?v=202610031857"></script>
|
||||||
<!-- DIE BILDSCHAU (25.09.2026). Eigene Datei, weil sie nichts vom
|
<!-- DIE BILDSCHAU (25.09.2026). Eigene Datei, weil sie nichts vom
|
||||||
Chat weiss: Sie bekommt einen Weg und einen Namen und zeigt ein
|
Chat weiss: Sie bekommt einen Weg und einen Namen und zeigt ein
|
||||||
Bild. Jede andere Seite mit Fotos kann sie ebenso benutzen, ohne
|
Bild. Jede andere Seite mit Fotos kann sie ebenso benutzen, ohne
|
||||||
@@ -767,8 +767,8 @@
|
|||||||
sie beim ersten Foto noch nicht da -- und der erste Klick ginge
|
sie beim ersten Foto noch nicht da -- und der erste Klick ginge
|
||||||
wie frueher in den Tab. Ein Fehler, der nur beim ERSTEN Mal
|
wie frueher in den Tab. Ein Fehler, der nur beim ERSTEN Mal
|
||||||
auftritt, ist der, den man nie nachstellen kann. -->
|
auftritt, ist der, den man nie nachstellen kann. -->
|
||||||
<script src="assets/js/bildschau.js?v=202610031525"></script>
|
<script src="assets/js/bildschau.js?v=202610031857"></script>
|
||||||
<script src="assets/js/chat.js?v=202610031525"></script>
|
<script src="assets/js/chat.js?v=202610031857"></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-17
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/content.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/content.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -179,15 +179,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/checkliste.js?v=202610031525" defer></script>
|
<script src="assets/js/checkliste.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/content.js?v=202610031525" defer></script>
|
<script src="assets/js/content.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -36,15 +36,15 @@
|
|||||||
<link rel="preload" as="image" href="assets/img/buehne/crew-gate-hoch-580.webp"
|
<link rel="preload" as="image" href="assets/img/buehne/crew-gate-hoch-580.webp"
|
||||||
type="image/webp" media="(max-width: 899px)" />
|
type="image/webp" media="(max-width: 899px)" />
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<!-- Diese Wand steht NUR auf der Adresse von Team Dogi (ueberall sonst
|
<!-- Diese Wand steht NUR auf der Adresse von Team Dogi (ueberall sonst
|
||||||
404, siehe crewWeiche). Sie darf das Haus deshalb direkt nennen
|
404, siehe crewWeiche). Sie darf das Haus deshalb direkt nennen
|
||||||
statt ueber den Platzhalter haus.css zu gehen -- und sie MUSS es:
|
statt ueber den Platzhalter haus.css zu gehen -- und sie MUSS es:
|
||||||
Eine Zugangswand, die sich erst nach dem Umbiegen faerbt, waere
|
Eine Zugangswand, die sich erst nach dem Umbiegen faerbt, waere
|
||||||
die eine Seite, auf der man das Umfaerben sieht. -->
|
die eine Seite, auf der man das Umfaerben sieht. -->
|
||||||
<link rel="stylesheet" href="assets/css/crew-haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/crew-haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="gate gate--crew">
|
<body class="gate gate--crew">
|
||||||
@@ -459,7 +459,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/gate.js?v=202610031525" defer></script>
|
<script src="assets/js/gate.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -23,25 +23,25 @@
|
|||||||
},
|
},
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/crew-192.png?v=202610031525",
|
"src": "/assets/img/app-symbole/crew-192.png?v=202610031857",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/crew-512.png?v=202610031525",
|
"src": "/assets/img/app-symbole/crew-512.png?v=202610031857",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202610031525",
|
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202610031857",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202610031525",
|
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202610031857",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
|
|||||||
+17
-17
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/dateien.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/dateien.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -108,15 +108,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610031525" defer></script>
|
<script src="assets/js/hochladen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/dateien.js?v=202610031525" defer></script>
|
<script src="assets/js/dateien.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+18
-18
@@ -7,14 +7,14 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -306,20 +306,20 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<!-- VOR entwicklung.js: Die Seite richtet den Katalog beim Start ein,
|
<!-- VOR entwicklung.js: Die Seite richtet den Katalog beim Start ein,
|
||||||
also muss es ihn zu dem Zeitpunkt geben. Mit "defer" laufen beide
|
also muss es ihn zu dem Zeitpunkt geben. Mit "defer" laufen beide
|
||||||
in Dokumentreihenfolge. -->
|
in Dokumentreihenfolge. -->
|
||||||
<script src="assets/js/vorlagenbrett.js?v=202610031525" defer></script>
|
<script src="assets/js/vorlagenbrett.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/entwicklung.js?v=202610031525" defer></script>
|
<script src="assets/js/entwicklung.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+15
-15
@@ -7,13 +7,13 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/hilfe.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/hilfe.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -146,14 +146,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/hilfe.js?v=202610031525" defer></script>
|
<script src="assets/js/hilfe.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -30,9 +30,9 @@
|
|||||||
<link rel="preload" as="image" href="assets/img/buehne/gate-hoch-580.webp"
|
<link rel="preload" as="image" href="assets/img/buehne/gate-hoch-580.webp"
|
||||||
type="image/webp" media="(max-width: 899px)" />
|
type="image/webp" media="(max-width: 899px)" />
|
||||||
|
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="gate">
|
<body class="gate">
|
||||||
@@ -427,7 +427,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/gate.js?v=202610031525" defer></script>
|
<script src="assets/js/gate.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-17
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/kalender.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/kalender.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -383,15 +383,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kalender.js?v=202610031525" defer></script>
|
<script src="assets/js/kalender.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kalender-abo.js?v=202610031525" defer></script>
|
<script src="assets/js/kalender-abo.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/leistung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/leistung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -444,13 +444,13 @@
|
|||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525"></script>
|
<script src="assets/js/meldung.js?v=202610031857"></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525"></script>
|
<script src="assets/js/nachfrage.js?v=202610031857"></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525"></script>
|
<script src="assets/js/wahl.js?v=202610031857"></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525"></script>
|
<script src="assets/js/bereiche.js?v=202610031857"></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525"></script>
|
<script src="assets/js/kopf.js?v=202610031857"></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525"></script>
|
<script src="assets/js/glocke.js?v=202610031857"></script>
|
||||||
<script src="assets/js/leistung.js?v=202610031525"></script>
|
<script src="assets/js/leistung.js?v=202610031857"></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -7,17 +7,17 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/manager-ziele.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/manager-ziele.css?v=202610031857" />
|
||||||
<!-- module.css an VORLETZTER, haus.css an LETZTER Stelle. Die
|
<!-- module.css an VORLETZTER, haus.css an LETZTER Stelle. Die
|
||||||
Reihenfolge ist keine Geschmacksfrage: haus.css setzt nur
|
Reihenfolge ist keine Geschmacksfrage: haus.css setzt nur
|
||||||
Variablen, und bei Variablen entscheidet allein, wer zuletzt
|
Variablen, und bei Variablen entscheidet allein, wer zuletzt
|
||||||
kommt. pruef-css-klassen.mjs misst genau dieses Paar nach. -->
|
kommt. pruef-css-klassen.mjs misst genau dieses Paar nach. -->
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -218,16 +218,16 @@
|
|||||||
kopf.js liest daraus die Leitungsrollen. Ohne sie stürzt jede
|
kopf.js liest daraus die Leitungsrollen. Ohne sie stürzt jede
|
||||||
Seite ab, und zwar nur in der Browserkonsole -- die Kopfleiste
|
Seite ab, und zwar nur in der Browserkonsole -- die Kopfleiste
|
||||||
kommt trotzdem. -->
|
kommt trotzdem. -->
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<!-- wahl.js gehört zu kopf.js: Der Sicht-Umschalter baut daraus seine
|
<!-- wahl.js gehört zu kopf.js: Der Sicht-Umschalter baut daraus seine
|
||||||
Liste. pruef-css-klassen setzt das durch, und zwar auch die
|
Liste. pruef-css-klassen setzt das durch, und zwar auch die
|
||||||
Reihenfolge -- kopf.js fragt beim Aufbau nach dem fertigen
|
Reihenfolge -- kopf.js fragt beim Aufbau nach dem fertigen
|
||||||
Bedienelement. -->
|
Bedienelement. -->
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/manager-ziele.js?v=202610031525" defer></script>
|
<script src="assets/js/manager-ziele.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -12,13 +12,13 @@
|
|||||||
vergessen wird. -->
|
vergessen wird. -->
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/material.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/material.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
<body class="start" data-ton="42" data-buehne="studio">
|
<body class="start" data-ton="42" data-buehne="studio">
|
||||||
|
|
||||||
@@ -138,14 +138,14 @@
|
|||||||
<p class="m-laedt" id="laedt">Einen Moment …</p>
|
<p class="m-laedt" id="laedt">Einen Moment …</p>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610031525" defer></script>
|
<script src="assets/js/hochladen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/material.js?v=202610031525" defer></script>
|
<script src="assets/js/material.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+14
-14
@@ -7,13 +7,13 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/notizen.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/notizen.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-ton="46">
|
<body class="start" data-ton="46">
|
||||||
@@ -181,12 +181,12 @@
|
|||||||
|
|
||||||
<!-- bereiche.js VOR kopf.js: Dort steht `window.Bereiche`, und kopf.js
|
<!-- bereiche.js VOR kopf.js: Dort steht `window.Bereiche`, und kopf.js
|
||||||
liest daraus die Leitungsrollen. -->
|
liest daraus die Leitungsrollen. -->
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/notizen.js?v=202610031525" defer></script>
|
<script src="assets/js/notizen.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/personen.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/personen.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -453,14 +453,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/personen.js?v=202610031525" defer></script>
|
<script src="assets/js/personen.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+18
-18
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/profil.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/profil.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -214,16 +214,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610031525" defer></script>
|
<script src="assets/js/hochladen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/steckbrief.js?v=202610031525" defer></script>
|
<script src="assets/js/steckbrief.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/profil.js?v=202610031525" defer></script>
|
<script src="assets/js/profil.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+19
-19
@@ -7,15 +7,15 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/reaktion.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/reaktion.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/spendenkarte.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/spendenkarte.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/werbung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/werbung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start reaktion-seite" data-stand="laedt">
|
<body class="start reaktion-seite" data-stand="laedt">
|
||||||
@@ -905,15 +905,15 @@
|
|||||||
|
|
||||||
<!-- bereiche.js VOR kopf.js: Dort steht `window.Bereiche`, und kopf.js
|
<!-- bereiche.js VOR kopf.js: Dort steht `window.Bereiche`, und kopf.js
|
||||||
liest daraus die Leitungsrollen. -->
|
liest daraus die Leitungsrollen. -->
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/spendenkarte.js?v=202610031525" defer></script>
|
<script src="assets/js/spendenkarte.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/werbung.js?v=202610031525" defer></script>
|
<script src="assets/js/werbung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/reaktion.js?v=202610031525" defer></script>
|
<script src="assets/js/reaktion.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-17
@@ -7,14 +7,14 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/treff.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/treff.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -134,14 +134,14 @@
|
|||||||
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
|
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
|
||||||
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
|
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
|
||||||
die seit dem 07.09. jede Seite danach absucht. -->
|
die seit dem 07.09. jede Seite danach absucht. -->
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/rechte.js?v=202610031525" defer></script>
|
<script src="assets/js/rechte.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+18
-18
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/report.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/report.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -106,17 +106,17 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202610031525" defer></script>
|
<script src="assets/js/ki.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/report.js?v=202610031525" defer></script>
|
<script src="assets/js/report.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/scouting.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/scouting.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -173,14 +173,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/scouting.js?v=202610031525" defer></script>
|
<script src="assets/js/scouting.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -12,21 +12,21 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<!-- Nur die Startseite: Begrüßungskachel, Uhr, Glockenmulde. Siehe
|
<!-- Nur die Startseite: Begrüßungskachel, Uhr, Glockenmulde. Siehe
|
||||||
den Hinweis in start.css -- dort stand es bis zum 07.09.2026. -->
|
den Hinweis in start.css -- dort stand es bis zum 07.09.2026. -->
|
||||||
<link rel="stylesheet" href="assets/css/heim.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/heim.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -751,16 +751,16 @@
|
|||||||
</p>
|
</p>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/live.js?v=202610031525" defer></script>
|
<script src="assets/js/live.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/start.js?v=202610031525" defer></script>
|
<script src="assets/js/start.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-17
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/startcheck.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/startcheck.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -85,16 +85,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202610031525" defer></script>
|
<script src="assets/js/ki.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/startcheck.js?v=202610031525" defer></script>
|
<script src="assets/js/startcheck.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+18
-18
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/profil.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/profil.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -150,16 +150,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610031525" defer></script>
|
<script src="assets/js/hochladen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/auskunft.js?v=202610031525" defer></script>
|
<script src="assets/js/auskunft.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/steckbrief.js?v=202610031525" defer></script>
|
<script src="assets/js/steckbrief.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+14
-14
@@ -7,13 +7,13 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/support.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/support.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -154,16 +154,16 @@
|
|||||||
(reading 'LEITUNG')" ab -- gemessen am 24.09.2026, als diese
|
(reading 'LEITUNG')" ab -- gemessen am 24.09.2026, als diese
|
||||||
Zeile beim Anlegen der Seite fehlte. Die Kopfleiste kam
|
Zeile beim Anlegen der Seite fehlte. Die Kopfleiste kam
|
||||||
trotzdem, deshalb sah man es nur in der Browserkonsole. -->
|
trotzdem, deshalb sah man es nur in der Browserkonsole. -->
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<!-- wahl.js gehoert zu kopf.js: Der Sicht-Umschalter in der
|
<!-- wahl.js gehoert zu kopf.js: Der Sicht-Umschalter in der
|
||||||
Kopfleiste baut daraus seine Liste. pruef-css-klassen setzt das
|
Kopfleiste baut daraus seine Liste. pruef-css-klassen setzt das
|
||||||
seit dem 07.09.2026 durch -- damals fehlte es auf chat.html und
|
seit dem 07.09.2026 durch -- damals fehlte es auf chat.html und
|
||||||
uebersicht.html, und heute hier. -->
|
uebersicht.html, und heute hier. -->
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/support.js?v=202610031525" defer></script>
|
<script src="assets/js/support.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
„Eigenes CSS" leer lassen (der Grund ist schon
|
„Eigenes CSS" leer lassen (der Grund ist schon
|
||||||
durchsichtig).
|
durchsichtig).
|
||||||
====================================================================== -->
|
====================================================================== -->
|
||||||
<link rel="stylesheet" href="assets/css/spendenkarte.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/spendenkarte.css?v=202610031857" />
|
||||||
<style>
|
<style>
|
||||||
/* DURCHSICHTIG BIS AUF DIE KARTEN. OBS legt die Quelle über das
|
/* DURCHSICHTIG BIS AUF DIE KARTEN. OBS legt die Quelle über das
|
||||||
Bild; jede Fläche, die hier steht, deckt dort etwas zu. */
|
Bild; jede Fläche, die hier steht, deckt dort etwas zu. */
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="obs-tafel spendentafel" id="tafel" aria-live="polite"></div>
|
<div class="obs-tafel spendentafel" id="tafel" aria-live="polite"></div>
|
||||||
|
|
||||||
<script src="assets/js/spendenkarte.js?v=202610031525" defer></script>
|
<script src="assets/js/spendenkarte.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/tafel.js?v=202610031525" defer></script>
|
<script src="assets/js/tafel.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+18
-18
@@ -7,18 +7,18 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031857" />
|
||||||
<!-- Wegen des Kastens „Anfragen“ ueber der Liste. Eine eigene Kopie
|
<!-- Wegen des Kastens „Anfragen“ ueber der Liste. Eine eigene Kopie
|
||||||
der Regel hier waere die zweite Stelle, an der dieselbe Sache
|
der Regel hier waere die zweite Stelle, an der dieselbe Sache
|
||||||
anders aussieht. -->
|
anders aussieht. -->
|
||||||
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -111,15 +111,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/talente.js?v=202610031525" defer></script>
|
<script src="assets/js/talente.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -7,20 +7,20 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/team.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/team.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -110,15 +110,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/team.js?v=202610031525" defer></script>
|
<script src="assets/js/team.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-17
@@ -7,20 +7,20 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/team.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/team.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<!-- `data-buehne` steht hier fest und nicht im Skript: Die Kachel zu
|
<!-- `data-buehne` steht hier fest und nicht im Skript: Die Kachel zu
|
||||||
@@ -84,15 +84,15 @@
|
|||||||
Kaputt ist dabei nichts -- er funktioniert. Genau deshalb faellt
|
Kaputt ist dabei nichts -- er funktioniert. Genau deshalb faellt
|
||||||
es niemandem auf, und deshalb prueft pruef-css-klassen die
|
es niemandem auf, und deshalb prueft pruef-css-klassen die
|
||||||
ABHAENGIGKEIT statt der Optik. Hier hat sie angeschlagen. -->
|
ABHAENGIGKEIT statt der Optik. Hier hat sie angeschlagen. -->
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/teamlage.js?v=202610031525" defer></script>
|
<script src="assets/js/teamlage.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+15
-15
@@ -7,13 +7,13 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/bereich.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/bereich.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -112,15 +112,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/teilen.js?v=202610031525" defer></script>
|
<script src="assets/js/teilen.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/treff.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/treff.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -126,14 +126,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/treff-moderation.js?v=202610031525" defer></script>
|
<script src="assets/js/treff-moderation.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -7,18 +7,18 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/treff.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/treff.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein. Auf der Adresse des
|
<!-- haus.css MUSS die letzte Stilvorlage sein. Auf der Adresse des
|
||||||
Rudels biegt der Server genau diesen Dateinamen auf crew-haus.css
|
Rudels biegt der Server genau diesen Dateinamen auf crew-haus.css
|
||||||
um, und die Seite kommt schon beim ERSTEN Abruf in Lila und
|
um, und die Seite kommt schon beim ERSTEN Abruf in Lila und
|
||||||
Babyblau an -- ohne Umfaerben im Browser, ohne Flackern. -->
|
Babyblau an -- ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -248,14 +248,14 @@
|
|||||||
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
|
Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen
|
||||||
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
|
Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen,
|
||||||
die seit dem 07.09. jede Seite danach absucht. -->
|
die seit dem 07.09. jede Seite danach absucht. -->
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/auskunft.js?v=202610031525" defer></script>
|
<script src="assets/js/auskunft.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/treff-regeln.js?v=202610031525" defer></script>
|
<script src="assets/js/treff-regeln.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -12,22 +12,22 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<!-- Formular- und Dialogstile: seit dem 07.09.2026 steht hier der
|
<!-- Formular- und Dialogstile: seit dem 07.09.2026 steht hier der
|
||||||
Dialog "Creator anlegen". -->
|
Dialog "Creator anlegen". -->
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -149,16 +149,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/uebersicht.js?v=202610031525" defer></script>
|
<script src="assets/js/uebersicht.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/unsere-seiten.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/unsere-seiten.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -335,14 +335,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/live.js?v=202610031525" defer></script>
|
<script src="assets/js/live.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/unsere-seiten.js?v=202610031525" defer></script>
|
<script src="assets/js/unsere-seiten.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/unterstuetzen.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/unterstuetzen.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -106,17 +106,17 @@
|
|||||||
<!-- bereiche.js VOR kopf.js: Dort steht `window.Bereiche`, und kopf.js
|
<!-- bereiche.js VOR kopf.js: Dort steht `window.Bereiche`, und kopf.js
|
||||||
liest daraus die Leitungsrollen. Ohne sie stürzt jede Seite mit
|
liest daraus die Leitungsrollen. Ohne sie stürzt jede Seite mit
|
||||||
„Cannot read properties of undefined (reading 'LEITUNG')" ab. -->
|
„Cannot read properties of undefined (reading 'LEITUNG')" ab. -->
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610031525" defer></script>
|
<script src="assets/js/holen.js?v=202610031857" defer></script>
|
||||||
<!-- Die Satz-Tafel. Ohne sie stand auf dieser Seite das Maschinenwort
|
<!-- Die Satz-Tafel. Ohne sie stand auf dieser Seite das Maschinenwort
|
||||||
des Servers (z.B. "nicht_gefunden") statt eines Satzes -- gemeldet
|
des Servers (z.B. "nicht_gefunden") statt eines Satzes -- gemeldet
|
||||||
von pruef-meldungen, nicht beim Ansehen. -->
|
von pruef-meldungen, nicht beim Ansehen. -->
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/unterstuetzen.js?v=202610031525" defer></script>
|
<script src="assets/js/unterstuetzen.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+16
-16
@@ -7,15 +7,15 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/werdegang.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/werdegang.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -144,14 +144,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/werdegang.js?v=202610031525" defer></script>
|
<script src="assets/js/werdegang.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+15
-15
@@ -12,13 +12,13 @@
|
|||||||
vergessen wird. -->
|
vergessen wird. -->
|
||||||
<link rel="manifest" href="/workspace/app.webmanifest" />
|
<link rel="manifest" href="/workspace/app.webmanifest" />
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/willkommen.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/willkommen.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
<!-- KOERPERKLASSE "start", NICHT "gate" (berichtigt 21.09.2026).
|
<!-- KOERPERKLASSE "start", NICHT "gate" (berichtigt 21.09.2026).
|
||||||
`body.gate` ist die Anmeldewand: `display:flex; align-items:center`,
|
`body.gate` ist die Anmeldewand: `display:flex; align-items:center`,
|
||||||
@@ -75,13 +75,13 @@
|
|||||||
<p class="fehler" id="fehler" hidden></p>
|
<p class="fehler" id="fehler" hidden></p>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/willkommen.js?v=202610031525" defer></script>
|
<script src="assets/js/willkommen.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+17
-17
@@ -12,20 +12,20 @@
|
|||||||
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite
|
||||||
eine Flaeche sind statt zweier. -->
|
eine Flaeche sind statt zweier. -->
|
||||||
<meta name="theme-color" content="#06090f" />
|
<meta name="theme-color" content="#06090f" />
|
||||||
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031525" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610031857" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031525" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/wissen.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/wissen.css?v=202610031857" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610031857" />
|
||||||
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
<!-- haus.css MUSS die letzte Stilvorlage sein (10.09.2026).
|
||||||
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
Auf der Agenturadresse ist sie leer -- das Haus hier IST der
|
||||||
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
Grundzustand. Auf der Adresse von Team Dogi biegt der Server
|
||||||
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
genau diesen Dateinamen auf crew-haus.css um, und die Seite
|
||||||
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
kommt schon beim ERSTEN Abruf in Lila und Babyblau an --
|
||||||
ohne Umfaerben im Browser, ohne Flackern. -->
|
ohne Umfaerben im Browser, ohne Flackern. -->
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610031525" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610031857" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -190,15 +190,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610031525" defer></script>
|
<script src="assets/js/meldung.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610031525" defer></script>
|
<script src="assets/js/hochladen.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610031525" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610031857" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610031525" defer></script>
|
<script src="assets/js/wahl.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610031525" defer></script>
|
<script src="assets/js/bereiche.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610031525" defer></script>
|
<script src="assets/js/installieren.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610031525" defer></script>
|
<script src="assets/js/kopf.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610031525" defer></script>
|
<script src="assets/js/glocke.js?v=202610031857" defer></script>
|
||||||
<script src="assets/js/wissen.js?v=202610031525" defer></script>
|
<script src="assets/js/wissen.js?v=202610031857" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user