Reaction: Material statt Kaesten, Spende in der Mitte, Gaeste werden gefragt
Nach Filipes sieben Bildschirmfotos vom 07.10.2026. Sieben Wuensche,
und einer davon ("alles viel hochwertiger") betrifft alle anderen --
deshalb steht das Fundament zuerst und nicht am Ende.
DAS AUSSEHEN HAT EINEN WERKSTOFF. Jede Flaeche sagt jetzt, ob sie oben
oder unten liegt: Was obenauf liegt, bekommt oben eine helle Kante und
darunter einen Schatten; was vertieft ist, genau umgekehrt. Dazwischen
gibt es nichts mehr. Vorher stand im ganzen Pult zweimal eine
Lichtkante und sonst nirgends -- genau deshalb sahen diese zwei Stellen
gut aus und alles daneben danebengestellt. Dazu: jeder Knopf senkt sich
beim Druecken, jedes Feld ist ein Loch und kein Kasten, und wer mit der
Tastatur bedient, wird zum ersten Mal ueberhaupt gesehen.
UND EIN FUND DABEI: Die drei Kacheln des Regieplatzes hiessen in der
HTML anders als im Stilblatt (kachel--laeuft gegen regiekachel--laeuft,
regieregiekachel__kopf gegen regiekachel__kopf). Die Aufteilung "links
was laeuft, rechts was man eintraegt" hat damit NIE gegriffen -- und
mess-reaktion hat den falschen Zustand gemessen und gruen gemeldet,
weil sie gegen die HTML geschrieben war.
DIE SPENDENKARTE STEHT IN DER MITTE und kommt aus der Tiefe nach vorn.
Das dreht eine Entscheidung vom 28.09. um ("sie deckt nie die Mitte
zu"); die Begruendung war richtig und ist es noch -- sie schuetzt das
Video, und Filipe sieht die Spende als das, was in dem Augenblick
zaehlt. Der alte Platz bleibt einen Knopf weit weg und gilt fuer Saal
UND OBS-Tafel. Die Karte besteht dafuer aus zwei Teilen: `opacity`
unter 1 zwingt ein Element auf `transform-style: flat`, eine Karte mit
Deckkraft-Uebergang waere also genau waehrend des Hereinkommens flach
und spraenge am Ende in einem Bild in die Tiefe.
FERTIGE SAETZE GEHEN SOFORT INS BILD. Der Browser schickt nur die
Kennung, den Text holt der Server -- deshalb darf hier die Bestaetigung
entfallen und beim freien Text nicht. Zwei Schranken bleiben: sofort
nur mit einem der vier Knopfbetraege (Filipes Ansage galt dem SATZ,
nicht der Summe), und GEZEIGT IST NICHT GEBUCHT -- die Dogen gibt es
erst nach dem Tipp der Leitung, sonst stellt sich jeder seine eigene
Waehrung aus.
WER GESPENDET HAT, GLAENZT IM CHAT -- je nach Hoehe. Die Dauer haengt
an der Stufe und nicht an einer zweiten Leiter; 0 heisst "gar nicht".
GAESTE WERDEN GEFRAGT, NICHT GEHOLT. Vorher sprang die Kamera eines
Zuschauers an, sobald jemand "Dazuholen" drueckte -- er hat es daran
gemerkt, dass er sich selbst sah. Jetzt gibt es einen Vorraum: eigenes
Bild, Pegel, Kamera und Mikro vorwaehlen, Geraete waehlen, dann "Dabei
sein" oder "Lieber nicht". Zwei Minuten Frist, und sie verfaellt
SICHTBAR -- eine verschwundene Zeile sieht fuer den Host aus wie ein
Verklicker.
DAS MISCHPULT. Hier stand fest `echoCancellation: true,
noiseSuppression: true`. Fuer ein Laptopmikrofon richtig, ueber einem
RODECaster falsch: Das Pult hat Gate, Kompressor und EQ schon gemacht,
und die Echo-Unterdrueckung legt sich danach als zweite Automatik
darueber und duckt, sobald von der Gegenseite Ton kommt -- genau das
Pumpen vom 14.09. Jetzt: Geraetewahl fuer Mikro, Kamera und Ausgabe
(auch fuer Gaeste), ein Pultmodus, und darunter GEMESSEN, was wirklich
ankommt. Mit und ohne Pult.
DAS ZWEITE VIDEO war nie gesperrt -- es war nur unsichtbar. Jetzt
stehen Vorschaubild, Titel und die gemerkte Stelle da, "Jetzt wechseln"
auch von hier aus, und aus der Warteschlange legt ein Knopf eines
bereit.
UND EIN FUND AUF DEM BILDSCHIRMFOTO: Das Band "Ton einschalten" lag auf
derselben Hoehe wie die Senderleiste. Bei vier Knoepfen reichte die
Leiste bis zur Mitte -- vom Mikro-Knopf war nur noch ein "t" zu sehen.
Das war schon vorher so; der fuenfte Knopf hat es sichtbar gemacht.
Dieselbe Lehre wie am 06.09.: keine neue Zahl suchen, sondern die
Begegnung unmoeglich machen. mess-reaktion misst das jetzt als
UEBERLAPPUNG.
GEPRUEFT: pruef-reaktion 423 -> 478 (0 Fehler), pruef-spenden 172 -> 215
(0), pruef-reaktion-schmal 44 (0), pruef-tippziele 13 (0), dazu gruen:
pruef-css-klassen, pruef-alle-wege, pruef-haus-trennung, pruef-agentur,
pruef-deutsche-texte. Keine Zahl ist gefallen.
Drei Doppelungen hat erst das Pruefen gefunden: `satz_unbekannt` gab es
zweimal (Muenzsatz), `saetze` im Spendenstand war belegt (ebenfalls
Muenzsaetze), und `glanz_minuten` waere in einem frischen Haus immer 0
geblieben -- die Spalte kam per ALTER TABLE, und das laeuft VOR dem
Anlegen der Werksstufen.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -335,7 +335,7 @@ await roh("/workspace/api/spenden", {
|
|||||||
rumpf: { dogen_mille: 2500, name: "Nachtfalter", gruss: "Gruss an die Buehne" },
|
rumpf: { dogen_mille: 2500, name: "Nachtfalter", gruss: "Gruss an die Buehne" },
|
||||||
});
|
});
|
||||||
await tafelSeite.waitForFunction(
|
await tafelSeite.waitForFunction(
|
||||||
() => document.querySelector('.spendenkarte[data-da="ja"]'), null, { timeout: 12000 },
|
() => document.querySelector('.spendenkarte-auftritt[data-da="ja"] .spendenkarte'), null, { timeout: 12000 },
|
||||||
).catch(() => {});
|
).catch(() => {});
|
||||||
await tafelSeite.waitForTimeout(600);
|
await tafelSeite.waitForTimeout(600);
|
||||||
const karte = await tafelSeite.evaluate(() => {
|
const karte = await tafelSeite.evaluate(() => {
|
||||||
|
|||||||
@@ -269,6 +269,13 @@ for (const stufe of ["vorbereitung", "live"]) {
|
|||||||
await roh("/workspace/api/reaktion/gast", {
|
await roh("/workspace/api/reaktion/gast", {
|
||||||
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 },
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 },
|
||||||
});
|
});
|
||||||
|
/* ZUSAGEN GEHOERT SEIT DEM 08.10.2026 DAZU. Ein Eingeladener steht
|
||||||
|
noch NICHT auf der Buehne -- ohne diesen zweiten Aufruf maesse
|
||||||
|
dieses Werkzeug einen Saal mit einem Kamerafenster statt zweien,
|
||||||
|
und zwar ohne einen einzigen Fehler zu melden. */
|
||||||
|
await roh("/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.gast2, rumpf: { ja: true, kamera: true, mikro: true },
|
||||||
|
});
|
||||||
/* Und ein paar Worte im Chat -- eine leere Schiene kann nicht
|
/* Und ein paar Worte im Chat -- eine leere Schiene kann nicht
|
||||||
ueberlaufen, und genau das waere ein gruener Haken ohne Inhalt. */
|
ueberlaufen, und genau das waere ein gruener Haken ohne Inhalt. */
|
||||||
for (const [wer, text] of REDEN) {
|
for (const [wer, text] of REDEN) {
|
||||||
|
|||||||
+345
-19
@@ -277,6 +277,10 @@ for (const [wer, text] of REDEN) {
|
|||||||
console.log("\n=== LIVE ===");
|
console.log("\n=== LIVE ===");
|
||||||
await roh("/workspace/api/reaktion/stand", { method: "POST", keks: k.admin, rumpf: { stand: "live" } });
|
await roh("/workspace/api/reaktion/stand", { method: "POST", keks: k.admin, rumpf: { stand: "live" } });
|
||||||
await roh("/workspace/api/reaktion/gast", { method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 } });
|
await roh("/workspace/api/reaktion/gast", { method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 } });
|
||||||
|
/* Und die Zusage: Seit dem 08.10.2026 wird GEFRAGT, nicht geholt --
|
||||||
|
wer nur gefragt ist, sendet noch nicht. */
|
||||||
|
await roh("/workspace/api/reaktion/gast/antwort",
|
||||||
|
{ method: "POST", keks: k.gast2, rumpf: { ja: true, kamera: true, mikro: true } });
|
||||||
|
|
||||||
/* ==== BEIDE SEITEN GLEICHZEITIG ====================================
|
/* ==== BEIDE SEITEN GLEICHZEITIG ====================================
|
||||||
Der Host sendet, die Zuschauerin empfaengt -- das geht nur, wenn
|
Der Host sendet, die Zuschauerin empfaengt -- das geht nur, wenn
|
||||||
@@ -785,9 +789,9 @@ await host.seite.waitForTimeout(900);
|
|||||||
Regiespalte stehen sie UNTEREINANDER -- das ist seit dem
|
Regiespalte stehen sie UNTEREINANDER -- das ist seit dem
|
||||||
Umbau „Regie links" der Sinn, nicht ein Fehler. Gefragt
|
Umbau „Regie links" der Sinn, nicht ein Fehler. Gefragt
|
||||||
ist deshalb: Gibt es alle drei, und hat jede Inhalt? */
|
ist deshalb: Gibt es alle drei, und hat jede Inhalt? */
|
||||||
laeuft: k(".regiekachel.kachel--laeuft"),
|
laeuft: k(".regiekachel.regiekachel--laeuft"),
|
||||||
sendung: k(".regiekachel.kachel--sendung"),
|
sendung: k(".regiekachel.regiekachel--sendung"),
|
||||||
bereit: k(".regiekachel.kachel--bereit"),
|
bereit: k(".regiekachel.regiekachel--bereit"),
|
||||||
leiste: k(".transport"),
|
leiste: k(".transport"),
|
||||||
spiel: k("#v-spiel"),
|
spiel: k("#v-spiel"),
|
||||||
/* Laeuft etwas seitlich hinaus? `scrollWidth` groesser als die
|
/* Laeuft etwas seitlich hinaus? `scrollWidth` groesser als die
|
||||||
@@ -825,7 +829,7 @@ await host.seite.waitForTimeout(900);
|
|||||||
Scrollen wie beim Stillstand. */
|
Scrollen wie beim Stillstand. */
|
||||||
letzte: (() => {
|
letzte: (() => {
|
||||||
const e = document.querySelector(".transport");
|
const e = document.querySelector(".transport");
|
||||||
const r = document.querySelector(".regiekachel.kachel--sendung");
|
const r = document.querySelector(".regiekachel.regiekachel--sendung");
|
||||||
if (!e || !r) return false;
|
if (!e || !r) return false;
|
||||||
/* 4 = DOCUMENT_POSITION_FOLLOWING */
|
/* 4 = DOCUMENT_POSITION_FOLLOWING */
|
||||||
return !!(r.compareDocumentPosition(e) & 4);
|
return !!(r.compareDocumentPosition(e) & 4);
|
||||||
@@ -850,10 +854,47 @@ await host.seite.waitForTimeout(900);
|
|||||||
const raus = [];
|
const raus = [];
|
||||||
const leiste = document.querySelector(".transport");
|
const leiste = document.querySelector(".transport");
|
||||||
if (!leiste) return raus;
|
if (!leiste) return raus;
|
||||||
|
/* ==== WAS WEGGEROLLT IST, IST NICHT VERDECKT (08.10.2026)
|
||||||
|
|
||||||
|
Die Regie-Schublade (`#pult-innen`) rollt: Ihr Inhalt ist 1228
|
||||||
|
Pixel hoch, sichtbar sind 342. Alles darunter ist
|
||||||
|
ABGESCHNITTEN -- man rollt es herunter, und dann ist es da.
|
||||||
|
`getBoundingClientRect()` meldet fuer solche Felder trotzdem
|
||||||
|
eine Lage im Fenster, und `elementFromPoint` findet dort die
|
||||||
|
Transportleiste. Die Messung meldete daraufhin „die Leiste
|
||||||
|
liegt ueber drei Bedienelementen" -- bei Feldern, die man nur
|
||||||
|
noch nicht heruntergerollt hat.
|
||||||
|
|
||||||
|
GEFUNDEN DURCH EINEN GEGENLAUF, nicht durch Nachdenken: Am
|
||||||
|
08.10. kam die Warnung neu, der Umbau sah wie die Ursache aus.
|
||||||
|
Ein `git worktree` auf den letzten Commit zeigte dieselbe Lage
|
||||||
|
-- dort lagen die Felder nur zufaellig ein paar Pixel tiefer,
|
||||||
|
unter dem Fensterrand, und `elementFromPoint` gab `null`
|
||||||
|
zurueck. Es war also nie eine Frage der Gestaltung, sondern
|
||||||
|
eine Luecke in der Messung.
|
||||||
|
|
||||||
|
Gefragt wird deshalb zuerst: Liegt das Feld ueberhaupt im
|
||||||
|
sichtbaren Teil seines Rollkastens? Nur dann kann es verdeckt
|
||||||
|
sein. */
|
||||||
|
const rollkasten = (e) => {
|
||||||
|
for (let p = e.parentElement; p; p = p.parentElement) {
|
||||||
|
const c = getComputedStyle(p);
|
||||||
|
if (/(auto|scroll)/.test(c.overflowY) || /(auto|scroll)/.test(c.overflowX)) return p;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
for (const e of document.querySelectorAll("#pult-innen button, #pult-innen input,"
|
for (const e of document.querySelectorAll("#pult-innen button, #pult-innen input,"
|
||||||
+ " #pult-innen select, #pult-innen label")) {
|
+ " #pult-innen select, #pult-innen label")) {
|
||||||
const r = e.getBoundingClientRect();
|
const r = e.getBoundingClientRect();
|
||||||
if (r.width === 0 || r.height === 0) continue;
|
if (r.width === 0 || r.height === 0) continue;
|
||||||
|
const k = rollkasten(e);
|
||||||
|
if (k) {
|
||||||
|
const kr = k.getBoundingClientRect();
|
||||||
|
const mitte = r.top + r.height / 2;
|
||||||
|
/* Ganz oder halb aus dem Rollkasten heraus: weggerollt,
|
||||||
|
nicht verdeckt. */
|
||||||
|
if (mitte < kr.top || mitte > kr.bottom) continue;
|
||||||
|
}
|
||||||
const oben = document.elementFromPoint(r.left + r.width / 2, r.top + r.height / 2);
|
const oben = document.elementFromPoint(r.left + r.width / 2, r.top + r.height / 2);
|
||||||
if (!oben || e === oben || e.contains(oben)) continue;
|
if (!oben || e === oben || e.contains(oben)) continue;
|
||||||
if (!leiste.contains(oben)) continue; /* nur die Leiste zaehlt */
|
if (!leiste.contains(oben)) continue; /* nur die Leiste zaehlt */
|
||||||
@@ -945,6 +986,56 @@ await host.seite.waitForTimeout(900);
|
|||||||
console.log(" ACHTUNG: Der Knopf zum Teilen fehlt oder ist zu klein.");
|
console.log(" ACHTUNG: Der Knopf zum Teilen fehlt oder ist zu klein.");
|
||||||
ausgang = 1;
|
ausgang = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==== NICHTS ÜBER DEM BILD DECKT EINEN KNOPF ZU (08.10.2026) ====
|
||||||
|
|
||||||
|
Über der Leinwand schweben drei Dinge: die Senderleiste (Kamera,
|
||||||
|
Bildschirm, Mikro, Geräte), das Band „Ton einschalten" und die
|
||||||
|
Spendenkarte. Sie liegen alle `absolute` und wissen nichts
|
||||||
|
voneinander.
|
||||||
|
|
||||||
|
GEFUNDEN AUF EINEM BILDSCHIRMFOTO, NICHT IN EINER ZAHL: Das Band
|
||||||
|
stand auf `left: 50%, bottom: 20px`, die Leiste auf `left: 16px,
|
||||||
|
bottom: 16px` — also auf derselben Höhe. Bei vier Knöpfen reichte
|
||||||
|
die Leiste bis zur Mitte, und vom Mikro-Knopf war nur noch ein
|
||||||
|
„t" zu sehen. Es war schon vorher so; mit dem fünften Knopf
|
||||||
|
wurde es nur sichtbar.
|
||||||
|
|
||||||
|
Gemessen wird nicht die Lage, sondern die ÜBERLAPPUNG — dieselbe
|
||||||
|
Form wie bei der Transportleiste. Eine Zahl („das Band muss 78
|
||||||
|
Pixel hoch liegen") wäre wieder die Schwelle, die beim nächsten
|
||||||
|
Knopf niemand nachzieht. */
|
||||||
|
const deckt = await host.seite.evaluate(() => {
|
||||||
|
const stuecke = [
|
||||||
|
...document.querySelectorAll(".senderleiste button"),
|
||||||
|
...document.querySelectorAll(".ton-an"),
|
||||||
|
].map((e) => ({ e, r: e.getBoundingClientRect() }))
|
||||||
|
.filter((x) => x.r.width > 0 && x.r.height > 0);
|
||||||
|
const raus = [];
|
||||||
|
for (let i = 0; i < stuecke.length; i++) {
|
||||||
|
for (let j = i + 1; j < stuecke.length; j++) {
|
||||||
|
const a = stuecke[i].r, b = stuecke[j].r;
|
||||||
|
const quer = Math.min(a.right, b.right) - Math.max(a.left, b.left);
|
||||||
|
const hoch = Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top);
|
||||||
|
if (quer > 1 && hoch > 1) {
|
||||||
|
const n = (x) => x.e.id || x.e.className || x.e.tagName;
|
||||||
|
raus.push(`${n(stuecke[i])} / ${n(stuecke[j])}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { zahl: stuecke.length, raus };
|
||||||
|
});
|
||||||
|
console.log(` Über dem Bild: ${deckt.zahl} Bedienteile, `
|
||||||
|
+ `${deckt.raus.length} Überlappung(en)`);
|
||||||
|
/* DIE ZAHL GEHOERT IN DIE BEDINGUNG. „null Ueberlappungen" ist auch
|
||||||
|
dann wahr, wenn gar nichts gemessen wurde -- und genau so sieht
|
||||||
|
ein gruener Haken aus, der nichts beweist. */
|
||||||
|
if (deckt.zahl < 4 || deckt.raus.length) {
|
||||||
|
console.log(` ACHTUNG: ${deckt.raus.length ? deckt.raus.join(" · ")
|
||||||
|
: "zu wenige Bedienteile gefunden -- die Messung greift ins Leere"}`);
|
||||||
|
ausgang = 1;
|
||||||
|
}
|
||||||
|
|
||||||
await bild(host.seite, "23-regieplatz");
|
await bild(host.seite, "23-regieplatz");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1140,7 +1231,16 @@ await zuschauer.seite.evaluate(() => {
|
|||||||
Versehen. */
|
Versehen. */
|
||||||
muenze: (n.querySelector(".spendenkarte__bild img")
|
muenze: (n.querySelector(".spendenkarte__bild img")
|
||||||
?.getAttribute("src") || "").split("/").pop(),
|
?.getAttribute("src") || "").split("/").pop(),
|
||||||
kleinWeg: n.dataset?.muenze === "ja",
|
/* ==== DIE MARKIERUNG SITZT AN DER KARTE, NICHT AN DER
|
||||||
|
HUELLE (08.10.2026)
|
||||||
|
|
||||||
|
Angehaengt wird seit heute die HUELLE -- sie macht das
|
||||||
|
Erscheinen, die Karte darin die Form. `n.dataset.muenze`
|
||||||
|
fragte also den falschen Knoten und war immer leer:
|
||||||
|
„Die Muenze steht zweimal auf derselben Karte", bei
|
||||||
|
einer Karte, auf der sie genau einmal stand. */
|
||||||
|
kleinWeg: (n.matches?.(".spendenkarte")
|
||||||
|
? n : n.querySelector?.(".spendenkarte"))?.dataset?.muenze === "ja",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1153,7 +1253,7 @@ await roh("/workspace/api/spenden", {
|
|||||||
rumpf: { dogen_mille: 2500, name: "Nachtfalter", gruss: "Fuer das Rudel!" },
|
rumpf: { dogen_mille: 2500, name: "Nachtfalter", gruss: "Fuer das Rudel!" },
|
||||||
});
|
});
|
||||||
await zuschauer.seite.waitForFunction(
|
await zuschauer.seite.waitForFunction(
|
||||||
() => document.querySelector('.spendenkarte[data-da="ja"]'), null, { timeout: 8000 },
|
() => document.querySelector('.spendenkarte-auftritt[data-da="ja"] .spendenkarte'), null, { timeout: 8000 },
|
||||||
).catch(() => {});
|
).catch(() => {});
|
||||||
await zuschauer.seite.waitForTimeout(700);
|
await zuschauer.seite.waitForTimeout(700);
|
||||||
await bild(zuschauer.seite, "10-spendenkarte");
|
await bild(zuschauer.seite, "10-spendenkarte");
|
||||||
@@ -1477,13 +1577,13 @@ if (!wartet) {
|
|||||||
naechste kommt erst, wenn die vorige abgelaufen ist. Also auf
|
naechste kommt erst, wenn die vorige abgelaufen ist. Also auf
|
||||||
das Merkmal warten, das nur die neue hat. */
|
das Merkmal warten, das nur die neue hat. */
|
||||||
await host.seite.waitForFunction(
|
await host.seite.waitForFunction(
|
||||||
() => [...document.querySelectorAll('.spendenkarte[data-da="ja"]')].some(
|
() => [...document.querySelectorAll('.spendenkarte-auftritt[data-da="ja"] .spendenkarte')].some(
|
||||||
(k2) => k2.querySelector(".spendenkarte__wer")?.textContent === "Probe"
|
(k2) => k2.querySelector(".spendenkarte__wer")?.textContent === "Probe"
|
||||||
&& k2.querySelector(".spendenkarte__bild img")),
|
&& k2.querySelector(".spendenkarte__bild img")),
|
||||||
null, { timeout: 20000 },
|
null, { timeout: 20000 },
|
||||||
).catch(() => {});
|
).catch(() => {});
|
||||||
const nachWechsel = await host.seite.evaluate(() => {
|
const nachWechsel = await host.seite.evaluate(() => {
|
||||||
const k2 = [...document.querySelectorAll('.spendenkarte[data-da="ja"]')]
|
const k2 = [...document.querySelectorAll('.spendenkarte-auftritt[data-da="ja"] .spendenkarte')]
|
||||||
.find((x) => x.querySelector(".spendenkarte__wer")?.textContent === "Probe");
|
.find((x) => x.querySelector(".spendenkarte__wer")?.textContent === "Probe");
|
||||||
const b = k2?.querySelector(".spendenkarte__bild img");
|
const b = k2?.querySelector(".spendenkarte__bild img");
|
||||||
/* Und auch hier: geladen, nicht nur vorhanden. */
|
/* Und auch hier: geladen, nicht nur vorhanden. */
|
||||||
@@ -1966,6 +2066,12 @@ await host.seite.waitForTimeout(1200);
|
|||||||
const tafelnLeeren = async () => {
|
const tafelnLeeren = async () => {
|
||||||
for (const s2 of [host.seite, zuschauer.seite]) {
|
for (const s2 of [host.seite, zuschauer.seite]) {
|
||||||
await s2.evaluate(() => {
|
await s2.evaluate(() => {
|
||||||
|
/* Die HUELLE wegnehmen und nicht nur die Karte darin: Seit dem
|
||||||
|
08.10.2026 macht die Huelle das Erscheinen, die Karte nur die
|
||||||
|
Form. Wer nur die Karte entfernt, laesst eine leere Huelle
|
||||||
|
stehen -- und misst gleich darauf, ob „schon eine Karte da
|
||||||
|
ist", mit einem Rest der vorigen im Bild. */
|
||||||
|
for (const k2 of document.querySelectorAll(".spendenkarte-auftritt")) k2.remove();
|
||||||
for (const k2 of document.querySelectorAll(".spendenkarte")) k2.remove();
|
for (const k2 of document.querySelectorAll(".spendenkarte")) k2.remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1993,10 +2099,27 @@ const messeKarte = async (erwartet) => {
|
|||||||
Sonst koennte die vorige Probe die Antwort geben, und die
|
Sonst koennte die vorige Probe die Antwort geben, und die
|
||||||
Messung bestaetigte eine Aenderung, die gar nicht
|
Messung bestaetigte eine Aenderung, die gar nicht
|
||||||
angekommen ist. */
|
angekommen ist. */
|
||||||
|
/* ==== GEWARTET WIRD AUF DEN FAKTOR, NICHT AUF EINE PIXELZAHL
|
||||||
|
(geaendert 08.10.2026)
|
||||||
|
|
||||||
|
Hier stand „warte, bis die Schrift 16 bzw. 32 Pixel misst". Das
|
||||||
|
war die Grundgroesse der Karte AM RAND. Seit heute steht sie in
|
||||||
|
der Mitte und ist dort groesser (1,3rem statt 1rem) -- und damit
|
||||||
|
wartete die Messung auf eine Zahl, die es nicht mehr gibt, lief
|
||||||
|
in die Frist und meldete „Die Probe zeigt keine Karte". Die
|
||||||
|
Karte war die ganze Zeit da.
|
||||||
|
|
||||||
|
DAS IST DIESELBE FALLE WIE EINE FESTE SCHWELLE IM STILBLATT:
|
||||||
|
eine Zahl, die irgendwo anders entsteht, hier abgeschrieben.
|
||||||
|
`--sp-gross` ist der Wert, um den es geht -- er kommt von der
|
||||||
|
Stufe, und die Messung fragt jetzt genau ihn ab. Wie viele
|
||||||
|
Pixel daraus werden, entscheidet die Gestaltung und darf sich
|
||||||
|
aendern. */
|
||||||
await host.seite.waitForFunction(
|
await host.seite.waitForFunction(
|
||||||
(soll) => [...document.querySelectorAll('.spendenkarte[data-da="ja"]')].some((k2) =>
|
(soll) => [...document.querySelectorAll('.spendenkarte-auftritt[data-da="ja"] .spendenkarte')]
|
||||||
k2.querySelector(".spendenkarte__wer")?.textContent === "Probe"
|
.some((k2) => k2.querySelector(".spendenkarte__wer")?.textContent === "Probe"
|
||||||
&& Math.abs(parseFloat(getComputedStyle(k2).fontSize) - soll) < 0.5),
|
&& Math.abs(parseFloat(
|
||||||
|
getComputedStyle(k2).getPropertyValue("--sp-gross")) - soll) < 0.01),
|
||||||
erwartet, { timeout: 16000 },
|
erwartet, { timeout: 16000 },
|
||||||
).catch(() => {});
|
).catch(() => {});
|
||||||
/* DIE KARTE KOMMT VON LINKS HEREIN (450 ms). Wer sofort misst,
|
/* DIE KARTE KOMMT VON LINKS HEREIN (450 ms). Wer sofort misst,
|
||||||
@@ -2012,7 +2135,7 @@ const messeKarte = async (erwartet) => {
|
|||||||
-- gemessen wurden dadurch 413 statt 430 Pixel (genau das
|
-- gemessen wurden dadurch 413 statt 430 Pixel (genau das
|
||||||
0,96-fache) und ein linker Rand von -1. Beides war kein
|
0,96-fache) und ein linker Rand von -1. Beides war kein
|
||||||
Fehler der Karte, sondern ein Blick zur falschen Zeit. */
|
Fehler der Karte, sondern ein Blick zur falschen Zeit. */
|
||||||
const k2 = [...document.querySelectorAll('.spendenkarte[data-da="ja"]')]
|
const k2 = [...document.querySelectorAll('.spendenkarte-auftritt[data-da="ja"] .spendenkarte')]
|
||||||
.find((x) => x.querySelector(".spendenkarte__wer")?.textContent === "Probe");
|
.find((x) => x.querySelector(".spendenkarte__wer")?.textContent === "Probe");
|
||||||
if (!k2) return null;
|
if (!k2) return null;
|
||||||
const r = k2.getBoundingClientRect();
|
const r = k2.getBoundingClientRect();
|
||||||
@@ -2036,7 +2159,7 @@ const messeKarte = async (erwartet) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const kKlein = await messeKarte(16);
|
const kKlein = await messeKarte(1);
|
||||||
console.log(` Größe 1: Karte ${kKlein?.breit}x${kKlein?.hoch} px, Schrift ${kKlein?.schrift} px, `
|
console.log(` Größe 1: Karte ${kKlein?.breit}x${kKlein?.hoch} px, Schrift ${kKlein?.schrift} px, `
|
||||||
+ `Betrag „${kKlein?.betragText}" bei ${kKlein?.betragSchrift} px, Stufe „${kKlein?.stufe}"`);
|
+ `Betrag „${kKlein?.betragText}" bei ${kKlein?.betragSchrift} px, Stufe „${kKlein?.stufe}"`);
|
||||||
if (!kKlein || kKlein.wer !== "Probe") {
|
if (!kKlein || kKlein.wer !== "Probe") {
|
||||||
@@ -2065,7 +2188,7 @@ await host.seite.evaluate(() => {
|
|||||||
document.getElementById("stufen-sichern").click();
|
document.getElementById("stufen-sichern").click();
|
||||||
});
|
});
|
||||||
await host.seite.waitForTimeout(1400);
|
await host.seite.waitForTimeout(1400);
|
||||||
const kGross = await messeKarte(32);
|
const kGross = await messeKarte(2);
|
||||||
console.log(` Größe 2: Karte ${kGross?.breit}x${kGross?.hoch} px, Schrift ${kGross?.schrift} px, `
|
console.log(` Größe 2: Karte ${kGross?.breit}x${kGross?.hoch} px, Schrift ${kGross?.schrift} px, `
|
||||||
+ `Betrag bei ${kGross?.betragSchrift} px, links ${kGross?.links} / oben ${kGross?.oben}, `
|
+ `Betrag bei ${kGross?.betragSchrift} px, links ${kGross?.links} / oben ${kGross?.oben}, `
|
||||||
+ `ganz im Bild=${kGross?.imBild}`);
|
+ `ganz im Bild=${kGross?.imBild}`);
|
||||||
@@ -2100,7 +2223,7 @@ if (!kGross || !kKlein) {
|
|||||||
|
|
||||||
/* ---- Und die Farbe? ---- */
|
/* ---- Und die Farbe? ---- */
|
||||||
const farbe = await host.seite.evaluate(() => {
|
const farbe = await host.seite.evaluate(() => {
|
||||||
const k2 = [...document.querySelectorAll('.spendenkarte[data-da="ja"]')]
|
const k2 = [...document.querySelectorAll('.spendenkarte-auftritt[data-da="ja"] .spendenkarte')]
|
||||||
.find((x) => x.querySelector(".spendenkarte__wer")?.textContent === "Probe");
|
.find((x) => x.querySelector(".spendenkarte__wer")?.textContent === "Probe");
|
||||||
return k2 ? getComputedStyle(k2).getPropertyValue("--sp-farbe").trim() : "";
|
return k2 ? getComputedStyle(k2).getPropertyValue("--sp-farbe").trim() : "";
|
||||||
});
|
});
|
||||||
@@ -2161,6 +2284,34 @@ if (tempoKnoepfe.length !== 6 || tempoKnoepfe.some((t) => t.breit < 44)) {
|
|||||||
ausgang = 1;
|
ausgang = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==== ERST AN DEN ANFANG, DANN MESSEN (08.10.2026) ================
|
||||||
|
|
||||||
|
Diese Messung braucht zwoelf Sekunden Videomaterial -- sechs bei
|
||||||
|
einfachem und sechs bei doppeltem Tempo, und bei doppeltem sind
|
||||||
|
das zwoelf Sekunden Film. Das Testvideo ist 3:34 lang, und was
|
||||||
|
davon noch uebrig ist, haengt davon ab, wie lange alle Abschnitte
|
||||||
|
davor gebraucht haben.
|
||||||
|
|
||||||
|
GENAU DAS HAT SIE FLATTERN LASSEN: Am 08.10. meldete sie in zwei
|
||||||
|
von vier Laeufen „Die Geschwindigkeit wirkt nicht" -- einmal mit
|
||||||
|
„2x: 0.00", einmal mit „2x: 0.50". Beides heisst nicht „zu
|
||||||
|
langsam", sondern „das Video war zu Ende". Im Gegenlauf auf dem
|
||||||
|
letzten Commit war es gruen, und auch das war Zufall: Dort lag der
|
||||||
|
Spieler zufaellig weit genug vorn.
|
||||||
|
|
||||||
|
Eine Pruefung, deren Ergebnis davon abhaengt, wie schnell der
|
||||||
|
Rechner die Abschnitte davor abgearbeitet hat, misst den Rechner.
|
||||||
|
Also: vorher an den Anfang springen. Dann sind immer 3:34
|
||||||
|
uebrig. */
|
||||||
|
await host.seite.evaluate(() => {
|
||||||
|
const band = document.getElementById("v-band");
|
||||||
|
if (!band) return;
|
||||||
|
band.value = "20"; /* 2 % von 3:34 ~ 4 s */
|
||||||
|
band.dispatchEvent(new Event("input", { bubbles: true }));
|
||||||
|
band.dispatchEvent(new Event("change", { bubbles: true }));
|
||||||
|
});
|
||||||
|
await host.seite.waitForTimeout(1500);
|
||||||
|
|
||||||
/* NORMALES TEMPO ZUERST MESSEN -- als Bezugswert. Ohne ihn wüsste man
|
/* NORMALES TEMPO ZUERST MESSEN -- als Bezugswert. Ohne ihn wüsste man
|
||||||
nicht, ob 1,5x wirklich schneller ist oder ob das Video einfach
|
nicht, ob 1,5x wirklich schneller ist oder ob das Video einfach
|
||||||
schon lief. */
|
schon lief. */
|
||||||
@@ -2188,7 +2339,15 @@ const normal = (a1 !== null && a2 !== null) ? (a2 - a1) / 6 : null;
|
|||||||
const schnell = (b1 !== null && b2 !== null) ? (b2 - b1) / 6 : null;
|
const schnell = (b1 !== null && b2 !== null) ? (b2 - b1) / 6 : null;
|
||||||
console.log(` 1x: ${normal === null ? "?" : normal.toFixed(2)} Sekunden je Sekunde · `
|
console.log(` 1x: ${normal === null ? "?" : normal.toFixed(2)} Sekunden je Sekunde · `
|
||||||
+ `2x: ${schnell === null ? "?" : schnell.toFixed(2)}`);
|
+ `2x: ${schnell === null ? "?" : schnell.toFixed(2)}`);
|
||||||
if (normal === null || schnell === null || schnell < normal * 1.5) {
|
/* UND DIE BEDINGUNG NENNT, WAS SIE GEMESSEN HAT. „schnell < normal *
|
||||||
|
1,5" ist auch dann wahr, wenn beide null sind -- also wenn der
|
||||||
|
Spieler ueberhaupt nicht lief. Das ist ein anderer Befund als
|
||||||
|
„das Tempo wirkt nicht", und er braucht einen anderen Satz. */
|
||||||
|
if (normal === null || schnell === null || normal < 0.5) {
|
||||||
|
console.log(" KONNTE NICHT NACHSEHEN: Das Video lief waehrend der Messung nicht "
|
||||||
|
+ `(1x: ${normal === null ? "?" : normal.toFixed(2)}). Das sagt nichts ueber das Tempo.`);
|
||||||
|
offenePunkte.push("Das Tempo war nicht messbar -- das Video lief nicht.");
|
||||||
|
} else if (schnell < normal * 1.5) {
|
||||||
console.log(" ACHTUNG: Die Geschwindigkeit wirkt nicht -- das Video laeuft gleich schnell.");
|
console.log(" ACHTUNG: Die Geschwindigkeit wirkt nicht -- das Video laeuft gleich schnell.");
|
||||||
ausgang = 1;
|
ausgang = 1;
|
||||||
}
|
}
|
||||||
@@ -2373,10 +2532,32 @@ if (nachHin.titel === nachZurueck.titel) {
|
|||||||
console.log(" ACHTUNG: Der Umschalter wechselt nicht.");
|
console.log(" ACHTUNG: Der Umschalter wechselt nicht.");
|
||||||
ausgang = 1;
|
ausgang = 1;
|
||||||
}
|
}
|
||||||
/* Die gemerkte Stelle: etwa dort weiter, wo es aufgehoert hat --
|
/* ==== DIE GEMERKTE STELLE -- UND WARUM NUR NACH UNTEN GEPRUEFT WIRD
|
||||||
sechs Sekunden Spiel fuer das Laden des Videos. */
|
(praezisiert 08.10.2026)
|
||||||
|
|
||||||
|
Hier stand `Math.abs(nachher - vorher) > 8`. Das misst zwei Dinge
|
||||||
|
auf einmal: ob die Stelle gemerkt wurde UND wie lange diese
|
||||||
|
Messung zwischendurch gewartet hat. Sie wartet 2x3 Sekunden, und
|
||||||
|
danach laeuft das zurueckgeholte Video ganz richtig WEITER --
|
||||||
|
gemessen wurden deshalb 86 -> 95, und die Pruefung nannte das
|
||||||
|
„verloren".
|
||||||
|
|
||||||
|
Im Gegenlauf auf dem letzten Commit stand dieselbe Zahl bei
|
||||||
|
213 -> 213, und das sah nach „alles in Ordnung" aus. Es war
|
||||||
|
Zufall: Das Video stand dort bei 213 von 214 Sekunden, also am
|
||||||
|
Ende, und konnte gar nicht weiterlaufen. Eine Pruefung, die nur
|
||||||
|
am Ende eines Videos gruen ist, prueft den Spieler und nicht die
|
||||||
|
Software.
|
||||||
|
|
||||||
|
WAS WIRKLICH SCHIEFGEHEN KANN, geht nach UNTEN: Die Stelle wird
|
||||||
|
vergessen (zurueck auf 0) oder es wird die Stelle des ANDEREN
|
||||||
|
Videos genommen (hier wenige Sekunden). Beides liegt deutlich
|
||||||
|
unter dem gemerkten Wert. Nach oben ist Weiterlaufen der
|
||||||
|
Normalfall; die Obergrenze bleibt nur als Netz gegen einen Sprung
|
||||||
|
ins Nichts. */
|
||||||
if (stelleVorher === null || stelleNachher === null
|
if (stelleVorher === null || stelleNachher === null
|
||||||
|| Math.abs(stelleNachher - stelleVorher) > 8) {
|
|| stelleNachher < stelleVorher - 2
|
||||||
|
|| stelleNachher > stelleVorher + 30) {
|
||||||
console.log(` ACHTUNG: Die gemerkte Stelle ging verloren `
|
console.log(` ACHTUNG: Die gemerkte Stelle ging verloren `
|
||||||
+ `(${stelleVorher} -> ${stelleNachher}).`);
|
+ `(${stelleVorher} -> ${stelleNachher}).`);
|
||||||
ausgang = 1;
|
ausgang = 1;
|
||||||
@@ -2760,6 +2941,151 @@ await roh(`/workspace/api/reaktion/massnahme/${IDS.gast}`, { method: "DELETE", k
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DER VORRAUM FUER EINGELADENE GAESTE (08.10.2026)
|
||||||
|
|
||||||
|
Filipe: „wenn gäste eingeladen werden, sollen die akzeptieren oder
|
||||||
|
ablehnen können. bevor die auch angezeigt werden sollen die
|
||||||
|
auswählen können ob die kamera an ist oder aus ist."
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
WARUM DAS HIER GEMESSEN WIRD UND NICHT NUR IN `pruef-reaktion`
|
||||||
|
|
||||||
|
Dort ist der ganze Weg geprueft -- fragen, zusagen, ablehnen,
|
||||||
|
Frist, Kameravorwahl. Was dort NICHT geprueft werden kann, ist, ob
|
||||||
|
der Vorhang auf dem Bildschirm auch wirklich erscheint. Ein
|
||||||
|
Zustand im Server, den die Seite nicht zeigt, ist fuer den
|
||||||
|
Gefragten dasselbe wie keine Einladung: Er sieht nichts, sagt
|
||||||
|
nichts, und der Host wartet zwei Minuten.
|
||||||
|
|
||||||
|
Deshalb wird hier gemessen, was ein Mensch sieht: Steht der
|
||||||
|
Vorhang da? Hat er BEIDE Ausgaenge? Laeuft das eigene Bild darin?
|
||||||
|
Und bringt „Dabei sein" ihn wirklich auf die Buehne?
|
||||||
|
===================================================================== */
|
||||||
|
console.log("");
|
||||||
|
console.log("=== Der Vorraum fuer eingeladene Gaeste ===");
|
||||||
|
{
|
||||||
|
/* Der Zuschauer war eben aus der Sendung genommen und
|
||||||
|
zurueckgeholt -- sein Vorhang steht noch (siehe der Abschnitt
|
||||||
|
darueber). Also neu laden, so wie es ein Mensch auch taete. */
|
||||||
|
await zuschauer.seite.reload({ waitUntil: "networkidle" });
|
||||||
|
await zuschauer.seite.waitForTimeout(900);
|
||||||
|
|
||||||
|
/* PLATZ SCHAFFEN. Die Buehne hat zwei Plaetze, und aus frueheren
|
||||||
|
Abschnitten steht dort noch jemand. Eine Einladung, die mit
|
||||||
|
„gaeste_voll" abgelehnt wird, maesse nichts ueber den Vorraum. */
|
||||||
|
const vorher = await roh("/workspace/api/reaktion", { keks: k.admin });
|
||||||
|
for (const g of (vorher.j?.gaeste || [])) {
|
||||||
|
await roh(`/workspace/api/reaktion/gast/${g.id}`, { method: "DELETE", keks: k.admin });
|
||||||
|
}
|
||||||
|
|
||||||
|
const ein = await roh("/workspace/api/reaktion/gast", {
|
||||||
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast },
|
||||||
|
});
|
||||||
|
console.log(` Eingeladen: ${ein.code} (${(ein.j?.einladungen || []).length} offene Frage)`);
|
||||||
|
|
||||||
|
await zuschauer.seite.waitForFunction(
|
||||||
|
() => { const v = document.getElementById("vorraum"); return !!v && !v.hidden; },
|
||||||
|
null, { timeout: 15000 },
|
||||||
|
).catch(() => {});
|
||||||
|
await zuschauer.seite.waitForTimeout(600);
|
||||||
|
|
||||||
|
const vr = await zuschauer.seite.evaluate(() => {
|
||||||
|
const v = document.getElementById("vorraum");
|
||||||
|
if (!v || v.hidden) return { da: false };
|
||||||
|
const sicht = (e) => {
|
||||||
|
if (!e) return null;
|
||||||
|
const r = e.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
b: Math.round(r.width), h: Math.round(r.height),
|
||||||
|
imBild: r.width > 0 && r.height > 0 && r.top >= -1 && r.left >= -1
|
||||||
|
&& r.bottom <= window.innerHeight + 1 && r.right <= window.innerWidth + 1,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const vid = document.getElementById("vorraum-video");
|
||||||
|
return {
|
||||||
|
da: true,
|
||||||
|
/* DECKT ER WIRKLICH ALLES ZU? Ein Vorhang, durch den man den
|
||||||
|
Saal weiterbedienen kann, ist keiner -- und ausgerechnet
|
||||||
|
hier soll man nicht nebenbei etwas anderes anklicken. */
|
||||||
|
ueberAllem: (() => {
|
||||||
|
const e = document.elementFromPoint(window.innerWidth / 2, 12);
|
||||||
|
return !!e && (e === v || v.contains(e));
|
||||||
|
})(),
|
||||||
|
ja: sicht(document.getElementById("vorraum-ja")),
|
||||||
|
nein: sicht(document.getElementById("vorraum-nein")),
|
||||||
|
kamera: sicht(document.getElementById("vorraum-kamera")),
|
||||||
|
mikro: sicht(document.getElementById("vorraum-mikro")),
|
||||||
|
/* LAEUFT DAS EIGENE BILD? `videoWidth` ist die einzige ehrliche
|
||||||
|
Antwort -- ein `<video>` ohne Strom steht genauso im
|
||||||
|
Dokument wie eines mit. */
|
||||||
|
bild: vid ? { breit: vid.videoWidth, laeuft: !vid.paused } : null,
|
||||||
|
satz: document.getElementById("vorraum-satz")?.textContent?.trim().slice(0, 60) || "",
|
||||||
|
frist: document.getElementById("vorraum-frist")?.textContent?.trim() || "",
|
||||||
|
geraete: document.querySelectorAll("#vorraum-geraete select").length,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
console.log(` Vorhang: da=${vr.da} ueberAllem=${vr.ueberAllem} · `
|
||||||
|
+ `„Dabei sein" ${vr.ja?.b}x${vr.ja?.h} · „Lieber nicht" ${vr.nein?.b}x${vr.nein?.h}`);
|
||||||
|
console.log(` Eigenes Bild: ${vr.bild?.breit} px, laeuft=${vr.bild?.laeuft} · `
|
||||||
|
+ `${vr.geraete} Geraetelisten · ${vr.frist}`);
|
||||||
|
await bild(zuschauer.seite, "24-vorraum");
|
||||||
|
|
||||||
|
/* ZWEI AUSGAENGE, BEIDE ANFASSBAR, BEIDE AUF HAUSGROESSE. Ein
|
||||||
|
Vorhang mit nur einem Weg hinaus ist keine Frage, sondern eine
|
||||||
|
Huerde -- und er stuende vor jemandem, der nur zuschauen
|
||||||
|
wollte. */
|
||||||
|
if (!vr.da || !vr.ueberAllem
|
||||||
|
|| !vr.ja?.imBild || !vr.nein?.imBild
|
||||||
|
|| (vr.ja?.h || 0) < 44 || (vr.nein?.h || 0) < 44
|
||||||
|
|| !vr.kamera?.imBild || !vr.mikro?.imBild) {
|
||||||
|
console.log(" ACHTUNG: Der Vorraum fehlt, deckt nicht zu, oder einer seiner "
|
||||||
|
+ "zwei Ausgaenge ist nicht da.");
|
||||||
|
ausgang = 1;
|
||||||
|
}
|
||||||
|
/* DAS BILD IST DER SINN DER SACHE. Ohne es waere der Vorraum eine
|
||||||
|
Frage ohne die Auskunft, die man zum Antworten braucht. */
|
||||||
|
if (!vr.bild || !vr.bild.breit) {
|
||||||
|
console.log(" ACHTUNG: Im Vorraum laeuft kein eigenes Bild.");
|
||||||
|
ausgang = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Kamera abwaehlen und zusagen ---- */
|
||||||
|
await zuschauer.seite.click("#vorraum-kamera").catch(() => {});
|
||||||
|
await zuschauer.seite.waitForTimeout(300);
|
||||||
|
const nachKlick = await zuschauer.seite.evaluate(() => ({
|
||||||
|
wort: document.getElementById("vorraum-kamera")?.textContent?.trim(),
|
||||||
|
schild: !document.getElementById("vorraum-aus")?.hidden,
|
||||||
|
}));
|
||||||
|
console.log(` Kamera abgewaehlt: „${nachKlick.wort}", Schild im Bild=${nachKlick.schild}`);
|
||||||
|
if (nachKlick.wort !== "Kamera aus" || !nachKlick.schild) {
|
||||||
|
console.log(" ACHTUNG: Die Kamera laesst sich im Vorraum nicht abwaehlen.");
|
||||||
|
ausgang = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
await zuschauer.seite.click("#vorraum-ja").catch(() => {});
|
||||||
|
await zuschauer.seite.waitForTimeout(1500);
|
||||||
|
const danach = await roh("/workspace/api/reaktion", { keks: k.admin });
|
||||||
|
const alsGast = (danach.j?.gaeste || []).find((g) => g.id === IDS.gast);
|
||||||
|
const zu = await zuschauer.seite.evaluate(() =>
|
||||||
|
!!document.getElementById("vorraum")?.hidden);
|
||||||
|
console.log(` Nach „Dabei sein": auf der Buehne=${!!alsGast}, `
|
||||||
|
+ `Kamera aus=${alsGast?.kamera_aus}, Vorhang zu=${zu}`);
|
||||||
|
/* DIE VORWAHL MUSS AM SERVER ANKOMMEN. Nur im Browser gegolten
|
||||||
|
hiesse: Der ganze Saal sieht ein schwarzes Fenster ohne
|
||||||
|
Beschriftung, und der Gast glaubt, seine Kamera sei aus,
|
||||||
|
waehrend sein Bild hinausgeht. */
|
||||||
|
if (!alsGast || alsGast.kamera_aus !== true || !zu) {
|
||||||
|
console.log(" ACHTUNG: Die Zusage kommt nicht an oder die Kameravorwahl geht verloren.");
|
||||||
|
ausgang = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Und wieder aufraeumen -- die folgenden Abschnitte erwarten einen
|
||||||
|
Zuschauer und keinen Gast. */
|
||||||
|
await roh(`/workspace/api/reaktion/gast/${IDS.gast}`, { method: "DELETE", keks: k.admin });
|
||||||
|
await zuschauer.seite.waitForTimeout(500);
|
||||||
|
}
|
||||||
|
|
||||||
/* =====================================================================
|
/* =====================================================================
|
||||||
DIE WERBEEINBLENDUNG -- beim Zuschauer, nicht beim Host
|
DIE WERBEEINBLENDUNG -- beim Zuschauer, nicht beim Host
|
||||||
===================================================================== */
|
===================================================================== */
|
||||||
|
|||||||
@@ -350,6 +350,22 @@ for (const [breite, hoehe, wie] of GERAETE) {
|
|||||||
await seite.waitForTimeout(300);
|
await seite.waitForTimeout(300);
|
||||||
const hinweisLage = await seite.evaluate(() => {
|
const hinweisLage = await seite.evaluate(() => {
|
||||||
const f = document.getElementById("fehler");
|
const f = document.getElementById("fehler");
|
||||||
|
/* ==== NOCH EINMAL SICHTBAR MACHEN -- GEGEN EINEN WETTLAUF
|
||||||
|
(08.10.2026)
|
||||||
|
|
||||||
|
Diese Pruefung meldete am 08.10. einmal „0 px" und beim
|
||||||
|
naechsten Lauf 62 px, bei unveraendertem Code. Ein Ergebnis,
|
||||||
|
das zwischen zwei Laeufen springt, ist zuerst als Wettlauf
|
||||||
|
verdaechtig und nicht als Fund -- und so war es auch:
|
||||||
|
`sagFehler()` in der Seite setzt beim Anzeigen eine Uhr, die
|
||||||
|
das Feld nach sechs Sekunden wieder versteckt. Lief vorher
|
||||||
|
irgendwo eine solche Meldung, fiel ihre Uhr in genau diese
|
||||||
|
300 Millisekunden, und gemessen wurde ein unsichtbares Feld.
|
||||||
|
|
||||||
|
Die Frage dieser Pruefung ist „ist der Hinweis lesbar, WENN er
|
||||||
|
erscheint" -- also wird er hier noch einmal aufgedeckt. Das
|
||||||
|
entfernt den Zufall, ohne die Frage zu aendern. */
|
||||||
|
f.hidden = false;
|
||||||
const r = f.getBoundingClientRect();
|
const r = f.getBoundingClientRect();
|
||||||
const mitte = document.elementFromPoint(
|
const mitte = document.elementFromPoint(
|
||||||
Math.min(innerWidth - 1, Math.max(0, r.left + r.width / 2)),
|
Math.min(innerWidth - 1, Math.max(0, r.left + r.width / 2)),
|
||||||
|
|||||||
+350
-6
@@ -401,22 +401,126 @@ melde("=== 6. Ein bis zwei Gaeste ===");
|
|||||||
const { GAESTE_MAX } = await import("./reaktion-tabellen.js");
|
const { GAESTE_MAX } = await import("./reaktion-tabellen.js");
|
||||||
ok(GAESTE_MAX === 2, `zwei Plaetze, wie in der Notiz (${GAESTE_MAX})`);
|
ok(GAESTE_MAX === 2, `zwei Plaetze, wie in der Notiz (${GAESTE_MAX})`);
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
SEIT DEM 08.10.2026 WIRD GEFRAGT, NICHT GEHOLT
|
||||||
|
|
||||||
|
Filipe: „wenn gäste eingeladen werden, sollen die akzeptieren
|
||||||
|
oder ablehnen können. bevor die auch angezeigt werden sollen die
|
||||||
|
auswählen können ob die kamera an ist oder aus ist."
|
||||||
|
|
||||||
|
Diese Pruefung hiess vorher „Gast 1 dazu" und erwartete nach
|
||||||
|
EINEM Aufruf einen Gast auf der Buehne. Genau das darf jetzt
|
||||||
|
nicht mehr passieren -- und sie ist rot geworden, als es nicht
|
||||||
|
mehr passierte. Das ist der Fall, fuer den sie da ist.
|
||||||
|
===================================================================== */
|
||||||
const a = await roh(CREW, "/workspace/api/reaktion/gast", {
|
const a = await roh(CREW, "/workspace/api/reaktion/gast", {
|
||||||
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast },
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast },
|
||||||
});
|
});
|
||||||
ok(a.code === 201 && a.j?.gaeste?.length === 1, `Gast 1 dazu (${a.code})`);
|
ok(a.code === 201, `Gast 1 eingeladen (${a.code})`);
|
||||||
ok(a.j.gaeste[0].platz === 1, `er bekommt Platz 1 (${a.j?.gaeste?.[0]?.platz})`);
|
ok((a.j?.gaeste || []).length === 0,
|
||||||
|
`und steht NICHT auf der Buehne, bevor er ja gesagt hat (${a.j?.gaeste?.length})`);
|
||||||
|
ok((a.j?.einladungen || []).some((e) => e.id === IDS.gast && e.stand === "gefragt"),
|
||||||
|
"der Host sieht die offene Frage");
|
||||||
|
ok((a.j?.einladungen || [])[0]?.noch_sek > 0,
|
||||||
|
`und wie lange sie noch gilt (${a.j?.einladungen?.[0]?.noch_sek}s)`);
|
||||||
|
|
||||||
|
/* ==== DER GEFRAGTE WEISS ES -- UND SONST NIEMAND ============== */
|
||||||
|
const gLage = await roh(CREW, "/workspace/api/reaktion", { keks: k.gast });
|
||||||
|
ok(gLage.j?.ich?.einladung?.noch_sek > 0,
|
||||||
|
"der Gefragte bekommt seine Einladung mit Restzeit");
|
||||||
|
ok(gLage.j?.ich?.gast === false,
|
||||||
|
"er ist dabei aber noch KEIN Gast");
|
||||||
|
ok(gLage.j?.einladungen === undefined,
|
||||||
|
"und er sieht die Liste der Einladungen nicht (die gehoert dem Host)");
|
||||||
|
const fremd = await roh(CREW, "/workspace/api/reaktion", { keks: k.gast2 });
|
||||||
|
ok(!fremd.j?.ich?.einladung,
|
||||||
|
"wer nicht gefragt wurde, hat auch keine Einladung");
|
||||||
|
ok(fremd.j?.einladungen === undefined,
|
||||||
|
"und erfaehrt nicht, dass jemand anderes gefragt wurde");
|
||||||
|
|
||||||
|
/* ==== EIN GEFRAGTER SENDET NOCH NICHT =========================
|
||||||
|
Die wichtigste Pruefung dieses Abschnitts: Solange er nicht
|
||||||
|
zugesagt hat, darf er nichts schalten -- sonst waere „gefragt"
|
||||||
|
nur ein anderes Wort fuer „dabei". */
|
||||||
|
const fruehSenden = await roh(CREW, "/workspace/api/reaktion/senden", {
|
||||||
|
method: "POST", keks: k.gast, rumpf: { kamera_aus: true },
|
||||||
|
});
|
||||||
|
ok(fruehSenden.code === 403,
|
||||||
|
`wer nur gefragt ist, sendet nicht (${fruehSenden.code})`);
|
||||||
|
|
||||||
|
/* ==== DIE ZUSAGE BRINGT IHN AUF DIE BUEHNE -- MIT KAMERA AUS == */
|
||||||
|
const ja = await roh(CREW, "/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.gast, rumpf: { ja: true, kamera: false, mikro: true },
|
||||||
|
});
|
||||||
|
ok(ja.code === 200 && (ja.j?.gaeste || []).length === 1,
|
||||||
|
`nach der Zusage steht er auf der Buehne (${ja.code})`);
|
||||||
|
ok(ja.j?.gaeste?.[0]?.platz === 1, `er bekommt Platz 1 (${ja.j?.gaeste?.[0]?.platz})`);
|
||||||
|
/* DIE VORWAHL MUSS AM SERVER ANGEKOMMEN SEIN. Haette sie nur im
|
||||||
|
Browser gegolten, saehe der ganze Saal ein schwarzes Fenster
|
||||||
|
ohne Beschriftung -- und der Gast glaubte, seine Kamera sei
|
||||||
|
aus, waehrend sein Bild hinausgeht. */
|
||||||
|
ok(ja.j?.gaeste?.[0]?.kamera_aus === true,
|
||||||
|
"seine Kamera ist aus, weil er sie abgewaehlt hat");
|
||||||
|
ok(ja.j?.gaeste?.[0]?.mikro_aus === false,
|
||||||
|
"sein Mikro ist an, weil er es angelassen hat");
|
||||||
|
ok((ja.j?.einladungen || []).length === 0,
|
||||||
|
"die beantwortete Einladung ist aus der Liste");
|
||||||
|
|
||||||
|
/* ==== ABLEHNEN BLEIBT SICHTBAR ===============================
|
||||||
|
Verschwaende die Zeile, saehe der Host nur, dass nichts
|
||||||
|
passiert -- und lade dieselbe Person ein zweites Mal ein. */
|
||||||
|
const b0 = await roh(CREW, "/workspace/api/reaktion/gast", {
|
||||||
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 },
|
||||||
|
});
|
||||||
|
ok(b0.code === 201, `Gast 2 eingeladen (${b0.code})`);
|
||||||
|
const nein = await roh(CREW, "/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.gast2, rumpf: { ja: false },
|
||||||
|
});
|
||||||
|
ok(nein.code === 200, `ablehnen geht (${nein.code})`);
|
||||||
|
const nachNein = await roh(CREW, "/workspace/api/reaktion", { keks: k.admin });
|
||||||
|
ok((nachNein.j?.gaeste || []).length === 1,
|
||||||
|
"wer ablehnt, steht nicht auf der Buehne");
|
||||||
|
ok((nachNein.j?.einladungen || []).some(
|
||||||
|
(e) => e.id === IDS.gast2 && e.stand === "abgelehnt"),
|
||||||
|
"aber der Host sieht, DASS abgelehnt wurde");
|
||||||
|
|
||||||
|
/* ==== OHNE EINLADUNG KEINE ANTWORT =========================== */
|
||||||
|
const ohne = await roh(CREW, "/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.modi, rumpf: { ja: true },
|
||||||
|
});
|
||||||
|
ok(ohne.code === 404 && ohne.j?.fehler === "keine_einladung",
|
||||||
|
`wer nicht gefragt wurde, kann nicht zusagen (${ohne.code}/${ohne.j?.fehler})`);
|
||||||
|
|
||||||
|
/* Die abgelehnte Zeile wegraeumen -- sonst zaehlt sie beim
|
||||||
|
naechsten Abschnitt mit. (Sie zaehlt NICHT fuer die Grenze,
|
||||||
|
siehe gleich; weg muss sie trotzdem, weil der Host sie sonst
|
||||||
|
bis zum Sendungsende vor sich hat.) */
|
||||||
|
await roh(CREW, `/workspace/api/reaktion/gast/${IDS.gast2}`, {
|
||||||
|
method: "DELETE", keks: k.admin,
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ==== EINE OFFENE FRAGE HAELT IHREN PLATZ ====================
|
||||||
|
Sonst laedt der Host zwei Leute ein, beide sagen ja, und der
|
||||||
|
zweite steht vor einer vollen Buehne -- nachdem er zugesagt
|
||||||
|
hat. */
|
||||||
const b = await roh(CREW, "/workspace/api/reaktion/gast", {
|
const b = await roh(CREW, "/workspace/api/reaktion/gast", {
|
||||||
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 },
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 },
|
||||||
});
|
});
|
||||||
ok(b.code === 201 && b.j?.gaeste?.length === 2, `Gast 2 dazu (${b.code})`);
|
ok(b.code === 201, `Gast 2 wieder eingeladen (${b.code})`);
|
||||||
|
|
||||||
const c = await roh(CREW, "/workspace/api/reaktion/gast", {
|
const c = await roh(CREW, "/workspace/api/reaktion/gast", {
|
||||||
method: "POST", keks: k.admin, rumpf: { person_id: IDS.modi },
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.modi },
|
||||||
});
|
});
|
||||||
ok(c.code === 409 && c.j?.fehler === "gaeste_voll",
|
ok(c.code === 409 && c.j?.fehler === "gaeste_voll",
|
||||||
`ein dritter passt nicht (${c.code}/${c.j?.fehler})`);
|
`ein dritter passt nicht -- die offene Frage zaehlt mit (${c.code}/${c.j?.fehler})`);
|
||||||
|
|
||||||
|
/* Und jetzt sagt der Zweite auch zu, damit der Rest des
|
||||||
|
Abschnitts zwei Gaeste auf der Buehne vorfindet. */
|
||||||
|
const ja2 = await roh(CREW, "/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.gast2, rumpf: { ja: true, kamera: true, mikro: true },
|
||||||
|
});
|
||||||
|
ok(ja2.code === 200 && (ja2.j?.gaeste || []).length === 2,
|
||||||
|
`Gast 2 ist dabei (${ja2.code})`);
|
||||||
|
|
||||||
/* EIN GAST BEKOMMT DIE NAMENSLISTE -- und das ist kein Zufall:
|
/* EIN GAST BEKOMMT DIE NAMENSLISTE -- und das ist kein Zufall:
|
||||||
Ohne sie wuesste er nicht, wen er anrufen soll, und sein Bild
|
Ohne sie wuesste er nicht, wen er anrufen soll, und sein Bild
|
||||||
@@ -454,13 +558,81 @@ melde("=== 6. Ein bis zwei Gaeste ===");
|
|||||||
|
|
||||||
/* Der frei gewordene Platz wird WIEDERVERWENDET. Mit „Anzahl + 1"
|
/* Der frei gewordene Platz wird WIEDERVERWENDET. Mit „Anzahl + 1"
|
||||||
bliebe Platz 1 fuer immer leer, sobald einmal jemand gegangen
|
bliebe Platz 1 fuer immer leer, sobald einmal jemand gegangen
|
||||||
ist -- und das faellt erst im dritten Stream auf. */
|
ist -- und das faellt erst im dritten Stream auf.
|
||||||
const neu = await roh(CREW, "/workspace/api/reaktion/gast", {
|
|
||||||
|
Der Platz wird seit dem 08.10.2026 bei der ZUSAGE vergeben und
|
||||||
|
nicht bei der Einladung: Wer ablehnt, soll Platz 1 nicht zwei
|
||||||
|
Minuten lang blockiert haben. */
|
||||||
|
await roh(CREW, "/workspace/api/reaktion/gast", {
|
||||||
method: "POST", keks: k.admin, rumpf: { person_id: IDS.modi },
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.modi },
|
||||||
});
|
});
|
||||||
|
const neu = await roh(CREW, "/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.modi, rumpf: { ja: true, kamera: true, mikro: true },
|
||||||
|
});
|
||||||
const plaetze = (neu.j?.gaeste || []).map((x) => x.platz).sort();
|
const plaetze = (neu.j?.gaeste || []).map((x) => x.platz).sort();
|
||||||
ok(plaetze.join(",") === "1,2",
|
ok(plaetze.join(",") === "1,2",
|
||||||
`der frei gewordene Platz wird wiederverwendet (${plaetze.join(",")})`);
|
`der frei gewordene Platz wird wiederverwendet (${plaetze.join(",")})`);
|
||||||
|
|
||||||
|
/* ==== DIE FRIST IST ECHT UND NICHT NUR EIN TEXT ===============
|
||||||
|
(08.10.2026)
|
||||||
|
|
||||||
|
Eine Einladung, die nach zwei Minuten „abgelaufen" HEISST, aber
|
||||||
|
weiterhin angenommen werden kann, ist keine Frist. Geprueft wird
|
||||||
|
das nicht mit Warten -- zwei Minuten Wartezeit in einem Pruflauf
|
||||||
|
waere genau die Sorte Pruefung, die beim naechsten Mal jemand
|
||||||
|
ueberspringt. Stattdessen wird der Zeitpunkt der Frage in der
|
||||||
|
Datenbank zurueckdatiert; das ist dieselbe Lage, nur sofort.
|
||||||
|
|
||||||
|
GEGENPROBE INBEGRIFFEN: Vorher wird bestaetigt, dass dieselbe
|
||||||
|
Einladung OHNE Rueckdatierung angenommen worden waere. Ohne sie
|
||||||
|
bewiese ein 409 nur, dass irgendetwas nicht ging. */
|
||||||
|
{
|
||||||
|
const { db } = await import("./workspace.js");
|
||||||
|
/* Erst Platz schaffen -- die Buehne ist gerade voll. */
|
||||||
|
await roh(CREW, `/workspace/api/reaktion/gast/${IDS.modi}`, {
|
||||||
|
method: "DELETE", keks: k.admin,
|
||||||
|
});
|
||||||
|
const e1 = await roh(CREW, "/workspace/api/reaktion/gast", {
|
||||||
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.modi },
|
||||||
|
});
|
||||||
|
ok(e1.code === 201, `fuer die Fristprobe noch einmal gefragt (${e1.code})`);
|
||||||
|
const vorDatum = await roh(CREW, "/workspace/api/reaktion", { keks: k.modi });
|
||||||
|
ok(vorDatum.j?.ich?.einladung?.noch_sek > 0,
|
||||||
|
"Gegenprobe: unmittelbar nach der Frage gilt sie noch");
|
||||||
|
|
||||||
|
/* Zehn Minuten zurueck -- weit jenseits der zwei Minuten. */
|
||||||
|
const alt = new Date(Date.now() - 600_000).toISOString();
|
||||||
|
db().prepare("UPDATE reaktion_gaeste SET gefragt_am = ? WHERE person_id = ?")
|
||||||
|
.run(alt, IDS.modi);
|
||||||
|
|
||||||
|
const zuSpaet = await roh(CREW, "/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.modi, rumpf: { ja: true },
|
||||||
|
});
|
||||||
|
ok(zuSpaet.code === 409 && zuSpaet.j?.fehler === "einladung_abgelaufen",
|
||||||
|
`eine abgelaufene Einladung wird abgelehnt (${zuSpaet.code}/${zuSpaet.j?.fehler})`);
|
||||||
|
|
||||||
|
const danach = await roh(CREW, "/workspace/api/reaktion", { keks: k.modi });
|
||||||
|
ok(!danach.j?.ich?.einladung,
|
||||||
|
"und der Gefragte sieht sie nicht mehr");
|
||||||
|
const beimHost = await roh(CREW, "/workspace/api/reaktion", { keks: k.admin });
|
||||||
|
ok((beimHost.j?.einladungen || []).some(
|
||||||
|
(x) => x.id === IDS.modi && x.stand === "keine_antwort"),
|
||||||
|
"der Host sieht „keine Antwort“ statt einer verschwundenen Zeile");
|
||||||
|
|
||||||
|
await roh(CREW, `/workspace/api/reaktion/gast/${IDS.modi}`, {
|
||||||
|
method: "DELETE", keks: k.admin,
|
||||||
|
});
|
||||||
|
/* Und wieder herstellen, was der naechste Abschnitt erwartet:
|
||||||
|
zwei Gaeste auf der Buehne. */
|
||||||
|
await roh(CREW, "/workspace/api/reaktion/gast", {
|
||||||
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.modi },
|
||||||
|
});
|
||||||
|
const zurueck = await roh(CREW, "/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.modi, rumpf: { ja: true, kamera: true, mikro: true },
|
||||||
|
});
|
||||||
|
ok((zurueck.j?.gaeste || []).length === 2,
|
||||||
|
`nach der Fristprobe stehen wieder zwei auf der Buehne (${zurueck.j?.gaeste?.length})`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =======================================================================
|
/* =======================================================================
|
||||||
@@ -1142,9 +1314,18 @@ melde("=== 13. Kamera und Chat ===");
|
|||||||
for (const rolle of ["admin", "hand", "linke", "modi", "gast", "gast2"]) {
|
for (const rolle of ["admin", "hand", "linke", "modi", "gast", "gast2"]) {
|
||||||
await roh(CREW, "/workspace/api/reaktion/dabei", { method: "POST", keks: k[rolle] });
|
await roh(CREW, "/workspace/api/reaktion/dabei", { method: "POST", keks: k[rolle] });
|
||||||
}
|
}
|
||||||
|
/* ZWEI SCHRITTE SEIT DEM 08.10.2026: fragen und zusagen. Hier
|
||||||
|
steht beides hintereinander, weil dieser Abschnitt die Kamera
|
||||||
|
prueft und nicht die Einladung -- die hat ihren eigenen
|
||||||
|
Abschnitt. Der zweite Aufruf gehoert trotzdem dazu: Ohne ihn
|
||||||
|
stuende hier ein Gefragter und kein Gast, und alles darunter
|
||||||
|
maesse etwas anderes. */
|
||||||
await roh(CREW, "/workspace/api/reaktion/gast", {
|
await roh(CREW, "/workspace/api/reaktion/gast", {
|
||||||
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 },
|
method: "POST", keks: k.admin, rumpf: { person_id: IDS.gast2 },
|
||||||
});
|
});
|
||||||
|
await roh(CREW, "/workspace/api/reaktion/gast/antwort", {
|
||||||
|
method: "POST", keks: k.gast2, rumpf: { ja: true, kamera: true, mikro: true },
|
||||||
|
});
|
||||||
|
|
||||||
const stand0 = await roh(CREW, "/workspace/api/reaktion", { keks: k.admin });
|
const stand0 = await roh(CREW, "/workspace/api/reaktion", { keks: k.admin });
|
||||||
ok(stand0.j?.stand === "live" && stand0.j?.gaeste?.length === 1,
|
ok(stand0.j?.stand === "live" && stand0.j?.gaeste?.length === 1,
|
||||||
@@ -2856,6 +3037,169 @@ melde("=== Beendet heisst leer ===");
|
|||||||
`wer nur vorbereitet hat, behaelt seine Eingaben ("${probe.j?.titel}")`);
|
`wer nur vorbereitet hat, behaelt seine Eingaben ("${probe.j?.titel}")`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
DER SPENDER-GLANZ IM CHAT (08.10.2026)
|
||||||
|
|
||||||
|
Filipe: „die leute die spenden gemacht haben sollen auch für eine
|
||||||
|
kurze zeit speziell aussehen je nach höhe von spende."
|
||||||
|
|
||||||
|
Geprueft wird hier der WEG: Traegt ein Chatbeitrag die Auskunft,
|
||||||
|
und steht sie nur bei dem, der wirklich gegeben hat? Dass die
|
||||||
|
Stufen stimmen und dass der Glanz ablaeuft, prueft `pruef-spenden`
|
||||||
|
-- dort steht die Leiter.
|
||||||
|
======================================================================= */
|
||||||
|
melde("");
|
||||||
|
melde("=== 18. Spender im Chat ===");
|
||||||
|
{
|
||||||
|
const { db } = await import("./workspace.js");
|
||||||
|
|
||||||
|
await roh(CREW, "/workspace/api/reaktion", {
|
||||||
|
method: "PUT", keks: k.admin,
|
||||||
|
rumpf: { titel: "Glanzprobe", video: "dQw4w9WgXcQ" },
|
||||||
|
});
|
||||||
|
await roh(CREW, "/workspace/api/reaktion/stand",
|
||||||
|
{ method: "POST", keks: k.admin, rumpf: { stand: "live" } });
|
||||||
|
for (const rolle of ["admin", "gast", "gast2"]) {
|
||||||
|
await roh(CREW, "/workspace/api/reaktion/dabei", { method: "POST", keks: k[rolle] });
|
||||||
|
}
|
||||||
|
|
||||||
|
await roh(CREW, "/workspace/api/reaktion/chat",
|
||||||
|
{ method: "POST", keks: k.gast2, rumpf: { text: "Ich gebe gleich was" } });
|
||||||
|
await roh(CREW, "/workspace/api/reaktion/chat",
|
||||||
|
{ method: "POST", keks: k.admin, rumpf: { text: "Ich nicht" } });
|
||||||
|
|
||||||
|
/* ==== DIE GEGENPROBE AN DERSELBEN PERSON ======================
|
||||||
|
|
||||||
|
Beim ersten Lauf stand hier „kein Beitrag traegt einen Glanz" --
|
||||||
|
und das war rot, zu Recht: Abschnitt 16 legt fuer `gast` eine
|
||||||
|
Spende an, und die glaenzte noch. Die Pruefung hat damit
|
||||||
|
bewiesen, dass der Glanz funktioniert, und sich selbst dabei
|
||||||
|
fuer kaputt erklaert.
|
||||||
|
|
||||||
|
Richtig ist eine Gegenprobe, die NUR von dem abhaengt, was
|
||||||
|
dieser Abschnitt selbst tut: dieselbe Person vorher und
|
||||||
|
nachher. */
|
||||||
|
const ohne = await roh(CREW, "/workspace/api/reaktion/chat", { keks: k.gast2 });
|
||||||
|
const vorSpende = (ohne.j?.beitraege || []).find((b) => b.person_id === IDS.gast2);
|
||||||
|
ok(!!vorSpende && vorSpende.spende === null,
|
||||||
|
"Gegenprobe: vor der Spende traegt sein Beitrag keinen Glanz");
|
||||||
|
|
||||||
|
/* Eine gezeigte Spende -- direkt in die Tabelle, weil hier der
|
||||||
|
CHAT geprueft wird und nicht der Weg einer Spende. Die
|
||||||
|
Stufenleiter steht ab Werk auf 5/15/45 Minuten. */
|
||||||
|
db().prepare(`INSERT INTO spenden
|
||||||
|
(betrag_cent, waehrung, name, gruss, person_id, herkunft, stand, erstellt, gezeigt_am)
|
||||||
|
VALUES (?,?,?,?,?,'hand','bestaetigt',?,?)`)
|
||||||
|
.run(2000, "EUR", "Lenny", "", IDS.gast2,
|
||||||
|
new Date().toISOString(), new Date().toISOString());
|
||||||
|
|
||||||
|
const mit = await roh(CREW, "/workspace/api/reaktion/chat", { keks: k.gast2 });
|
||||||
|
const meiner = (mit.j?.beitraege || []).find((b) => b.person_id === IDS.gast2);
|
||||||
|
const fremder = (mit.j?.beitraege || []).find((b) => b.person_id === IDS.admin);
|
||||||
|
ok(!!meiner?.spende, "wer gespendet hat, traegt den Glanz am Beitrag");
|
||||||
|
ok(/^#[0-9a-fA-F]{6}$/.test(meiner?.spende?.farbe || ""),
|
||||||
|
`mit einer echten Farbe (${meiner?.spende?.farbe})`);
|
||||||
|
ok(!!meiner?.spende?.stufe, `und dem Namen der Stufe (${meiner?.spende?.stufe})`);
|
||||||
|
ok(meiner?.spende?.noch_ms > 0,
|
||||||
|
`und einer Restdauer statt einer Uhrzeit (${meiner?.spende?.noch_ms} ms)`);
|
||||||
|
ok(fremder?.spende === null, "und der Nachbar daneben nicht");
|
||||||
|
|
||||||
|
/* ==== AUCH DER EINZELNE NEUE BEITRAG TRAEGT IHN ==============
|
||||||
|
Es gibt zwei Ausgaenge (Liste beim Laden, Meldung beim
|
||||||
|
Schreiben). Wer nur einen pflegt, hat den Glanz nach dem
|
||||||
|
Neuladen -- und beim Schreiben nicht. */
|
||||||
|
const neu = await roh(CREW, "/workspace/api/reaktion/chat",
|
||||||
|
{ method: "POST", keks: k.gast2, rumpf: { text: "Noch einer" } });
|
||||||
|
ok(!!neu.j?.spende,
|
||||||
|
"auch ein frisch geschriebener Beitrag bringt ihn gleich mit");
|
||||||
|
|
||||||
|
/* ==== UND DER ROLLENSCHLUESSEL BLEIBT DRAUSSEN ===============
|
||||||
|
Dieselbe Regel wie am 07.10.2026: Was der Saal nicht wissen
|
||||||
|
muss, verlaesst das Haus nicht. Der Glanz traegt Farbe, Namen
|
||||||
|
und Dauer -- keine Personennummer eines anderen, keinen Betrag
|
||||||
|
in Geld. */
|
||||||
|
ok(meiner?.spende?.dogen_mille > 0 && meiner?.spende?.cent === undefined,
|
||||||
|
"er traegt Dogen und kein Geld");
|
||||||
|
|
||||||
|
await roh(CREW, "/workspace/api/reaktion/stand",
|
||||||
|
{ method: "POST", keks: k.admin, rumpf: { stand: "zu" } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
19. WAS AUF DER SEITE STEHEN MUSS (08.10.2026)
|
||||||
|
|
||||||
|
Drei Umbauten dieses Tages haben Bedienteile, die es vorher nicht
|
||||||
|
gab. Eine Funktion, die nur im Programm existiert und nicht im
|
||||||
|
Dokument, ist nicht da -- und gemerkt wird es in einer Sendung.
|
||||||
|
======================================================================= */
|
||||||
|
melde("");
|
||||||
|
melde("=== 19. Vorraum, Geraete, zweites Video ===");
|
||||||
|
{
|
||||||
|
const html = readFileSync(join(HIER, "..", "workspace", "reaktion.html"), "utf8");
|
||||||
|
const js = readFileSync(join(HIER, "..", "workspace", "assets", "js", "reaktion.js"), "utf8");
|
||||||
|
const css = readFileSync(
|
||||||
|
join(HIER, "..", "workspace", "assets", "css", "reaktion.css"), "utf8");
|
||||||
|
|
||||||
|
/* ---- Der Vorraum ---- */
|
||||||
|
ok(/id="vorraum"/.test(html), "der Vorraum steht in der Seite");
|
||||||
|
/* ZWEI AUSGAENGE. Ein Vorhang, aus dem nur ein Weg herausfuehrt,
|
||||||
|
ist keine Frage -- und er stuende ausgerechnet vor jemandem, der
|
||||||
|
gerade nur zuschauen wollte. */
|
||||||
|
ok(/id="vorraum-ja"/.test(html) && /id="vorraum-nein"/.test(html),
|
||||||
|
"und er hat zwei Ausgaenge: dabei sein und lieber nicht");
|
||||||
|
ok(/id="vorraum-kamera"/.test(html) && /id="vorraum-mikro"/.test(html),
|
||||||
|
"Kamera und Mikro lassen sich VORHER waehlen");
|
||||||
|
ok(/id="vorraum-video"/.test(html) && /muted/.test(html),
|
||||||
|
"das eigene Bild laeuft darin -- stumm");
|
||||||
|
ok(/vorraumZu\(true\)/.test(js),
|
||||||
|
"und beim Ablehnen wird die Kamera wirklich angehalten");
|
||||||
|
ok(/\.vorraum\b/.test(css), "der Vorraum hat eine Regel im Stilblatt");
|
||||||
|
|
||||||
|
/* ---- Die Geraete ---- */
|
||||||
|
ok(/id="geraete"/.test(html), "das Register „Ton“ hat einen Geraeteteil");
|
||||||
|
ok(/id="s-geraete"/.test(html) && /id="geraetefenster"/.test(html),
|
||||||
|
"und auch Gaeste kommen daran -- ueber die Senderleiste");
|
||||||
|
/* ==== DER EIGENTLICHE FUND VOM 08.10.2026 ====================
|
||||||
|
Hier stand fest `echoCancellation: true, noiseSuppression: true`.
|
||||||
|
Ueber einem Mischpult ist das falsch: Der Duo hat Gate,
|
||||||
|
Kompressor und EQ schon gemacht, und die Echo-Unterdrueckung
|
||||||
|
des Browsers duckt danach, sobald von der Gegenseite Ton kommt.
|
||||||
|
Wenn diese Zeile je wieder fest dasteht, ist der Pultmodus
|
||||||
|
wirkungslos -- und es faellt erst im Stream auf. */
|
||||||
|
ok(!/audio:\s*\{\s*echoCancellation:\s*true/.test(js),
|
||||||
|
"Gegenprobe: die Echo-Unterdrueckung steht nicht mehr fest auf an");
|
||||||
|
ok(/echoCancellation:\s*!pult/.test(js),
|
||||||
|
"sie haengt am Pultmodus");
|
||||||
|
ok(/autoGainControl:\s*!pult/.test(js),
|
||||||
|
"und die Lautstaerke-Automatik ebenso");
|
||||||
|
ok(/OverconstrainedError/.test(js),
|
||||||
|
"ein Geraet, das nicht mehr da ist, hat einen eigenen Ausgang");
|
||||||
|
ok(/setSinkId/.test(js), "und der Ausgabeweg laesst sich waehlen");
|
||||||
|
|
||||||
|
/* ---- Das zweite Video ---- */
|
||||||
|
ok(/id="zweitbild"/.test(html) && /id="zweit-titel"/.test(html),
|
||||||
|
"das zweite Video wird gezeigt und nicht nur eingetippt");
|
||||||
|
ok(/id="zweit-stelle"/.test(html),
|
||||||
|
"samt der gemerkten Stelle -- sie ist der Grund fuer den zweiten Platz");
|
||||||
|
ok(/id="p-zweit-tausch"/.test(html),
|
||||||
|
"und es laesst sich von hier aus umschalten");
|
||||||
|
ok(/dataset\.was = 'bereit'/.test(js),
|
||||||
|
"aus der Warteschlange laesst sich eines bereitlegen");
|
||||||
|
|
||||||
|
/* ---- Die fertigen Saetze und der Platz ---- */
|
||||||
|
ok(/id="geben-satzreihe"/.test(html),
|
||||||
|
"die fertigen Saetze stehen im Spendenkasten");
|
||||||
|
ok(/id="saetze"/.test(html) && /id="saetze-sichern"/.test(html),
|
||||||
|
"und die Leitung pflegt sie im Register „Gestaltung“");
|
||||||
|
ok(/id="platzwahl"/.test(html), "der Platz der Karte laesst sich stellen");
|
||||||
|
|
||||||
|
/* ---- Der Werkstoff ---- */
|
||||||
|
ok(/--w-hoch:/.test(css) && /--w-tief:/.test(css),
|
||||||
|
"die Seite hat eine Hoehensprache (was obenauf liegt, was vertieft ist)");
|
||||||
|
ok(/:focus-visible/.test(css),
|
||||||
|
"und wer mit der Tastatur bedient, wird gesehen");
|
||||||
|
}
|
||||||
|
|
||||||
melde("");
|
melde("");
|
||||||
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
|
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
|
||||||
melde(fehler === 0 ? "ALLES IN ORDNUNG" : "NICHT IN ORDNUNG");
|
melde(fehler === 0 ? "ALLES IN ORDNUNG" : "NICHT IN ORDNUNG");
|
||||||
|
|||||||
@@ -1103,6 +1103,309 @@ melde("=== 10. Die drei Muenzsaetze ===");
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
11. DIE FERTIGEN SAETZE (08.10.2026)
|
||||||
|
|
||||||
|
Filipe: „es soll fertige sätze geben und wenn jemand die auswählt
|
||||||
|
muss keiner es bestätigen dan wird es sofort angezeigt und wenn
|
||||||
|
jemand selber was schreibt dan muss bestätigt werden damit es
|
||||||
|
angezeigt wird."
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
WAS HIER WIRKLICH AUF DEM SPIEL STEHT
|
||||||
|
|
||||||
|
Eine Karte, die OHNE Bestaetigung in einen Livestream geht, ist die
|
||||||
|
offenste Tuer des ganzen Hauses. Sie darf nur deshalb offen sein,
|
||||||
|
weil der Text NICHT vom Absender kommt, sondern aus der Datenbank.
|
||||||
|
Genau das wird hier angegriffen: Es wird versucht, neben der
|
||||||
|
Satzkennung einen eigenen Text einzuschmuggeln.
|
||||||
|
======================================================================= */
|
||||||
|
melde("");
|
||||||
|
melde("=== 11. Die fertigen Saetze ===");
|
||||||
|
{
|
||||||
|
const { db } = await import("./workspace.js");
|
||||||
|
/* Die Bremse „eine Meldung je Minute und Person" steht allen
|
||||||
|
folgenden Pruefungen im Weg -- sie brauchen mehrere Meldungen
|
||||||
|
derselben Person. Zurueckdatieren statt warten: Eine Pruefung,
|
||||||
|
die Minuten wartet, wird beim naechsten Mal uebersprungen. */
|
||||||
|
const bremseLoesen = (personId) => {
|
||||||
|
db().prepare("UPDATE spenden SET erstellt = ? WHERE person_id = ?")
|
||||||
|
.run(new Date(Date.now() - 600_000).toISOString(), personId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const lage = await roh(CREW, "/workspace/api/spenden", { keks: k.admin });
|
||||||
|
const saetze = lage.j?.fertige_saetze || [];
|
||||||
|
ok(saetze.length >= 3,
|
||||||
|
`ab Werk stehen ${saetze.length} fertige Saetze zum Aussuchen bereit`);
|
||||||
|
ok(saetze.every((s) => s.id && s.text),
|
||||||
|
"jeder hat eine Kennung und einen Text");
|
||||||
|
|
||||||
|
const beimGast = await roh(CREW, "/workspace/api/spenden", { keks: k.gast });
|
||||||
|
ok((beimGast.j?.fertige_saetze || []).length === saetze.length,
|
||||||
|
"ein Zuschauer bekommt sie auch -- er soll ja einen aussuchen");
|
||||||
|
|
||||||
|
/* ==== SOFORT INS BILD, ABER NICHT INS BUCH ===================== */
|
||||||
|
bremseLoesen(IDS.gast);
|
||||||
|
const standVorher = (await roh(CREW, "/workspace/api/spenden", { keks: k.gast }))
|
||||||
|
.j?.ich?.dogen_mille ?? -1;
|
||||||
|
|
||||||
|
const sofort = await roh(CREW, "/workspace/api/spenden/melden", {
|
||||||
|
method: "POST", keks: k.gast,
|
||||||
|
rumpf: { dogen_mille: 500, satz_id: saetze[0].id, gruss: "HIER STEHT ETWAS ANDERES" },
|
||||||
|
});
|
||||||
|
ok(sofort.code === 201 && sofort.j?.sofort === true,
|
||||||
|
`ein fertiger Satz geht sofort ins Bild (${sofort.code}/${sofort.j?.sofort})`);
|
||||||
|
ok(sofort.j?.wartet === false,
|
||||||
|
"und er wartet ausdruecklich NICHT auf eine Bestaetigung");
|
||||||
|
|
||||||
|
const imPult = await roh(CREW, "/workspace/api/spenden", { keks: k.admin });
|
||||||
|
const frisch = (imPult.j?.offen || []).find((x) => x.dogen_mille === 500);
|
||||||
|
ok(!!frisch, "sie steht trotzdem im Pult");
|
||||||
|
ok(frisch?.schon_gezeigt === true,
|
||||||
|
"und zwar mit dem Vermerk, dass sie schon gelaufen ist");
|
||||||
|
/* ==== DER ANGRIFF: EIN EIGENER TEXT NEBEN DER KENNUNG =========
|
||||||
|
Wer `gruss` mitschickt, hat wieder ein freies Feld -- nur mit
|
||||||
|
einem Haken daneben, auf dem „ist ja ein fertiger" steht. Der
|
||||||
|
Text MUSS aus der Datenbank kommen. */
|
||||||
|
ok(frisch?.gruss === saetze[0].text,
|
||||||
|
`der Text kommt aus der Datenbank, nicht aus der Leitung ("${frisch?.gruss}")`);
|
||||||
|
ok(frisch?.gruss !== "HIER STEHT ETWAS ANDERES",
|
||||||
|
"Gegenprobe: der mitgeschickte eigene Text gilt NICHT");
|
||||||
|
|
||||||
|
/* ==== GEZEIGT IST NICHT GEBUCHT ==============================
|
||||||
|
Sonst stellte sich jede Minute jeder seine eigene Waehrung aus. */
|
||||||
|
const standNachher = (await roh(CREW, "/workspace/api/spenden", { keks: k.gast }))
|
||||||
|
.j?.ich?.dogen_mille ?? -1;
|
||||||
|
ok(standNachher === standVorher,
|
||||||
|
`gezeigt, aber noch nicht gutgeschrieben (${standVorher} -> ${standNachher})`);
|
||||||
|
|
||||||
|
/* ==== DIE BESTAETIGUNG BUCHT -- UND ZEIGT NICHT NOCH EINMAL === */
|
||||||
|
const vorBest = db().prepare("SELECT gezeigt_am FROM spenden WHERE id = ?").get(frisch.id);
|
||||||
|
const best = await roh(CREW, `/workspace/api/spenden/${frisch.id}/bestaetigen`, {
|
||||||
|
method: "POST", keks: k.admin, rumpf: {},
|
||||||
|
});
|
||||||
|
ok(best.code === 200, `die Leitung bestaetigt sie nachtraeglich (${best.code})`);
|
||||||
|
const standBest = (await roh(CREW, "/workspace/api/spenden", { keks: k.gast }))
|
||||||
|
.j?.ich?.dogen_mille ?? -1;
|
||||||
|
ok(standBest === standVorher + 500,
|
||||||
|
`erst jetzt gibt es die Dogen (${standVorher} -> ${standBest})`);
|
||||||
|
const nachBest = db().prepare("SELECT gezeigt_am FROM spenden WHERE id = ?").get(frisch.id);
|
||||||
|
ok(nachBest?.gezeigt_am === vorBest?.gezeigt_am,
|
||||||
|
"und die Karte laeuft NICHT ein zweites Mal (der Zeitpunkt steht still)");
|
||||||
|
|
||||||
|
/* ==== EIN FREIER TEXT WARTET WEITERHIN ======================== */
|
||||||
|
bremseLoesen(IDS.gast2);
|
||||||
|
const frei = await roh(CREW, "/workspace/api/spenden/melden", {
|
||||||
|
method: "POST", keks: k.gast2,
|
||||||
|
rumpf: { dogen_mille: 500, gruss: "Selbst getippt" },
|
||||||
|
});
|
||||||
|
ok(frei.code === 201 && frei.j?.sofort !== true && frei.j?.wartet === true,
|
||||||
|
`ein selbst geschriebener Text wartet (${frei.code}/sofort=${frei.j?.sofort})`);
|
||||||
|
const freiImPult = (await roh(CREW, "/workspace/api/spenden", { keks: k.admin }))
|
||||||
|
.j?.offen?.find((x) => x.gruss === "Selbst getippt");
|
||||||
|
ok(freiImPult?.schon_gezeigt === false,
|
||||||
|
"und ist nicht im Bild gewesen");
|
||||||
|
|
||||||
|
/* ==== EINE FREIE ZAHL GEHT AUCH MIT SATZ NICHT SOFORT =========
|
||||||
|
Filipes Ansage galt dem SATZ, nicht der Summe. Wer eine eigene
|
||||||
|
Zahl eintraegt, behauptet eine Hoehe -- und „25 Dogen" ungesehen
|
||||||
|
gross im Stream ist der Fehler, den man nicht mehr einfangen
|
||||||
|
kann, wenn hundert Leute zusehen. */
|
||||||
|
bremseLoesen(IDS.gast2);
|
||||||
|
const krumm = await roh(CREW, "/workspace/api/spenden/melden", {
|
||||||
|
method: "POST", keks: k.gast2, rumpf: { dogen_mille: 777, satz_id: saetze[0].id },
|
||||||
|
});
|
||||||
|
ok(krumm.code === 201 && krumm.j?.sofort === false,
|
||||||
|
`ein Betrag, den kein Knopf anbietet, wartet trotz Satz (${krumm.j?.sofort})`);
|
||||||
|
/* GEGENPROBE: Mit einem Knopfbetrag waere derselbe Satz sofort
|
||||||
|
gelaufen -- sonst bewiese das Obige nur, dass irgendetwas
|
||||||
|
nicht sofort geht. */
|
||||||
|
bremseLoesen(IDS.gast2);
|
||||||
|
const rund = await roh(CREW, "/workspace/api/spenden/melden", {
|
||||||
|
method: "POST", keks: k.gast2, rumpf: { dogen_mille: 200, satz_id: saetze[0].id },
|
||||||
|
});
|
||||||
|
ok(rund.j?.sofort === true,
|
||||||
|
"Gegenprobe: mit einem Knopfbetrag geht derselbe Satz sofort");
|
||||||
|
|
||||||
|
/* ==== EINE KENNUNG, DIE ES NICHT GIBT ======================== */
|
||||||
|
bremseLoesen(IDS.gast2);
|
||||||
|
const falsch = await roh(CREW, "/workspace/api/spenden/melden", {
|
||||||
|
method: "POST", keks: k.gast2, rumpf: { dogen_mille: 200, satz_id: 999999 },
|
||||||
|
});
|
||||||
|
ok(falsch.code === 400 && falsch.j?.fehler === "fertigsatz_unbekannt",
|
||||||
|
`eine erfundene Satzkennung wird abgelehnt (${falsch.code}/${falsch.j?.fehler})`);
|
||||||
|
|
||||||
|
/* ==== DIE LEITUNG PFLEGT DIE LISTE =========================== */
|
||||||
|
const neu = await roh(CREW, "/workspace/api/spenden/fertige-saetze", {
|
||||||
|
method: "PUT", keks: k.admin,
|
||||||
|
rumpf: { fertige_saetze: ["Erster Satz", " ", "Zweiter Satz"] },
|
||||||
|
});
|
||||||
|
ok(neu.code === 200 && (neu.j?.fertige_saetze || []).length === 2,
|
||||||
|
`leere Zeilen fallen weg (${neu.j?.fertige_saetze?.length} statt 3)`);
|
||||||
|
ok(neu.j.fertige_saetze[0].text === "Erster Satz"
|
||||||
|
&& neu.j.fertige_saetze[1].text === "Zweiter Satz",
|
||||||
|
"und die Reihenfolge bleibt");
|
||||||
|
|
||||||
|
for (const rolle of ["linke", "modi", "gast"]) {
|
||||||
|
const a = await roh(CREW, "/workspace/api/spenden/fertige-saetze", {
|
||||||
|
method: "PUT", keks: k[rolle], rumpf: { fertige_saetze: ["Ich auch"] },
|
||||||
|
});
|
||||||
|
ok(a.code === 403, `${rolle}: darf die Saetze nicht aendern (${a.code})`);
|
||||||
|
}
|
||||||
|
const zuViele = await roh(CREW, "/workspace/api/spenden/fertige-saetze", {
|
||||||
|
method: "PUT", keks: k.admin,
|
||||||
|
rumpf: { fertige_saetze: Array.from({ length: 9 }, (_, i) => `Satz ${i}`) },
|
||||||
|
});
|
||||||
|
ok(zuViele.code === 400 && zuViele.j?.fehler === "zu_viele_saetze",
|
||||||
|
`neun sind zu viele (${zuViele.code}/${zuViele.j?.fehler})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =======================================================================
|
||||||
|
12. WO DIE KARTE STEHT UND WER IM CHAT GLAENZT (08.10.2026)
|
||||||
|
======================================================================= */
|
||||||
|
melde("");
|
||||||
|
melde("=== 12. Platz und Spender-Glanz ===");
|
||||||
|
{
|
||||||
|
const { db } = await import("./workspace.js");
|
||||||
|
const { spenderGlanz } = await import("./workspace-spenden.js");
|
||||||
|
|
||||||
|
/* ---- Der Platz ---- */
|
||||||
|
const l0 = await roh(CREW, "/workspace/api/spenden", { keks: k.admin });
|
||||||
|
ok(l0.j?.platz === "mitte", `die Vorgabe ist die Mitte (${l0.j?.platz})`);
|
||||||
|
ok((l0.j?.gestaltung?.plaetze || []).join(",") === "mitte,rand",
|
||||||
|
"und es gibt genau zwei Plaetze");
|
||||||
|
|
||||||
|
/* ==== DIESER ABSCHNITT SETZT SEINE EIGENE LEITER ==============
|
||||||
|
|
||||||
|
Die Abschnitte davor haben an der Stufenleiter gearbeitet --
|
||||||
|
verschoben, geloescht, neu angelegt. Sich darauf zu verlassen,
|
||||||
|
was dabei uebrig geblieben ist, waere die Kopplung, die spaeter
|
||||||
|
jemand aus Versehen zerreisst; dann faellt ein Abschnitt um, an
|
||||||
|
dem nichts falsch ist. (Genau so ist dieser Abschnitt beim
|
||||||
|
ersten Lauf rot geworden: zwei Stufen statt drei, beide ohne
|
||||||
|
Glanz.)
|
||||||
|
|
||||||
|
Die drei Werte sind dieselben wie ab Werk -- 5, 15, 45 --, damit
|
||||||
|
die Pruefung auch das misst, was ein frisches Haus mitbringt. */
|
||||||
|
const leiterSoll = [
|
||||||
|
{ id: 0, ab_mille: 100, name: "Danke", vorlage: "herz", farbe: "#8ec9ff",
|
||||||
|
dauer_ms: 6000, groesse: 1, glanz_minuten: 5 },
|
||||||
|
{ id: 0, ab_mille: 500, name: "Starke Runde", vorlage: "welle", farbe: "#a98bff",
|
||||||
|
dauer_ms: 8000, groesse: 1.15, glanz_minuten: 15 },
|
||||||
|
{ id: 0, ab_mille: 2000, name: "Rudel-Legende", vorlage: "krone", farbe: "#e0a13a",
|
||||||
|
dauer_ms: 11000, groesse: 1.45, glanz_minuten: 45 },
|
||||||
|
];
|
||||||
|
const gesetzt = await roh(CREW, "/workspace/api/spenden/stufen", {
|
||||||
|
method: "PUT", keks: k.admin, rumpf: { stufen: leiterSoll },
|
||||||
|
});
|
||||||
|
ok(gesetzt.code === 200 && (gesetzt.j?.stufen || []).length === 3,
|
||||||
|
`drei Stufen fuer diesen Abschnitt gesetzt (${gesetzt.j?.stufen?.length})`);
|
||||||
|
ok((gesetzt.j?.stufen || []).map((s) => s.glanz_minuten).join("/") === "5/15/45",
|
||||||
|
`und der Glanz kommt zurueck, wie er hingeschickt wurde `
|
||||||
|
+ `(${(gesetzt.j?.stufen || []).map((s) => s.glanz_minuten).join("/")})`);
|
||||||
|
|
||||||
|
const stufenJetzt = (gesetzt.j?.stufen || []).map((s) => ({
|
||||||
|
id: s.id, ab_mille: s.ab_mille, name: s.name, vorlage: s.vorlage,
|
||||||
|
farbe: s.farbe, dauer_ms: s.dauer_ms, groesse: s.groesse,
|
||||||
|
glanz_minuten: s.glanz_minuten,
|
||||||
|
}));
|
||||||
|
const amRand = await roh(CREW, "/workspace/api/spenden/stufen", {
|
||||||
|
method: "PUT", keks: k.admin, rumpf: { stufen: stufenJetzt, platz: "rand" },
|
||||||
|
});
|
||||||
|
ok(amRand.code === 200 && amRand.j?.platz === "rand",
|
||||||
|
`er laesst sich auf „rand" stellen (${amRand.j?.platz})`);
|
||||||
|
const falscherPlatz = await roh(CREW, "/workspace/api/spenden/stufen", {
|
||||||
|
method: "PUT", keks: k.admin, rumpf: { stufen: stufenJetzt, platz: "oben" },
|
||||||
|
});
|
||||||
|
ok(falscherPlatz.code === 400 && falscherPlatz.j?.fehler === "platz_unklar",
|
||||||
|
`ein erfundener Platz wird abgelehnt (${falscherPlatz.code}/${falscherPlatz.j?.fehler})`);
|
||||||
|
|
||||||
|
/* ==== DER PLATZ REIST MIT DER KARTE ==========================
|
||||||
|
Die Spendentafel in OBS hat keine Sitzung und kann nichts
|
||||||
|
nachfragen -- was sie nicht mitbekommt, kann sie nicht
|
||||||
|
anzeigen. */
|
||||||
|
const mitKarte = await roh(CREW, "/workspace/api/spenden", { keks: k.admin });
|
||||||
|
const eine = (mitKarte.j?.letzte || [])[0];
|
||||||
|
ok(eine?.platz === "rand", `jede Karte traegt den Platz mit (${eine?.platz})`);
|
||||||
|
|
||||||
|
await roh(CREW, "/workspace/api/spenden/stufen", {
|
||||||
|
method: "PUT", keks: k.admin, rumpf: { stufen: stufenJetzt, platz: "mitte" },
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ---- Der Glanz im Chat ---- */
|
||||||
|
const werte = stufenJetzt.map((s) => s.glanz_minuten);
|
||||||
|
ok(werte.length >= 3 && werte[0] > 0 && werte[2] > werte[0],
|
||||||
|
`je hoeher die Stufe, desto laenger der Glanz (${werte.join(" / ")} Minuten)`);
|
||||||
|
|
||||||
|
const glanz = spenderGlanz();
|
||||||
|
const meiner = glanz.get(IDS.gast);
|
||||||
|
ok(!!meiner, "wer eben gespendet hat, glaenzt im Chat");
|
||||||
|
ok(meiner?.farbe && /^#[0-9a-fA-F]{6}$/.test(meiner.farbe),
|
||||||
|
`in der Farbe seiner Stufe (${meiner?.farbe})`);
|
||||||
|
ok(!!meiner?.stufe, `und mit ihrem Namen (${meiner?.stufe})`);
|
||||||
|
ok(meiner?.noch_ms > 0, `und mit einer Restdauer (${meiner?.noch_ms} ms)`);
|
||||||
|
/* ALS ALTER UND NICHT ALS UHRZEIT -- eine Uhr im Handy kann falsch
|
||||||
|
gehen, eine Dauer nicht. Dieselbe Lehre wie beim Gleichlauf des
|
||||||
|
Videos am 30.09.2026. */
|
||||||
|
ok(meiner?.noch_ms <= werte[1] * 60_000 + 1000,
|
||||||
|
"und die Restdauer passt zur Stufe");
|
||||||
|
|
||||||
|
/* ==== DIE STAERKSTE STUFE GEWINNT, NICHT DIE LETZTE ==========
|
||||||
|
Wer erst viel und dann wenig gibt, soll nicht herabgestuft
|
||||||
|
werden -- das laese sich wie eine Bestrafung dafuer, dass er
|
||||||
|
noch einmal gegeben hat. */
|
||||||
|
{
|
||||||
|
const gross = stufenJetzt[stufenJetzt.length - 1].ab_mille;
|
||||||
|
db().prepare(`INSERT INTO spenden
|
||||||
|
(betrag_cent, waehrung, name, gruss, person_id, herkunft, stand, erstellt, gezeigt_am)
|
||||||
|
VALUES (?,?,?,?,?,'hand','bestaetigt',?,?)`)
|
||||||
|
.run(gross * 10, "EUR", "Probe", "", IDS.gast,
|
||||||
|
new Date(Date.now() - 60_000).toISOString(),
|
||||||
|
new Date(Date.now() - 60_000).toISOString());
|
||||||
|
db().prepare(`INSERT INTO spenden
|
||||||
|
(betrag_cent, waehrung, name, gruss, person_id, herkunft, stand, erstellt, gezeigt_am)
|
||||||
|
VALUES (?,?,?,?,?,'hand','bestaetigt',?,?)`)
|
||||||
|
.run(100, "EUR", "Probe", "", IDS.gast, new Date().toISOString(),
|
||||||
|
new Date().toISOString());
|
||||||
|
const g2 = spenderGlanz().get(IDS.gast);
|
||||||
|
ok(g2?.stufe === stufenJetzt[stufenJetzt.length - 1].name,
|
||||||
|
`die hoechste noch gueltige Stufe gewinnt (${g2?.stufe})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== NULL MINUTEN HEISST GAR NICHT ==========================
|
||||||
|
Eine gueltige Einstellung und kein fehlender Wert. */
|
||||||
|
{
|
||||||
|
const aus = stufenJetzt.map((s) => ({ ...s, glanz_minuten: 0 }));
|
||||||
|
const a = await roh(CREW, "/workspace/api/spenden/stufen", {
|
||||||
|
method: "PUT", keks: k.admin, rumpf: { stufen: aus },
|
||||||
|
});
|
||||||
|
ok(a.code === 200, `alle Stufen auf null (${a.code})`);
|
||||||
|
ok(spenderGlanz().size === 0,
|
||||||
|
"dann glaenzt niemand mehr -- auch nicht, wer eben gespendet hat");
|
||||||
|
const zurueck = await roh(CREW, "/workspace/api/spenden/stufen", {
|
||||||
|
method: "PUT", keks: k.admin, rumpf: { stufen: stufenJetzt },
|
||||||
|
});
|
||||||
|
ok(zurueck.code === 200 && spenderGlanz().size > 0,
|
||||||
|
"Gegenprobe: mit Minuten glaenzt er wieder");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== UND NACH DER ZEIT IST SCHLUSS ========================== */
|
||||||
|
{
|
||||||
|
const lange = stufenJetzt[stufenJetzt.length - 1].glanz_minuten;
|
||||||
|
db().prepare("UPDATE spenden SET gezeigt_am = ? WHERE person_id = ?")
|
||||||
|
.run(new Date(Date.now() - (lange + 10) * 60_000).toISOString(), IDS.gast);
|
||||||
|
ok(!spenderGlanz().get(IDS.gast),
|
||||||
|
`nach ${lange} Minuten ist der Glanz vorbei`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const grenze = await roh(CREW, "/workspace/api/spenden/stufen", {
|
||||||
|
method: "PUT", keks: k.admin,
|
||||||
|
rumpf: { stufen: stufenJetzt.map((s) => ({ ...s, glanz_minuten: 9999 })) },
|
||||||
|
});
|
||||||
|
ok(grenze.code === 400 && grenze.j?.fehler === "glanz_unklar",
|
||||||
|
`und 9999 Minuten sind zu viel (${grenze.code}/${grenze.j?.fehler})`);
|
||||||
|
}
|
||||||
|
|
||||||
melde("");
|
melde("");
|
||||||
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
|
melde(`${geprueft} Pruefungen, ${fehler} Fehler`);
|
||||||
melde(fehler === 0 ? "ALLES IN ORDNUNG" : "NICHT IN ORDNUNG");
|
melde(fehler === 0 ? "ALLES IN ORDNUNG" : "NICHT IN ORDNUNG");
|
||||||
|
|||||||
@@ -68,9 +68,35 @@ export const VERLAUF_TAGE = 180;
|
|||||||
/** Hoechstens so viele Zuschauer bekommen Kamerabild. Darueber: nur Ton. */
|
/** Hoechstens so viele Zuschauer bekommen Kamerabild. Darueber: nur Ton. */
|
||||||
export const SICHT_PLAETZE = Number(process.env.REAKTION_SICHT_PLAETZE || 12);
|
export const SICHT_PLAETZE = Number(process.env.REAKTION_SICHT_PLAETZE || 12);
|
||||||
|
|
||||||
/** Hoechstens so viele Gaeste gleichzeitig (Filipes Notiz: 1-2). */
|
/** Hoechstens so viele Gaeste gleichzeitig (Filipes Notiz: 1-2).
|
||||||
|
*
|
||||||
|
* GEZAEHLT WERDEN AUCH DIE GEFRAGTEN. Eine offene Einladung haelt
|
||||||
|
* ihren Platz frei -- sonst kann der Host zwei Leute einladen,
|
||||||
|
* beide sagen ja, und der zweite steht vor einer vollen Buehne,
|
||||||
|
* nachdem er schon zugesagt hat. */
|
||||||
export const GAESTE_MAX = 2;
|
export const GAESTE_MAX = 2;
|
||||||
|
|
||||||
|
/** So lange wartet eine Einladung auf eine Antwort.
|
||||||
|
*
|
||||||
|
* Zwei Minuten. Kuerzer verpasst sie jeder, der gerade etwas holt;
|
||||||
|
* laenger blockiert eine Einladung an jemanden, der gar nicht mehr
|
||||||
|
* am Geraet sitzt, mitten in der Sendung einen von zwei Plaetzen.
|
||||||
|
*
|
||||||
|
* SIE VERFAELLT SICHTBAR UND NICHT STILL. Der Eintrag bleibt als
|
||||||
|
* „keine Antwort" stehen, bis der Host ihn wegnimmt -- sonst sieht
|
||||||
|
* er nur, dass nichts passiert, und laedt dieselbe Person noch
|
||||||
|
* einmal ein. */
|
||||||
|
export const EINLADUNG_SEKUNDEN = 120;
|
||||||
|
|
||||||
|
/* Die vier Zustaende einer Gastzeile -- gefragt, dabei, abgelehnt,
|
||||||
|
keine_antwort -- stehen dort, wo die Spalte entsteht (weiter unten
|
||||||
|
bei der Nachruestung), und sonst nirgends.
|
||||||
|
|
||||||
|
EINE LISTE DANEBEN GAB ES KURZ, und sie wurde von niemandem
|
||||||
|
gelesen. Eine Konstante, die nichts erzwingt und niemand abfragt,
|
||||||
|
sieht im Quelltext aus wie eine Regel und ist keine -- genau die
|
||||||
|
Sorte Zeile, auf die man sich beim naechsten Umbau verlaesst. */
|
||||||
|
|
||||||
/** Ein Chatbeitrag in der Reaction. */
|
/** Ein Chatbeitrag in der Reaction. */
|
||||||
export const TEXT_MAX = 400;
|
export const TEXT_MAX = 400;
|
||||||
|
|
||||||
@@ -555,6 +581,39 @@ export function reaktionTabellen(d) {
|
|||||||
d.exec("ALTER TABLE reaktion_dabei ADD COLUMN mikro_aus INTEGER NOT NULL DEFAULT 0");
|
d.exec("ALTER TABLE reaktion_dabei ADD COLUMN mikro_aus INTEGER NOT NULL DEFAULT 0");
|
||||||
console.log("[reaktion] Spalte mikro_aus angelegt.");
|
console.log("[reaktion] Spalte mikro_aus angelegt.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==== DIE EINLADUNG (08.10.2026) ===============================
|
||||||
|
|
||||||
|
Filipe: „wenn gäste eingeladen werden, sollen die akzeptieren
|
||||||
|
oder ablehnen können. bevor die auch angezeigt werden sollen die
|
||||||
|
auswählen können ob die kamera an ist oder aus ist. also iohre
|
||||||
|
eigene."
|
||||||
|
|
||||||
|
Bis heute machte „Dazuholen" aus jemandem SOFORT einen Gast:
|
||||||
|
Seine Kamera sprang an, sein Bild lief, und er hat es daran
|
||||||
|
gemerkt, dass er sich selbst sah. Das ist bei jemandem, der
|
||||||
|
gerade zuschaut, ein Griff in sein Wohnzimmer.
|
||||||
|
|
||||||
|
VIER ZUSTAENDE UND NICHT ZWEI. „gefragt" ist der neue Normalfall,
|
||||||
|
„dabei" das Ziel. Die beiden anderen sind Antworten, die stehen
|
||||||
|
bleiben muessen: Wer ablehnt oder nicht antwortet, verschwindet
|
||||||
|
sonst spurlos aus der Liste, und der Host sieht nur, dass nichts
|
||||||
|
passiert -- und holt ihn ein zweites Mal.
|
||||||
|
|
||||||
|
WARUM DIE VORGABE 'dabei' IST: Wer in dem Augenblick, in dem
|
||||||
|
diese Spalte entsteht, schon auf der Buehne steht, steht dort
|
||||||
|
wirklich. Eine Vorgabe 'gefragt' haette alle laufenden Gaeste
|
||||||
|
mitten in einer Sendung zu Eingeladenen gemacht und ihr Bild
|
||||||
|
abgeschaltet. */
|
||||||
|
const gaeste = new Set(
|
||||||
|
d.prepare("PRAGMA table_info(reaktion_gaeste)").all().map((z) => z.name));
|
||||||
|
if (!gaeste.has("stand")) {
|
||||||
|
d.exec("ALTER TABLE reaktion_gaeste ADD COLUMN stand TEXT NOT NULL DEFAULT 'dabei'");
|
||||||
|
/* Wann gefragt wurde -- daraus rechnet sich die Frist. Leer bei
|
||||||
|
allen, die schon dabei sind; sie wurden nie gefragt. */
|
||||||
|
d.exec("ALTER TABLE reaktion_gaeste ADD COLUMN gefragt_am TEXT NOT NULL DEFAULT ''");
|
||||||
|
console.log("[reaktion] Spalten fuer die Gaeste-Einladung angelegt.");
|
||||||
|
}
|
||||||
if (!da.has("kamera_gross")) {
|
if (!da.has("kamera_gross")) {
|
||||||
/* Groesse und Ecke der Kamerafenster. Beide gelten fuer die
|
/* Groesse und Ecke der Kamerafenster. Beide gelten fuer die
|
||||||
ganze Sendung -- wer sendet, stellt das Bild fuer alle ein. */
|
ganze Sendung -- wer sendet, stellt das Bild fuer alle ein. */
|
||||||
|
|||||||
+178
-6
@@ -273,9 +273,12 @@ export const MUENZEN_VERTEILT = "dogen_muenzen_verteilt";
|
|||||||
* richtig grosse Danke. Drei Stufen, nicht sieben — bei sieben
|
* richtig grosse Danke. Drei Stufen, nicht sieben — bei sieben
|
||||||
* merkt sich niemand mehr, was welche bedeutet. */
|
* merkt sich niemand mehr, was welche bedeutet. */
|
||||||
export const STUFEN_START = [
|
export const STUFEN_START = [
|
||||||
{ ab_cent: 100, name: "Danke", vorlage: "herz", farbe: "#8ec9ff", dauer_ms: 6000, groesse: 1 },
|
{ ab_cent: 100, name: "Danke", vorlage: "herz", farbe: "#8ec9ff",
|
||||||
{ ab_cent: 500, name: "Starke Runde", vorlage: "welle", farbe: "#a98bff", dauer_ms: 8000, groesse: 1.15 },
|
dauer_ms: 6000, groesse: 1, glanz_minuten: 5 },
|
||||||
{ ab_cent: 2000, name: "Rudel-Legende", vorlage: "krone", farbe: "#e0a13a", dauer_ms: 11000, groesse: 1.45 },
|
{ ab_cent: 500, name: "Starke Runde", vorlage: "welle", farbe: "#a98bff",
|
||||||
|
dauer_ms: 8000, groesse: 1.15, glanz_minuten: 15 },
|
||||||
|
{ ab_cent: 2000, name: "Rudel-Legende", vorlage: "krone", farbe: "#e0a13a",
|
||||||
|
dauer_ms: 11000, groesse: 1.45, glanz_minuten: 45 },
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Die Knoepfe, die zum Geben angeboten werden — in TAUSENDSTELN.
|
/** Die Knoepfe, die zum Geben angeboten werden — in TAUSENDSTELN.
|
||||||
@@ -292,6 +295,109 @@ export const STUFEN_START = [
|
|||||||
* einer runden Zahl — das waere eine Erwartung, keine Auswahl. */
|
* einer runden Zahl — das waere eine Erwartung, keine Auswahl. */
|
||||||
export const KNOEPFE_MILLE = [200, 500, 1000, 2500];
|
export const KNOEPFE_MILLE = [200, 500, 1000, 2500];
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DIE FERTIGEN SÄTZE (08.10.2026)
|
||||||
|
|
||||||
|
Filipe: „es soll fertige sätze geben und wenn jemand die auswählt
|
||||||
|
muss keiner es bestätigen dan wird es sofort angezeigt und wenn
|
||||||
|
jemand selber was schreibt dan muss bestätigt werden damit es
|
||||||
|
angezeigt wird."
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
WARUM EIN FERTIGER SATZ OHNE BESTÄTIGUNG DARF UND EIN FREIER NICHT
|
||||||
|
|
||||||
|
Die Schranke vor dem Stream war nie gegen den Betrag gerichtet,
|
||||||
|
sondern gegen den TEXT: Ein freies Feld, das im Livestream gross
|
||||||
|
erscheint, ist die offenste Tür des ganzen Hauses. Ein fertiger
|
||||||
|
Satz hat diese Tür nicht — er steht in der Datenbank, DogFather
|
||||||
|
hat ihn selbst geschrieben, und der Browser schickt nur seine
|
||||||
|
Kennung. Es kann also gar kein fremdes Wort ins Bild kommen.
|
||||||
|
|
||||||
|
DESHALB REIST DER TEXT NICHT MIT. Der Browser sendet `satz_id`,
|
||||||
|
und der Server holt den Satz. Wer den Text mitschickte, hätte
|
||||||
|
wieder ein freies Feld — nur mit einem Haken daneben, auf dem
|
||||||
|
„ist ja ein fertiger" steht.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
WAS TROTZDEM GEPRÜFT WIRD, UND WARUM
|
||||||
|
|
||||||
|
Sofort ins Bild geht die Karte nur, wenn der BETRAG von einem der
|
||||||
|
Spendenknöpfe stammt (`KNOEPFE_MILLE`). Das ist keine Aufweichung
|
||||||
|
von Filipes Ansage — sie betraf den SATZ, nicht die Summe. Wer
|
||||||
|
eine freie Zahl einträgt, behauptet eine Höhe; dass „25 Dogen"
|
||||||
|
ungesehen gross im Stream stehen, war nie gemeint und wäre der
|
||||||
|
Fehler, den man nicht mehr einfangen kann, wenn hundert Leute
|
||||||
|
zusehen.
|
||||||
|
|
||||||
|
UND DIE DOGEN GIBT ES ERST NACH DER BESTÄTIGUNG. Gezeigt wird
|
||||||
|
sofort, GUTGESCHRIEBEN wird nach dem Tipp der Leitung. Sonst
|
||||||
|
bekäme jede Minute jeder ohne eine einzige Zahlung Punkte — und
|
||||||
|
eine Währung, die man sich selbst ausstellen kann, ist keine.
|
||||||
|
Die Spende bleibt dafür auf `offen` stehen und wandert ganz
|
||||||
|
normal in die Liste „Wartet auf dich".
|
||||||
|
===================================================================== */
|
||||||
|
|
||||||
|
/** So viele fertige Sätze höchstens.
|
||||||
|
*
|
||||||
|
* Acht. Eine Liste, die man scrollen muss, wird nicht gelesen —
|
||||||
|
* und wer gerade gespendet hat, soll aussuchen und nicht suchen. */
|
||||||
|
export const SAETZE_MAX = 8;
|
||||||
|
|
||||||
|
/** Die Sätze ab Werk. Sie stehen hier und nicht in der Datenbank,
|
||||||
|
* damit ein frisches Haus sofort welche anzubieten hat; geändert
|
||||||
|
* werden sie danach im Register „Gestaltung".
|
||||||
|
*
|
||||||
|
* KURZ, FREUNDLICH, OHNE INNENWITZ. Ein Satz, den nur drei Leute
|
||||||
|
* verstehen, wählt auch nur einer aus. Und keiner davon behauptet
|
||||||
|
* etwas über den Betrag — „Grosse Runde!" neben 0,2 Dogen wäre
|
||||||
|
* Spott, und zwar ausgerechnet gegenüber dem, der gegeben hat. */
|
||||||
|
export const SAETZE_START = [
|
||||||
|
"Weiter so, Dogi!",
|
||||||
|
"Danke für den Abend.",
|
||||||
|
"Grüsse ans ganze Rudel.",
|
||||||
|
"Bleib wie du bist.",
|
||||||
|
"Kleine Stärkung für die Sendung.",
|
||||||
|
"Einfach, weil es Spass macht.",
|
||||||
|
];
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
WIE LANGE JEMAND IM CHAT BESONDERS AUSSIEHT (08.10.2026)
|
||||||
|
|
||||||
|
Filipe: „die leute die spenden gemacht haben sollen auch für eine
|
||||||
|
kurze zeit speziell aussehen je nach höhe von spende."
|
||||||
|
|
||||||
|
„Je nach Höhe" gibt es im Haus schon — das ist die Stufenleiter.
|
||||||
|
Eine zweite Grenzenliste daneben wäre eine zweite Antwort auf
|
||||||
|
dieselbe Frage, und spätestens wenn eine Stufe verschoben wird,
|
||||||
|
leuchtete im Chat eine andere Farbe als auf der Karte. Also hängt
|
||||||
|
die Dauer an der STUFE und wird mit ihr eingestellt.
|
||||||
|
|
||||||
|
NULL HEISST „GAR NICHT". Eine Stufe ohne Glanz ist eine gültige
|
||||||
|
Einstellung und kein fehlender Wert — wer die unterste Stufe
|
||||||
|
ruhig haben will, stellt 0 ein.
|
||||||
|
===================================================================== */
|
||||||
|
export const GLANZ_MIN_MINUTEN = 0;
|
||||||
|
export const GLANZ_MAX_MINUTEN = 180;
|
||||||
|
|
||||||
|
/* Was die drei Werksstufen mitbringen, steht bei ihnen selbst
|
||||||
|
(`STUFEN_START`): 5 · 15 · 45 Minuten. „Kurze Zeit" ist Filipes
|
||||||
|
Wort, und bei einer Sendung von ein bis zwei Stunden heisst das:
|
||||||
|
Die unterste Stufe ist nach einem Videowechsel wieder normal, die
|
||||||
|
oberste bleibt den ganzen Abend.
|
||||||
|
|
||||||
|
EINE EIGENE LISTE DANEBEN GAB ES KURZ, und sie war schon beim
|
||||||
|
ersten Lauf falsch: Sie wurde über `ab_cent` zugeordnet, also über
|
||||||
|
einen Wert, den jemand verschieben kann. Was zu einer Stufe
|
||||||
|
gehört, steht an der Stufe. */
|
||||||
|
|
||||||
|
/** Wo die Spendenkarte im Bild steht. */
|
||||||
|
export const PLATZ_NAME = "spenden_platz";
|
||||||
|
export const PLAETZE = ["mitte", "rand"];
|
||||||
|
|
||||||
|
/** Unter welchem Namen steht, dass die fertigen Sätze einmal angelegt
|
||||||
|
* wurden. Siehe die Begründung an der Stelle, die ihn setzt. */
|
||||||
|
export const SAETZE_ANGELEGT = "spenden_saetze_angelegt";
|
||||||
|
|
||||||
export function spendenTabellen(d) {
|
export function spendenTabellen(d) {
|
||||||
d.exec(`
|
d.exec(`
|
||||||
/* Eine Zeile je Spende. Auch die abgelehnten bleiben stehen:
|
/* Eine Zeile je Spende. Auch die abgelehnten bleiben stehen:
|
||||||
@@ -348,6 +454,18 @@ export function spendenTabellen(d) {
|
|||||||
farbe TEXT NOT NULL DEFAULT '#8ec9ff',
|
farbe TEXT NOT NULL DEFAULT '#8ec9ff',
|
||||||
dauer_ms INTEGER NOT NULL DEFAULT 7000
|
dauer_ms INTEGER NOT NULL DEFAULT 7000
|
||||||
CHECK (dauer_ms BETWEEN 2000 AND 30000),
|
CHECK (dauer_ms BETWEEN 2000 AND 30000),
|
||||||
|
/* Wie lange jemand nach einer Spende dieser Stufe im Chat
|
||||||
|
besonders aussieht. 0 heisst „gar nicht" und ist eine
|
||||||
|
gueltige Einstellung.
|
||||||
|
|
||||||
|
SIE STEHT HIER UND NICHT NUR IM ALTER-TABLE DARUNTER. Beim
|
||||||
|
ersten Bau stand sie nur dort -- und das Nachruesten laeuft
|
||||||
|
VOR dem Anlegen der Werksstufen. In einem frischen Haus lief das
|
||||||
|
nachtraegliche Fuellen also ueber eine leere Tabelle, und
|
||||||
|
alle drei Stufen bekamen die Vorgabe 0: Der Glanz war
|
||||||
|
eingebaut und blieb trotzdem aus. Gefunden hat es die
|
||||||
|
Pruefung, nicht das Lesen. */
|
||||||
|
glanz_minuten INTEGER NOT NULL DEFAULT 0,
|
||||||
geaendert TEXT NOT NULL DEFAULT ''
|
geaendert TEXT NOT NULL DEFAULT ''
|
||||||
);
|
);
|
||||||
`);
|
`);
|
||||||
@@ -409,6 +527,59 @@ export function spendenTabellen(d) {
|
|||||||
d.exec("ALTER TABLE spenden_stufen ADD COLUMN groesse REAL NOT NULL DEFAULT 1");
|
d.exec("ALTER TABLE spenden_stufen ADD COLUMN groesse REAL NOT NULL DEFAULT 1");
|
||||||
console.log("[spenden] Spalte groesse angelegt.");
|
console.log("[spenden] Spalte groesse angelegt.");
|
||||||
}
|
}
|
||||||
|
/* ==== NACHGEWACHSEN: DER GLANZ IM CHAT (08.10.2026) =============
|
||||||
|
Derselbe Weg wie oben, aus demselben Grund. Die Vorgabe ist 0 —
|
||||||
|
eine bestehende Leiter soll nicht von selbst anfangen zu
|
||||||
|
leuchten, nur weil jemand ein Programm aktualisiert hat. Die
|
||||||
|
drei WERKSSTUFEN bekommen ihre Werte gleich darunter, und zwar
|
||||||
|
nur, solange sie noch ihre Werksgrenzen tragen. */
|
||||||
|
if (!da.has("glanz_minuten")) {
|
||||||
|
d.exec("ALTER TABLE spenden_stufen ADD COLUMN glanz_minuten INTEGER NOT NULL DEFAULT 0");
|
||||||
|
/* Nur dort, wo noch die Werksgrenze steht: Wer seine Leiter
|
||||||
|
umgebaut hat, soll nicht ploetzlich einen Glanz bekommen, den
|
||||||
|
er nie eingestellt hat. */
|
||||||
|
for (const s of STUFEN_START) {
|
||||||
|
d.prepare("UPDATE spenden_stufen SET glanz_minuten = ? WHERE ab_cent = ?")
|
||||||
|
.run(s.glanz_minuten, s.ab_cent);
|
||||||
|
}
|
||||||
|
console.log("[spenden] Spalte glanz_minuten angelegt.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== DIE FERTIGEN SÄTZE ========================================
|
||||||
|
Eine Zeile je Satz. `platz` statt einer Reihenfolge im Namen:
|
||||||
|
Wer einen Satz nach oben zieht, soll nicht alle anderen
|
||||||
|
umbenennen müssen. */
|
||||||
|
d.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS spenden_saetze (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
text TEXT NOT NULL,
|
||||||
|
platz INTEGER NOT NULL DEFAULT 0,
|
||||||
|
geaendert TEXT NOT NULL DEFAULT ''
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
/* NUR BEIM ALLERERSTEN MAL. `COUNT` und nicht `INSERT OR IGNORE`:
|
||||||
|
Ein Satz hat keinen eindeutigen Schlüssel, über den „gibt es
|
||||||
|
schon" zu entscheiden wäre — und wer alle sechs löscht, weil er
|
||||||
|
eigene schreiben will, soll sie beim nächsten Neustart nicht
|
||||||
|
wieder vorfinden. Eine Einstellung, die sich gegen den Benutzer
|
||||||
|
durchsetzt, wird abgeschafft; das ist dieselbe Lehre wie bei den
|
||||||
|
Münzen darunter, nur mit einem anderen Merker: hier genügt die
|
||||||
|
eigene Tabelle, denn „niemals angelegt" und „alle gelöscht"
|
||||||
|
unterscheiden sich durch den Merker in `einstellungen`. */
|
||||||
|
try {
|
||||||
|
const schon = d.prepare("SELECT wert FROM einstellungen WHERE schluessel = ?")
|
||||||
|
.get(SAETZE_ANGELEGT);
|
||||||
|
if (!schon) {
|
||||||
|
const ein = d.prepare("INSERT INTO spenden_saetze (text, platz, geaendert)"
|
||||||
|
+ " VALUES (?,?,?)");
|
||||||
|
SAETZE_START.forEach((t, i) => ein.run(t, i, new Date().toISOString()));
|
||||||
|
d.prepare(`INSERT OR REPLACE INTO einstellungen (schluessel, wert, geaendert)
|
||||||
|
VALUES (?,?,?)`).run(SAETZE_ANGELEGT, "ja", new Date().toISOString());
|
||||||
|
console.log(`[spenden] ${SAETZE_START.length} fertige Sätze angelegt.`);
|
||||||
|
}
|
||||||
|
} catch (fehler) {
|
||||||
|
console.error("[spenden] Sätze anlegen:", fehler?.message);
|
||||||
|
}
|
||||||
|
|
||||||
/* DIE DREI STUFEN ANLEGEN, WENN ES NOCH KEINE GIBT.
|
/* DIE DREI STUFEN ANLEGEN, WENN ES NOCH KEINE GIBT.
|
||||||
|
|
||||||
@@ -418,9 +589,10 @@ export function spendenTabellen(d) {
|
|||||||
const nun = new Date().toISOString();
|
const nun = new Date().toISOString();
|
||||||
for (const s of STUFEN_START) {
|
for (const s of STUFEN_START) {
|
||||||
d.prepare(`INSERT OR IGNORE INTO spenden_stufen
|
d.prepare(`INSERT OR IGNORE INTO spenden_stufen
|
||||||
(ab_cent, name, vorlage, farbe, dauer_ms, groesse, geaendert)
|
(ab_cent, name, vorlage, farbe, dauer_ms, groesse, glanz_minuten, geaendert)
|
||||||
VALUES (?,?,?,?,?,?,?)`)
|
VALUES (?,?,?,?,?,?,?,?)`)
|
||||||
.run(s.ab_cent, s.name, s.vorlage, s.farbe, s.dauer_ms, s.groesse, nun);
|
.run(s.ab_cent, s.name, s.vorlage, s.farbe, s.dauer_ms, s.groesse,
|
||||||
|
s.glanz_minuten, nun);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==== DIE MUENZEN EINMAL AN DIE DREI STUFEN VERTEILEN ==========
|
/* ==== DIE MUENZEN EINMAL AN DIE DREI STUFEN VERTEILEN ==========
|
||||||
|
|||||||
+278
-14
@@ -44,10 +44,16 @@ import express from "express";
|
|||||||
import { db, sitzungLesen, protokolliere, echteIp } from "./workspace.js";
|
import { db, sitzungLesen, protokolliere, echteIp } from "./workspace.js";
|
||||||
import { stromAn } from "./workspace-chat.js";
|
import { stromAn } from "./workspace-chat.js";
|
||||||
import { buehneMelden } from "./workspace-buehne.js";
|
import { buehneMelden } from "./workspace-buehne.js";
|
||||||
|
/* Der Spender-Glanz im Chat. EINE RICHTUNG: Die Reaction fragt die
|
||||||
|
Spenden, nie umgekehrt -- `workspace-spenden.js` kennt diese Datei
|
||||||
|
nicht und soll sie nicht kennen, sonst stünden sich beim Laden
|
||||||
|
zwei Dateien gegenseitig im Weg. */
|
||||||
|
import { spenderGlanz } from "./workspace-spenden.js";
|
||||||
import { einstellung } from "./workspace.js";
|
import { einstellung } from "./workspace.js";
|
||||||
import { mitZugangsdaten, wegeAusfaechern } from "./workspace-turn.js";
|
import { mitZugangsdaten, wegeAusfaechern } from "./workspace-turn.js";
|
||||||
import {
|
import {
|
||||||
SICHT_PLAETZE, GAESTE_MAX, TEXT_MAX, SCHREIB_BREMSE, STAENDE, LAYOUTS, TEMPI,
|
SICHT_PLAETZE, GAESTE_MAX, EINLADUNG_SEKUNDEN, TEXT_MAX, SCHREIB_BREMSE,
|
||||||
|
STAENDE, LAYOUTS, TEMPI,
|
||||||
KAMERA_GROESSEN, KAMERA_ECKEN,
|
KAMERA_GROESSEN, KAMERA_ECKEN,
|
||||||
MELDUNG_TAGE,
|
MELDUNG_TAGE,
|
||||||
VERLAUF_TAGE, LISTE_MAX, CHAT_MODI, STUMM_MAX_MINUTEN, MASSNAHMEN,
|
VERLAUF_TAGE, LISTE_MAX, CHAT_MODI, STUMM_MAX_MINUTEN, MASSNAHMEN,
|
||||||
@@ -313,13 +319,66 @@ function weiterZu(zeile, personId) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Wer wirklich auf der Buehne steht.
|
||||||
|
*
|
||||||
|
* NUR `dabei`. Seit dem 08.10.2026 gibt es Zeilen, die noch keine
|
||||||
|
* Gaeste sind (gefragt) und welche, die keine mehr werden
|
||||||
|
* (abgelehnt, keine Antwort). Haetten die hier gestanden, saehe der
|
||||||
|
* ganze Saal ein Kamerafenster fuer jemanden, der die Frage noch
|
||||||
|
* gar nicht gelesen hat -- und die Anruflogik haette versucht, ihn
|
||||||
|
* anzurufen. */
|
||||||
function gaesteListe() {
|
function gaesteListe() {
|
||||||
return db().prepare(`
|
return db().prepare(`
|
||||||
SELECT g.person_id AS id, g.stumm, g.platz, p.name, p.rolle
|
SELECT g.person_id AS id, g.stumm, g.platz, p.name, p.rolle
|
||||||
FROM reaktion_gaeste g JOIN personen p ON p.id = g.person_id
|
FROM reaktion_gaeste g JOIN personen p ON p.id = g.person_id
|
||||||
|
WHERE g.stand = 'dabei'
|
||||||
ORDER BY g.platz`).all();
|
ORDER BY g.platz`).all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Die offenen und beantworteten Einladungen -- nur fuer den Host.
|
||||||
|
*
|
||||||
|
* ==== DIE FRIST WIRD BEIM LESEN GEZOGEN UND NICHT VON EINER UHR
|
||||||
|
*
|
||||||
|
* Ein eigener Zeitgeber waere ein zweiter Ort, an dem dieselbe
|
||||||
|
* Entscheidung faellt -- und er liefe auch dann, wenn niemand
|
||||||
|
* hinsieht. Hier gilt: Wer die Liste liest, bekommt den Stand, der
|
||||||
|
* jetzt gilt. Das ist dieselbe Form wie bei `dabeiListe()`, die
|
||||||
|
* ihre Karteileichen auch beim Lesen wegraeumt.
|
||||||
|
*
|
||||||
|
* UND SIE WIRD NICHT GELOESCHT, SONDERN UMGESCHRIEBEN. Eine
|
||||||
|
* verfallene Einladung, die verschwindet, sieht fuer den Host aus
|
||||||
|
* wie „ich habe mich verklickt". */
|
||||||
|
function einladungenListe() {
|
||||||
|
const grenze = new Date(Date.now() - EINLADUNG_SEKUNDEN * 1000).toISOString();
|
||||||
|
db().prepare(`UPDATE reaktion_gaeste SET stand = 'keine_antwort'
|
||||||
|
WHERE stand = 'gefragt' AND gefragt_am < ?`).run(grenze);
|
||||||
|
return db().prepare(`
|
||||||
|
SELECT g.person_id AS id, g.stand, g.gefragt_am, p.name
|
||||||
|
FROM reaktion_gaeste g JOIN personen p ON p.id = g.person_id
|
||||||
|
WHERE g.stand <> 'dabei'
|
||||||
|
ORDER BY g.gefragt_am`).all()
|
||||||
|
.map((z) => ({
|
||||||
|
id: z.id, name: z.name, stand: z.stand,
|
||||||
|
/* ==== ALS REST UND NICHT ALS UHRZEIT ====================
|
||||||
|
Der Empfaenger bekommt „noch so viele Sekunden" statt eines
|
||||||
|
Zeitpunkts. Eine Uhrzeit muesste gegen die Uhr seines
|
||||||
|
Geraets gerechnet werden, und die kann falsch gehen --
|
||||||
|
dieselbe Lehre wie beim Gleichlauf des Videos am
|
||||||
|
30.09.2026. Ein Handy, das zwei Minuten vorgeht, saehe
|
||||||
|
sonst jede Einladung als abgelaufen. */
|
||||||
|
noch_sek: z.stand === "gefragt"
|
||||||
|
? Math.max(0, Math.round(
|
||||||
|
(Date.parse(z.gefragt_am) + EINLADUNG_SEKUNDEN * 1000 - Date.now()) / 1000))
|
||||||
|
: 0,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Wie viele Plaetze gerade belegt oder vorgemerkt sind. */
|
||||||
|
function gaesteBelegt() {
|
||||||
|
return db().prepare(`SELECT COUNT(*) AS n FROM reaktion_gaeste
|
||||||
|
WHERE stand IN ('dabei','gefragt')`).get()?.n || 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Wer gerade dabei ist -- und ob noch ein Kameraplatz frei war.
|
/** Wer gerade dabei ist -- und ob noch ein Kameraplatz frei war.
|
||||||
*
|
*
|
||||||
* ZWEI MINUTEN OHNE LEBENSZEICHEN HEISST WEG. Ein Browser, der
|
* ZWEI MINUTEN OHNE LEBENSZEICHEN HEISST WEG. Ein Browser, der
|
||||||
@@ -413,6 +472,13 @@ function lage(person) {
|
|||||||
})),
|
})),
|
||||||
chat_modus: s.chat_modus || "offen",
|
chat_modus: s.chat_modus || "offen",
|
||||||
chat_modi: CHAT_MODI,
|
chat_modi: CHAT_MODI,
|
||||||
|
/* ==== DIE OFFENEN EINLADUNGEN (08.10.2026) ==================
|
||||||
|
Nur fuer den Host. Wer gefragt wurde und noch nicht geantwortet
|
||||||
|
hat, ist noch kein Gast -- und dass jemand gefragt WURDE, geht
|
||||||
|
den Saal nichts an. Wird in `oeffentlich()` ausdruecklich
|
||||||
|
entfernt. */
|
||||||
|
einladungen: istHost ? einladungenListe() : undefined,
|
||||||
|
einladung_sekunden: EINLADUNG_SEKUNDEN,
|
||||||
/* ==== DIE WERBUNG SIEHT JEDER =============================
|
/* ==== DIE WERBUNG SIEHT JEDER =============================
|
||||||
Sie ist das Einzige auf dieser Seite, das ausdruecklich fuer
|
Sie ist das Einzige auf dieser Seite, das ausdruecklich fuer
|
||||||
alle gedacht ist -- eine Einblendung, die nur der Host sieht,
|
alle gedacht ist -- eine Einblendung, die nur der Host sieht,
|
||||||
@@ -480,6 +546,32 @@ function lage(person) {
|
|||||||
rolle: person.rolle,
|
rolle: person.rolle,
|
||||||
host: istHost,
|
host: istHost,
|
||||||
gast: binGast,
|
gast: binGast,
|
||||||
|
/* ==== BIN ICH GERADE GEFRAGT? (08.10.2026) ==============
|
||||||
|
Die eine Auskunft, aus der die Seite den Vorhang baut:
|
||||||
|
„DogFather will dich auf die Bühne". Sie steht an `ich` und
|
||||||
|
nicht in einer Liste -- jeder bekommt nur seine eigene, und
|
||||||
|
dass jemand anderes gefragt wurde, geht ihn nichts an.
|
||||||
|
|
||||||
|
`noch_sek` reist mit, damit die Seite den Countdown ohne
|
||||||
|
eine eigene Uhr zeichnen kann. */
|
||||||
|
einladung: (() => {
|
||||||
|
const e = db().prepare(`SELECT gefragt_am FROM reaktion_gaeste
|
||||||
|
WHERE person_id = ? AND stand = 'gefragt'`).get(person.id);
|
||||||
|
if (!e) return null;
|
||||||
|
const rest = Math.round(
|
||||||
|
(Date.parse(e.gefragt_am) + EINLADUNG_SEKUNDEN * 1000 - Date.now()) / 1000);
|
||||||
|
/* Abgelaufen heißt „keine Einladung mehr". Die Zeile wird
|
||||||
|
beim nächsten Lesen der Hostliste umgeschrieben; hier
|
||||||
|
reicht es, sie nicht mehr zu zeigen -- sonst stünde vor
|
||||||
|
jemandem ein Vorhang mit „noch -40 Sekunden". */
|
||||||
|
if (rest <= 0) return null;
|
||||||
|
/* WER EINLÄDT, STEHT SCHON IM STAND (`lage.host.name`). Den
|
||||||
|
Namen hier ein zweites Mal mitzuschicken wäre eine zweite
|
||||||
|
Antwort auf dieselbe Frage -- und die beiden könnten
|
||||||
|
auseinanderlaufen, sobald jemand mitten in der Sendung die
|
||||||
|
Führung übernimmt. */
|
||||||
|
return { noch_sek: rest };
|
||||||
|
})(),
|
||||||
moderiert: MODERIERT.has(person.rolle),
|
moderiert: MODERIERT.has(person.rolle),
|
||||||
sicht: !!(dabei.find((d) => d.id === person.id)?.sicht),
|
sicht: !!(dabei.find((d) => d.id === person.id)?.sicht),
|
||||||
kamera_aus: !!(dabei.find((d) => d.id === person.id)?.kamera_aus),
|
kamera_aus: !!(dabei.find((d) => d.id === person.id)?.kamera_aus),
|
||||||
@@ -939,8 +1031,106 @@ reaktionRouter.post("/workspace/api/reaktion/gast", nurHost, express.json({ limi
|
|||||||
if (!p) return res.status(404).json({ fehler: "nicht_gefunden" });
|
if (!p) return res.status(404).json({ fehler: "nicht_gefunden" });
|
||||||
if (id === req.person.id) return res.status(400).json({ fehler: "host_ist_kein_gast" });
|
if (id === req.person.id) return res.status(400).json({ fehler: "host_ist_kein_gast" });
|
||||||
|
|
||||||
const da = db().prepare("SELECT COUNT(*) AS n FROM reaktion_gaeste").get()?.n || 0;
|
/* Verfallene Einladungen erst wegräumen — sonst hält eine
|
||||||
if (da >= GAESTE_MAX) return res.status(409).json({ fehler: "gaeste_voll" });
|
Frage von vor einer Stunde noch einen Platz besetzt. */
|
||||||
|
einladungenListe();
|
||||||
|
if (gaesteBelegt() >= GAESTE_MAX) {
|
||||||
|
return res.status(409).json({ fehler: "gaeste_voll" });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== GEFRAGT, NICHT GEHOLT (08.10.2026) =================
|
||||||
|
|
||||||
|
Filipe: „wenn gäste eingeladen werden, sollen die
|
||||||
|
akzeptieren oder ablehnen können. bevor die auch angezeigt
|
||||||
|
werden sollen die auswählen können ob die kamera an ist oder
|
||||||
|
aus ist. also iohre eigene."
|
||||||
|
|
||||||
|
Vorher stand hier ein Platz und eine Zeile — und die Kamera
|
||||||
|
des Gastes sprang im selben Augenblick an. Jetzt entsteht
|
||||||
|
erst eine FRAGE. Der Platz wird beim Zusagen vergeben, nicht
|
||||||
|
jetzt: Wer ablehnt, soll Platz 1 nicht für zwei Minuten
|
||||||
|
blockiert haben.
|
||||||
|
|
||||||
|
`INSERT OR REPLACE` räumt dabei eine alte Antwort derselben
|
||||||
|
Person weg — wer eben abgelehnt hat und jetzt noch einmal
|
||||||
|
gefragt wird, steht nicht zweimal in der Liste. */
|
||||||
|
db().prepare(`INSERT OR REPLACE INTO reaktion_gaeste
|
||||||
|
(person_id, seit, stumm, platz, stand, gefragt_am)
|
||||||
|
VALUES (?,?,0,0,'gefragt',?)`).run(id, jetzt(), jetzt());
|
||||||
|
protokolliere("reaktion_gast_gefragt", {
|
||||||
|
personId: req.person.id,
|
||||||
|
detail: p.name,
|
||||||
|
ip: echteIp(req),
|
||||||
|
});
|
||||||
|
const l = lage(req.person);
|
||||||
|
/* KEIN RUNDRUF AN DEN SAAL. Es hat sich für ihn nichts
|
||||||
|
geändert — auf der Bühne steht niemand Neues. Ein Rundruf
|
||||||
|
hier hieße, dass alle erfahren, wer gefragt wurde. */
|
||||||
|
stromAn([id], "reaktion", { was: "du_bist_eingeladen" });
|
||||||
|
res.status(201).json(l);
|
||||||
|
} catch (fehler) {
|
||||||
|
console.error("[reaktion] Gast:", fehler?.message);
|
||||||
|
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ---------- Die Antwort des Gastes -------------------------------------
|
||||||
|
Filipe: „sollen die akzeptieren oder ablehnen können. bevor die
|
||||||
|
auch angezeigt werden sollen die auswählen können ob die kamera an
|
||||||
|
ist oder aus ist."
|
||||||
|
|
||||||
|
ZWEI DINGE IN EINEM AUFRUF, und das ist Absicht: Die Zusage UND
|
||||||
|
die Vorwahl von Kamera und Mikro kommen zusammen an. Zwei Aufrufe
|
||||||
|
hintereinander hätten ein Fenster dazwischen, in dem jemand schon
|
||||||
|
auf der Bühne steht, dessen Kamera noch auf „an" steht — und genau
|
||||||
|
diese Sekunde ist das, was abgestellt werden soll.
|
||||||
|
|
||||||
|
DAS IST KEIN HOST-WEG. Hier antwortet der Gefragte selbst, für
|
||||||
|
sich. `nurHost` wäre hier falsch herum.
|
||||||
|
----------------------------------------------------------------------- */
|
||||||
|
reaktionRouter.post("/workspace/api/reaktion/gast/antwort",
|
||||||
|
express.json({ limit: "2kb" }), (req, res) => {
|
||||||
|
try {
|
||||||
|
const e = db().prepare(`SELECT * FROM reaktion_gaeste
|
||||||
|
WHERE person_id = ? AND stand = 'gefragt'`).get(req.person.id);
|
||||||
|
if (!e) return res.status(404).json({ fehler: "keine_einladung" });
|
||||||
|
|
||||||
|
/* Die Frist gilt auch hier und nicht nur beim Anzeigen. Sonst
|
||||||
|
könnte eine Seite, die seit einer Stunde offen liegt, eine
|
||||||
|
längst verfallene Einladung annehmen — und stünde plötzlich
|
||||||
|
im Bild, ohne dass jemand damit rechnet. */
|
||||||
|
if (Date.parse(e.gefragt_am) + EINLADUNG_SEKUNDEN * 1000 <= Date.now()) {
|
||||||
|
db().prepare("UPDATE reaktion_gaeste SET stand = 'keine_antwort' WHERE person_id = ?")
|
||||||
|
.run(req.person.id);
|
||||||
|
return res.status(409).json({ fehler: "einladung_abgelaufen" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const ja = req.body?.ja === true;
|
||||||
|
if (!ja) {
|
||||||
|
db().prepare("UPDATE reaktion_gaeste SET stand = 'abgelehnt' WHERE person_id = ?")
|
||||||
|
.run(req.person.id);
|
||||||
|
protokolliere("reaktion_gast_abgelehnt", {
|
||||||
|
personId: req.person.id, detail: req.person.name, ip: echteIp(req),
|
||||||
|
});
|
||||||
|
/* Nur der Host erfährt es — und er erfährt es SOFORT, sonst
|
||||||
|
wartet er zwei Minuten auf eine Antwort, die schon da
|
||||||
|
ist. */
|
||||||
|
const s = sendung();
|
||||||
|
if (s?.host_id) {
|
||||||
|
stromAn([s.host_id], "reaktion",
|
||||||
|
{ was: "einladung_beantwortet", name: req.person.name, ja: false });
|
||||||
|
}
|
||||||
|
return res.json(lage(req.person));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zwischen Frage und Zusage kann ein zweiter Gast zugesagt
|
||||||
|
haben. Ohne diese Prüfung stünden drei auf einer Bühne für
|
||||||
|
zwei. */
|
||||||
|
const dabeiJetzt = db().prepare(`SELECT COUNT(*) AS n FROM reaktion_gaeste
|
||||||
|
WHERE stand = 'dabei'`).get()?.n || 0;
|
||||||
|
if (dabeiJetzt >= GAESTE_MAX) {
|
||||||
|
return res.status(409).json({ fehler: "gaeste_voll" });
|
||||||
|
}
|
||||||
|
|
||||||
/* Der Platz ist die kleinste freie Zahl -- nicht „Anzahl + 1".
|
/* Der Platz ist die kleinste freie Zahl -- nicht „Anzahl + 1".
|
||||||
Wer Gast 1 entfernt und dann jemanden holt, bekaeme sonst
|
Wer Gast 1 entfernt und dann jemanden holt, bekaeme sonst
|
||||||
@@ -949,19 +1139,62 @@ reaktionRouter.post("/workspace/api/reaktion/gast", nurHost, express.json({ limi
|
|||||||
let platz = 1;
|
let platz = 1;
|
||||||
while (belegt.has(platz)) platz++;
|
while (belegt.has(platz)) platz++;
|
||||||
|
|
||||||
db().prepare("INSERT OR REPLACE INTO reaktion_gaeste (person_id, seit, stumm, platz) VALUES (?,?,0,?)")
|
/* ==== DIE VORWAHL WIRD GESETZT, BEVOR DIE BÜHNE AUFGEHT ===
|
||||||
.run(id, jetzt(), platz);
|
Sie steht in `reaktion_dabei` — dort, wo auch der
|
||||||
|
Senderknopf sie später hinschreibt. Eine zweite Spalte an
|
||||||
|
der Gastzeile wäre eine zweite Antwort auf dieselbe Frage,
|
||||||
|
und spätestens beim ersten Klick auf „Kamera" liefen beide
|
||||||
|
auseinander.
|
||||||
|
|
||||||
|
FEHLT DIE ANGABE, IST SIE AN. Das ist der Zustand, den jeder
|
||||||
|
erwartet, der gerade „ja" gesagt hat — und die Seite
|
||||||
|
schickt sie immer mit. */
|
||||||
|
const kameraAus = req.body?.kamera === false ? 1 : 0;
|
||||||
|
const mikroAus = req.body?.mikro === false ? 1 : 0;
|
||||||
|
|
||||||
|
db().exec("BEGIN IMMEDIATE");
|
||||||
|
try {
|
||||||
|
db().prepare(`UPDATE reaktion_gaeste SET stand = 'dabei', platz = ?, seit = ?
|
||||||
|
WHERE person_id = ?`).run(platz, jetzt(), req.person.id);
|
||||||
|
/* ==== EINFÜGEN ODER ÄNDERN, ABER NIE ÜBERSCHREIBEN ====
|
||||||
|
Wer antwortet, sitzt im Saal und steht damit längst in
|
||||||
|
`reaktion_dabei` — der Normalfall ist also ein ÄNDERN.
|
||||||
|
Ein reines `UPDATE` hätte aber einen stillen Ausgang: Ist
|
||||||
|
die Zeile zwischendurch weggeräumt worden (zwei Minuten
|
||||||
|
ohne Lebenszeichen genügen), ändert es null Zeilen, meldet
|
||||||
|
nichts, und der Gast stünde mit laufender Kamera im Bild,
|
||||||
|
obwohl er sie abgewählt hat. Genau die Sorte Fehler, die
|
||||||
|
man erst im Stream sieht.
|
||||||
|
|
||||||
|
`ON CONFLICT` setzt deshalb nur die beiden Felder und
|
||||||
|
lässt `seit`, `gesehen` und `sicht` in Ruhe. */
|
||||||
|
db().prepare(`INSERT INTO reaktion_dabei
|
||||||
|
(person_id, seit, gesehen, sicht, kamera_aus, mikro_aus)
|
||||||
|
VALUES (?,?,?,0,?,?)
|
||||||
|
ON CONFLICT(person_id) DO UPDATE SET
|
||||||
|
kamera_aus = excluded.kamera_aus, mikro_aus = excluded.mikro_aus`)
|
||||||
|
.run(req.person.id, jetzt(), jetzt(), kameraAus, mikroAus);
|
||||||
|
db().exec("COMMIT");
|
||||||
|
} catch (f) {
|
||||||
|
db().exec("ROLLBACK");
|
||||||
|
throw f;
|
||||||
|
}
|
||||||
|
|
||||||
protokolliere("reaktion_gast_dazu", {
|
protokolliere("reaktion_gast_dazu", {
|
||||||
personId: req.person.id,
|
personId: req.person.id,
|
||||||
detail: `${p.name} (Platz ${platz})`,
|
detail: `${req.person.name} (Platz ${platz}, Kamera ${kameraAus ? "aus" : "an"})`,
|
||||||
ip: echteIp(req),
|
ip: echteIp(req),
|
||||||
});
|
});
|
||||||
const l = lage(req.person);
|
const l = lage(req.person);
|
||||||
melden("reaktion", { was: "gaeste", lage: oeffentlich(l) });
|
melden("reaktion", { was: "gaeste", lage: oeffentlich(l) });
|
||||||
stromAn([id], "reaktion", { was: "du_bist_gast", lage: oeffentlich(l) });
|
const s = sendung();
|
||||||
res.status(201).json(l);
|
if (s?.host_id) {
|
||||||
|
stromAn([s.host_id], "reaktion",
|
||||||
|
{ was: "einladung_beantwortet", name: req.person.name, ja: true });
|
||||||
|
}
|
||||||
|
res.json(l);
|
||||||
} catch (fehler) {
|
} catch (fehler) {
|
||||||
console.error("[reaktion] Gast:", fehler?.message);
|
console.error("[reaktion] Gastantwort:", fehler?.message);
|
||||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1459,8 +1692,10 @@ reaktionRouter.post("/workspace/api/reaktion/senden", express.json({ limit: "2kb
|
|||||||
if (s.stand === "zu") return res.status(409).json({ fehler: "saal_zu" });
|
if (s.stand === "zu") return res.status(409).json({ fehler: "saal_zu" });
|
||||||
|
|
||||||
const istHost = HOST_ROLLEN.has(req.person.rolle);
|
const istHost = HOST_ROLLEN.has(req.person.rolle);
|
||||||
const binGast = !!db().prepare("SELECT 1 FROM reaktion_gaeste WHERE person_id = ?")
|
/* `stand = 'dabei'` seit dem 08.10.2026: Wer erst GEFRAGT ist,
|
||||||
.get(req.person.id);
|
sendet noch nicht und darf hier auch nichts schalten. */
|
||||||
|
const binGast = !!db().prepare("SELECT 1 FROM reaktion_gaeste"
|
||||||
|
+ " WHERE person_id = ? AND stand = 'dabei'").get(req.person.id);
|
||||||
if (!istHost && !binGast) return res.status(403).json({ fehler: "sendest_nicht" });
|
if (!istHost && !binGast) return res.status(403).json({ fehler: "sendest_nicht" });
|
||||||
|
|
||||||
/* TEILWEISE AENDERN IST ERLAUBT. Wer nur die Kamera schaltet,
|
/* TEILWEISE AENDERN IST ERLAUBT. Wer nur die Kamera schaltet,
|
||||||
@@ -1917,15 +2152,37 @@ const CHAT_ABZEICHEN = {
|
|||||||
* und die Meldung beim Schreiben. Zwei Fassungen waeren zwei
|
* und die Meldung beim Schreiben. Zwei Fassungen waeren zwei
|
||||||
* Gelegenheiten, eine davon zu vergessen -- und vergessen wuerde man
|
* Gelegenheiten, eine davon zu vergessen -- und vergessen wuerde man
|
||||||
* die, die seltener angefasst wird. */
|
* die, die seltener angefasst wird. */
|
||||||
function fuerDenSaal(b) {
|
function fuerDenSaal(b, glanz) {
|
||||||
if (!b) return b;
|
if (!b) return b;
|
||||||
const { rolle, ...rest } = b;
|
const { rolle, ...rest } = b;
|
||||||
|
/* ==== DER SPENDER-GLANZ (08.10.2026) ==========================
|
||||||
|
|
||||||
|
Filipe: „die leute die spenden gemacht haben sollen auch für
|
||||||
|
eine kurze zeit speziell aussehen je nach höhe von spende."
|
||||||
|
|
||||||
|
DIE KARTE WIRD EINMAL JE ANFRAGE GEBAUT und hereingereicht --
|
||||||
|
der Chat lädt 120 Beiträge, und eine Abfrage je Beitrag wären
|
||||||
|
120 Abfragen für eine Auskunft, die sich dazwischen gar nicht
|
||||||
|
ändert. Fehlt sie (einzelner neuer Beitrag), holt diese
|
||||||
|
Funktion sie selbst; dann ist es genau eine.
|
||||||
|
|
||||||
|
WARUM DER GLANZ AM BEITRAG HÄNGT UND NICHT AN DER PERSON: Ein
|
||||||
|
Beitrag von vor einer Stunde soll nicht nachträglich leuchten,
|
||||||
|
wenn jemand eben gespendet hat. Er bekommt den Stand, der beim
|
||||||
|
Laden gilt -- und beim nächsten Laden den dann gültigen. */
|
||||||
|
const k = (glanz || spenderGlanz()).get(b.person_id);
|
||||||
return {
|
return {
|
||||||
...rest,
|
...rest,
|
||||||
abzeichen: CHAT_ABZEICHEN[rolle] || null,
|
abzeichen: CHAT_ABZEICHEN[rolle] || null,
|
||||||
/* „Gehoert zum Team" war vorher `b.rolle !== 'gast'` in der
|
/* „Gehoert zum Team" war vorher `b.rolle !== 'gast'` in der
|
||||||
Oberflaeche. Dieselbe Frage, nur ohne den Namen. */
|
Oberflaeche. Dieselbe Frage, nur ohne den Namen. */
|
||||||
team: !!rolle && rolle !== "gast",
|
team: !!rolle && rolle !== "gast",
|
||||||
|
spende: k
|
||||||
|
? {
|
||||||
|
stufe: k.stufe, farbe: k.farbe, dogen_mille: k.dogen_mille,
|
||||||
|
muenze: k.muenze, noch_ms: k.noch_ms,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1934,7 +2191,8 @@ reaktionRouter.get("/workspace/api/reaktion/chat", (req, res) => {
|
|||||||
const reihen = db().prepare(`
|
const reihen = db().prepare(`
|
||||||
SELECT id, person_id, name, rolle, text, erstellt
|
SELECT id, person_id, name, rolle, text, erstellt
|
||||||
FROM reaktion_chat WHERE weg_am IS NULL ORDER BY id DESC LIMIT 120`).all();
|
FROM reaktion_chat WHERE weg_am IS NULL ORDER BY id DESC LIMIT 120`).all();
|
||||||
res.json({ beitraege: reihen.reverse().map(fuerDenSaal) });
|
const glanz = spenderGlanz();
|
||||||
|
res.json({ beitraege: reihen.reverse().map((b) => fuerDenSaal(b, glanz)) });
|
||||||
} catch (fehler) {
|
} catch (fehler) {
|
||||||
console.error("[reaktion] Chat:", fehler?.message);
|
console.error("[reaktion] Chat:", fehler?.message);
|
||||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||||
@@ -2093,7 +2351,13 @@ function oeffentlich(l) {
|
|||||||
laufenden Botschaften stehen ohnehin unter `werbung.band` und
|
laufenden Botschaften stehen ohnehin unter `werbung.band` und
|
||||||
gehoeren allen; ein Entwurf, den jemand bewusst ausgeschaltet
|
gehoeren allen; ein Entwurf, den jemand bewusst ausgeschaltet
|
||||||
hat, gehoert niemandem. */
|
hat, gehoert niemandem. */
|
||||||
const { zuschauer, ich, liste, meldungen, massnahmen, zweit,
|
/* `einladungen` KAM AM 08.10.2026 DAZU. Dass jemand gefragt wurde
|
||||||
|
und noch nicht geantwortet hat, geht den Saal nichts an -- und
|
||||||
|
erst recht nicht, dass jemand ABGELEHNT hat. Der Rundruf wird
|
||||||
|
aus dem Stand dessen gebaut, der gerade etwas getan hat; war das
|
||||||
|
der Host, ginge die ganze Liste an jeden im Saal. Genau dieselbe
|
||||||
|
Falle wie bei `meldungen` am 28.09. */
|
||||||
|
const { zuschauer, ich, liste, meldungen, massnahmen, zweit, einladungen,
|
||||||
banner_alle: _verwaltung, ...rest } = l;
|
banner_alle: _verwaltung, ...rest } = l;
|
||||||
return rest;
|
return rest;
|
||||||
}
|
}
|
||||||
|
|||||||
+329
-15
@@ -47,6 +47,7 @@ import {
|
|||||||
GROESSE_MIN, GROESSE_MAX, BILD_MAX_BYTES,
|
GROESSE_MIN, GROESSE_MAX, BILD_MAX_BYTES,
|
||||||
centInMille, milleInCent, ZEICHEN_NAME, CENT_JE_DOGE,
|
centInMille, milleInCent, ZEICHEN_NAME, CENT_JE_DOGE,
|
||||||
DOGEN_SAETZE, DOGEN_STUFEN, SATZ_NAME, muenzeAdresse,
|
DOGEN_SAETZE, DOGEN_STUFEN, SATZ_NAME, muenzeAdresse,
|
||||||
|
SAETZE_MAX, GLANZ_MIN_MINUTEN, GLANZ_MAX_MINUTEN, PLATZ_NAME, PLAETZE,
|
||||||
} from "./spenden-tabellen.js";
|
} from "./spenden-tabellen.js";
|
||||||
|
|
||||||
const BILDER = join(DATEN_ORDNER, "spendenbilder");
|
const BILDER = join(DATEN_ORDNER, "spendenbilder");
|
||||||
@@ -291,6 +292,22 @@ function alsKarte(z) {
|
|||||||
herkunft: z.herkunft,
|
herkunft: z.herkunft,
|
||||||
stand: z.stand,
|
stand: z.stand,
|
||||||
erstellt: z.erstellt,
|
erstellt: z.erstellt,
|
||||||
|
/* ==== STAND UND „SCHON IM BILD" SIND ZWEI VERSCHIEDENE DINGE
|
||||||
|
(08.10.2026)
|
||||||
|
|
||||||
|
Seit es die fertigen Sätze gibt, kann eine Karte GELAUFEN
|
||||||
|
sein, während die Spende noch auf die Bestätigung wartet. Ohne
|
||||||
|
diese Auskunft stünde sie im Pult wie jede andere offene, und
|
||||||
|
die Leitung würde sie bestätigen in der Annahme, sie damit
|
||||||
|
erst zu zeigen — sie wäre längst durch. */
|
||||||
|
schon_gezeigt: !!z.gezeigt_am,
|
||||||
|
/* WO DIE KARTE HINGEHÖRT, ENTSCHEIDET NICHT DIE KARTE. Der Platz
|
||||||
|
ist eine Einstellung des Hauses und gilt für alle; er reist
|
||||||
|
trotzdem MIT der Karte, weil die Bühnentafel in OBS keine
|
||||||
|
zweite Auskunft abholen kann -- sie hat keine Sitzung und
|
||||||
|
bekommt nur, was der Strom bringt. Dieselbe Begründung wie
|
||||||
|
beim Zeichen eine Zeile darüber. */
|
||||||
|
platz: kartenPlatz(),
|
||||||
stufe: st ? {
|
stufe: st ? {
|
||||||
name: st.name, vorlage: st.vorlage, bild: bildAdresse(st.bild),
|
name: st.name, vorlage: st.vorlage, bild: bildAdresse(st.bild),
|
||||||
farbe: st.farbe, dauer_ms: st.dauer_ms,
|
farbe: st.farbe, dauer_ms: st.dauer_ms,
|
||||||
@@ -299,6 +316,29 @@ function alsKarte(z) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Wo die Karte steht — „mitte" oder „rand".
|
||||||
|
*
|
||||||
|
* ==== WARUM DIE MITTE DIE VORGABE IST (08.10.2026)
|
||||||
|
*
|
||||||
|
* Filipe: „die spende soll auch in der mitte vom bild angezeigt
|
||||||
|
* werden. es soll richtig geil angezeigt werden so richtig in 3D
|
||||||
|
* modus."
|
||||||
|
*
|
||||||
|
* Das dreht eine Entscheidung vom 28.09. um; dort stand wörtlich
|
||||||
|
* „sie deckt nie die Mitte zu". Der Grund dafür war richtig und ist
|
||||||
|
* es immer noch — nur gilt er für eine andere Frage: Er schützt das
|
||||||
|
* VIDEO. Filipe sieht inzwischen die Spende als das, was in diesem
|
||||||
|
* Augenblick zählt, und das ist seine Entscheidung und nicht meine.
|
||||||
|
*
|
||||||
|
* „rand" bleibt deshalb erhalten und ist einen Knopf weit weg: Bei
|
||||||
|
* einem Film, bei dem der Mitteldeckel stört, ist der alte Platz
|
||||||
|
* der bessere — und eine Entscheidung, die man nicht zurücknehmen
|
||||||
|
* kann, ist keine Einstellung, sondern eine Festlegung. */
|
||||||
|
function kartenPlatz() {
|
||||||
|
const p = einstellung(PLATZ_NAME, "");
|
||||||
|
return PLAETZE.includes(p) ? p : PLAETZE[0];
|
||||||
|
}
|
||||||
|
|
||||||
/** Aus dem Dateinamen wird eine Adresse -- oder nichts.
|
/** Aus dem Dateinamen wird eine Adresse -- oder nichts.
|
||||||
*
|
*
|
||||||
* Die Adresse zeigt auf den Buehnen-Router und NICHT hierher: Die
|
* Die Adresse zeigt auf den Buehnen-Router und NICHT hierher: Die
|
||||||
@@ -418,13 +458,19 @@ function personenListe(person) {
|
|||||||
} catch { return []; }
|
} catch { return []; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Eine bestaetigte Spende ins Bild schicken. */
|
/** Eine Spende ins Bild schicken.
|
||||||
function zeigen(z) {
|
*
|
||||||
|
* `buchen` entscheidet, ob die Dogen dabei gutgeschrieben werden.
|
||||||
|
* Seit dem 08.10.2026 sind das zwei getrennte Fragen: Eine Karte mit
|
||||||
|
* fertigem Satz läuft SOFORT, die Punkte gibt es erst nach dem Tipp
|
||||||
|
* der Leitung. Die Begründung steht ausführlich in
|
||||||
|
* `spenden-tabellen.js` beim Abschnitt über die fertigen Sätze. */
|
||||||
|
function zeigen(z, buchen = true) {
|
||||||
/* ERST BUCHEN, DANN ZEIGEN. Andersherum liefe die Karte, und wenn
|
/* ERST BUCHEN, DANN ZEIGEN. Andersherum liefe die Karte, und wenn
|
||||||
dabei etwas schiefginge, stuenden die Dogen nicht im Buch --
|
dabei etwas schiefginge, stuenden die Dogen nicht im Buch --
|
||||||
sichtbar gedankt und nicht gutgeschrieben ist der aergerlichere
|
sichtbar gedankt und nicht gutgeschrieben ist der aergerlichere
|
||||||
der beiden moeglichen Fehler. */
|
der beiden moeglichen Fehler. */
|
||||||
gutschreiben(z);
|
if (buchen) gutschreiben(z);
|
||||||
db().prepare("UPDATE spenden SET gezeigt_am = ? WHERE id = ?").run(jetzt(), z.id);
|
db().prepare("UPDATE spenden SET gezeigt_am = ? WHERE id = ?").run(jetzt(), z.id);
|
||||||
const daten = { was: "zeigen", karte: alsKarte(z) };
|
const daten = { was: "zeigen", karte: alsKarte(z) };
|
||||||
stromAn(empfaenger(), "spende", daten);
|
stromAn(empfaenger(), "spende", daten);
|
||||||
@@ -433,6 +479,118 @@ function zeigen(z) {
|
|||||||
buehneMelden("spende", daten);
|
buehneMelden("spende", daten);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ======================================================================
|
||||||
|
DIE FERTIGEN SÄTZE
|
||||||
|
====================================================================== */
|
||||||
|
|
||||||
|
/** Alle fertigen Sätze, in ihrer Reihenfolge. */
|
||||||
|
function saetzeLesen() {
|
||||||
|
try {
|
||||||
|
return db().prepare("SELECT id, text FROM spenden_saetze ORDER BY platz, id").all();
|
||||||
|
} catch { return []; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ======================================================================
|
||||||
|
WER IM CHAT GERADE BESONDERS AUSSIEHT (08.10.2026)
|
||||||
|
|
||||||
|
Filipe: „die leute die spenden gemacht haben sollen auch für eine
|
||||||
|
kurze zeit speziell aussehen je nach höhe von spende."
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
EINE ABFRAGE FÜR ALLE BEITRÄGE, NICHT EINE JE BEITRAG
|
||||||
|
|
||||||
|
Der Chat lädt 120 Beiträge auf einmal. Eine Abfrage je Beitrag
|
||||||
|
wären 120 Abfragen für eine Auskunft, die sich zwischen ihnen gar
|
||||||
|
nicht ändern kann. Also einmal lesen, Map zurückgeben, fertig --
|
||||||
|
`fuerDenSaal()` schlägt darin nur noch nach.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
DIE STÄRKSTE STUFE GEWINNT, NICHT DIE LETZTE
|
||||||
|
|
||||||
|
Wer zuerst 2,5 Dogen gibt und zehn Minuten später 0,2, soll nicht
|
||||||
|
auf die kleine Stufe zurückfallen -- das läse sich wie eine
|
||||||
|
Bestrafung dafür, dass er noch einmal gegeben hat. Gilt die alte
|
||||||
|
grosse noch, bleibt sie.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
GEZÄHLT WIRD AB „IM BILD", NICHT AB „EINGETRAGEN"
|
||||||
|
|
||||||
|
`gezeigt_am` und nicht `erstellt`: Eine Spende, die eine Stunde im
|
||||||
|
Pult lag, würde sonst im selben Augenblick golden und wieder grau,
|
||||||
|
in dem die Leitung sie bestätigt. Der Glanz beginnt dort, wo ihn
|
||||||
|
alle sehen.
|
||||||
|
====================================================================== */
|
||||||
|
export function spenderGlanz() {
|
||||||
|
const karte = new Map();
|
||||||
|
try {
|
||||||
|
const stufen = db().prepare("SELECT ab_cent, name, farbe, glanz_minuten"
|
||||||
|
+ " FROM spenden_stufen ORDER BY ab_cent DESC").all();
|
||||||
|
if (!stufen.length) return karte;
|
||||||
|
|
||||||
|
/* NUR SO WEIT ZURÜCK, WIE DIE LÄNGSTE STUFE REICHT. Ohne diese
|
||||||
|
Grenze läse die Abfrage bei jedem Chataufruf die ganze
|
||||||
|
Spendentabelle -- 400 Tage lang. */
|
||||||
|
const laengste = Math.max(0, ...stufen.map((s) => Number(s.glanz_minuten) || 0));
|
||||||
|
if (laengste <= 0) return karte;
|
||||||
|
const seit = new Date(Date.now() - laengste * 60_000).toISOString();
|
||||||
|
|
||||||
|
const zeichen = zeichenSatz();
|
||||||
|
const reihen = db().prepare(`SELECT person_id, betrag_cent, gezeigt_am
|
||||||
|
FROM spenden
|
||||||
|
WHERE person_id IS NOT NULL AND gezeigt_am IS NOT NULL AND gezeigt_am > ?
|
||||||
|
ORDER BY gezeigt_am`).all(seit);
|
||||||
|
|
||||||
|
const jetztMs = Date.now();
|
||||||
|
for (const z of reihen) {
|
||||||
|
/* Dieselbe Regel wie überall: die höchste Stufe, die noch
|
||||||
|
passt. Die Liste steht absteigend, also gewinnt die erste. */
|
||||||
|
const st = stufen.find((s) => s.ab_cent <= z.betrag_cent);
|
||||||
|
if (!st) continue;
|
||||||
|
const minuten = Number(st.glanz_minuten) || 0;
|
||||||
|
if (minuten <= 0) continue;
|
||||||
|
const bis = Date.parse(z.gezeigt_am) + minuten * 60_000;
|
||||||
|
if (!Number.isFinite(bis) || bis <= jetztMs) continue;
|
||||||
|
|
||||||
|
const mille = centInMille(z.betrag_cent);
|
||||||
|
const alt = karte.get(z.person_id);
|
||||||
|
if (alt && alt.ab_cent > st.ab_cent) continue;
|
||||||
|
karte.set(z.person_id, {
|
||||||
|
ab_cent: st.ab_cent,
|
||||||
|
stufe: st.name,
|
||||||
|
farbe: st.farbe,
|
||||||
|
dogen_mille: mille,
|
||||||
|
/* DIE MÜNZE FERTIG UND NICHT DER GANZE SATZ. Eine Nachricht
|
||||||
|
trägt sonst vier Adressen mit sich, von denen drei nie
|
||||||
|
gebraucht werden -- bei 120 Beiträgen ist das der
|
||||||
|
Unterschied zwischen einer kleinen und einer grossen
|
||||||
|
Antwort. */
|
||||||
|
muenze: muenzeFuerSatz(zeichen, mille),
|
||||||
|
/* Wann der Glanz endet -- als ALTER in Millisekunden und
|
||||||
|
nicht als Uhrzeit. Die Uhr des Empfängers kann falsch
|
||||||
|
gehen; eine Dauer kann kein Gerät falsch stellen. Das ist
|
||||||
|
dieselbe Lehre wie beim Gleichlauf des Videos am
|
||||||
|
30.09.2026. */
|
||||||
|
noch_ms: Math.max(0, bis - jetztMs),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (fehler) {
|
||||||
|
/* Ein fehlender Glanz ist ein Schönheitsfehler. Der Chat muss
|
||||||
|
auch dann laufen, wenn die Spendentabellen klemmen. */
|
||||||
|
console.error("[spenden] Glanz:", fehler?.message);
|
||||||
|
}
|
||||||
|
return karte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Welche Münze zu dieser Zahl gehört -- dieselbe Regel wie im
|
||||||
|
* Browser (`spendenkarte.js`), nur hier für den Chat. */
|
||||||
|
function muenzeFuerSatz(satz, mille) {
|
||||||
|
if (!satz || !Array.isArray(satz.grenzen)) return "";
|
||||||
|
const [u, o] = satz.grenzen;
|
||||||
|
if (mille < u) return satz.niedrig || "";
|
||||||
|
if (mille < o) return satz.mittel || "";
|
||||||
|
return satz.hoch || "";
|
||||||
|
}
|
||||||
|
|
||||||
/* ======================================================================
|
/* ======================================================================
|
||||||
DIE WEGE
|
DIE WEGE
|
||||||
====================================================================== */
|
====================================================================== */
|
||||||
@@ -484,6 +642,8 @@ spendenRouter.get("/workspace/api/spenden", (req, res) => {
|
|||||||
dauer_min: DAUER_MS_MIN, dauer_max: DAUER_MS_MAX,
|
dauer_min: DAUER_MS_MIN, dauer_max: DAUER_MS_MAX,
|
||||||
groesse_min: GROESSE_MIN, groesse_max: GROESSE_MAX,
|
groesse_min: GROESSE_MIN, groesse_max: GROESSE_MAX,
|
||||||
bild_max_mb: Math.round(BILD_MAX_BYTES / 1024 / 1024),
|
bild_max_mb: Math.round(BILD_MAX_BYTES / 1024 / 1024),
|
||||||
|
glanz_min: GLANZ_MIN_MINUTEN, glanz_max: GLANZ_MAX_MINUTEN,
|
||||||
|
plaetze: PLAETZE, saetze_max: SAETZE_MAX,
|
||||||
},
|
},
|
||||||
/* ==== DER KURS GEHT NUR AN DIE LEITUNG ==================
|
/* ==== DER KURS GEHT NUR AN DIE LEITUNG ==================
|
||||||
|
|
||||||
@@ -508,6 +668,26 @@ spendenRouter.get("/workspace/api/spenden", (req, res) => {
|
|||||||
dogen_max_mille: DOGEN_MAX_MILLE,
|
dogen_max_mille: DOGEN_MAX_MILLE,
|
||||||
gruss_max: GRUSS_MAX,
|
gruss_max: GRUSS_MAX,
|
||||||
name_max: NAME_MAX,
|
name_max: NAME_MAX,
|
||||||
|
/* ==== DIE FERTIGEN SÄTZE SIEHT JEDER ======================
|
||||||
|
Sie sind das Angebot an den, der gibt -- ohne sie bliebe
|
||||||
|
nur das freie Feld, und genau das soll die Ausnahme werden
|
||||||
|
und nicht die Regel. Welche Kennung zu welchem Satz gehört,
|
||||||
|
darf jeder wissen; der Text steht ohnehin auf dem Knopf. */
|
||||||
|
/* ==== `fertige_saetze` UND NICHT `saetze` =================
|
||||||
|
`saetze` gehört seit dem 28.09.2026 den MÜNZSÄTZEN (Klassik,
|
||||||
|
Amethyst, Neon). Beim ersten Bau hiess dieses Feld genauso
|
||||||
|
und hat sie überschrieben -- die Münzauswahl im Register
|
||||||
|
„Gestaltung" wäre damit leer gewesen, und zwar lautlos.
|
||||||
|
Gefunden hat es `pruef-spenden` beim ersten Lauf. Zwei
|
||||||
|
Bedeutungen unter einem Namen sind dieselbe Falle wie zwei
|
||||||
|
Regeln für dieselbe Frage. */
|
||||||
|
fertige_saetze: saetzeLesen(),
|
||||||
|
/* Welche Beträge sofort ins Bild dürfen. Der Browser graut
|
||||||
|
den Sofort-Weg sonst nach Gefühl aus oder gar nicht -- und
|
||||||
|
eine Zahl, die er selbst mitbringt, wäre die zweite
|
||||||
|
Antwort auf dieselbe Frage. */
|
||||||
|
sofort_mille: KNOEPFE_MILLE,
|
||||||
|
platz: kartenPlatz(),
|
||||||
/* WAS ICH SELBST HABE, SEHE ICH IMMER. Das ist Filipes
|
/* WAS ICH SELBST HABE, SEHE ICH IMMER. Das ist Filipes
|
||||||
„hinzugefuegt werden": Ohne einen sichtbaren Stand waere es
|
„hinzugefuegt werden": Ohne einen sichtbaren Stand waere es
|
||||||
eine Zahl in einer Datenbank und kein Grund, wiederzukommen. */
|
eine Zahl in einer Datenbank und kein Grund, wiederzukommen. */
|
||||||
@@ -570,13 +750,53 @@ spendenRouter.post("/workspace/api/spenden/melden", express.json({ limit: "4kb"
|
|||||||
erscheint, die offenste Tuer des ganzen Hauses. */
|
erscheint, die offenste Tuer des ganzen Hauses. */
|
||||||
const name = String(req.body?.name ?? req.person.name).trim().slice(0, NAME_MAX)
|
const name = String(req.body?.name ?? req.person.name).trim().slice(0, NAME_MAX)
|
||||||
|| req.person.name;
|
|| req.person.name;
|
||||||
const gruss = String(req.body?.gruss ?? "").trim().slice(0, GRUSS_MAX);
|
|
||||||
|
/* ==== EIN FERTIGER SATZ GEHT SOFORT INS BILD (08.10.2026) ==
|
||||||
|
|
||||||
|
Filipe: „es soll fertige sätze geben und wenn jemand die
|
||||||
|
auswählt muss keiner es bestätigen dan wird es sofort
|
||||||
|
angezeigt und wenn jemand selber was schreibt dan muss
|
||||||
|
bestätigt werden damit es angezeigt wird."
|
||||||
|
|
||||||
|
DER TEXT KOMMT AUS DER DATENBANK UND NICHT AUS DER LEITUNG.
|
||||||
|
Hereingeschickt wird nur `satz_id`. Damit kann an dieser
|
||||||
|
Stelle überhaupt kein fremdes Wort entstehen -- und genau
|
||||||
|
das ist der Grund, warum hier die Bestätigung entfallen
|
||||||
|
darf und beim freien Text nicht.
|
||||||
|
|
||||||
|
GILT NUR FÜR DIE BETRÄGE DER KNÖPFE. Die vollständige
|
||||||
|
Begründung steht in `spenden-tabellen.js`; kurz: Filipes
|
||||||
|
Ansage galt dem SATZ, nicht der Summe, und eine
|
||||||
|
selbstgetippte Zahl ungesehen gross im Stream wäre der
|
||||||
|
Fehler, den man nicht mehr einfangen kann. */
|
||||||
|
const satzId = Number(req.body?.satz_id) || 0;
|
||||||
|
const satz = satzId
|
||||||
|
? db().prepare("SELECT text FROM spenden_saetze WHERE id = ?").get(satzId)
|
||||||
|
: null;
|
||||||
|
/* Eine Kennung, die es nicht gibt, ist ein Fehler und kein
|
||||||
|
„dann eben ohne Text". Wer einen Satz ausgewählt hat und
|
||||||
|
eine leere Karte bekäme, hielte das für kaputt -- zu Recht. */
|
||||||
|
if (satzId && !satz) return res.status(400).json({ fehler: "fertigsatz_unbekannt" });
|
||||||
|
|
||||||
|
const gruss = satz
|
||||||
|
? satz.text
|
||||||
|
: String(req.body?.gruss ?? "").trim().slice(0, GRUSS_MAX);
|
||||||
|
const sofort = !!satz && KNOEPFE_MILLE.includes(Math.round(Number(req.body.dogen_mille)));
|
||||||
|
|
||||||
const { lastInsertRowid } = db().prepare(`INSERT INTO spenden
|
const { lastInsertRowid } = db().prepare(`INSERT INTO spenden
|
||||||
(betrag_cent, waehrung, name, gruss, person_id, herkunft, stand, erstellt)
|
(betrag_cent, waehrung, name, gruss, person_id, herkunft, stand, erstellt)
|
||||||
VALUES (?,?,?,?,?,'gemeldet','offen',?)`)
|
VALUES (?,?,?,?,?,'gemeldet','offen',?)`)
|
||||||
.run(cent, "EUR", name, gruss, req.person.id, jetzt());
|
.run(cent, "EUR", name, gruss, req.person.id, jetzt());
|
||||||
|
|
||||||
const z = db().prepare("SELECT * FROM spenden WHERE id = ?").get(Number(lastInsertRowid));
|
let z = db().prepare("SELECT * FROM spenden WHERE id = ?").get(Number(lastInsertRowid));
|
||||||
|
/* OHNE GUTSCHRIFT. Gezeigt wird sofort, gebucht wird nach der
|
||||||
|
Bestätigung -- sonst stellte sich jeder seine eigene
|
||||||
|
Währung aus. */
|
||||||
|
if (sofort) {
|
||||||
|
zeigen(z, false);
|
||||||
|
z = db().prepare("SELECT * FROM spenden WHERE id = ?").get(Number(lastInsertRowid));
|
||||||
|
}
|
||||||
|
|
||||||
/* Die Leitung erfaehrt es sofort -- sonst liegt die Meldung da,
|
/* Die Leitung erfaehrt es sofort -- sonst liegt die Meldung da,
|
||||||
und der Zuschauer wartet auf eine Karte, die niemand sieht. */
|
und der Zuschauer wartet auf eine Karte, die niemand sieht. */
|
||||||
stromAn(
|
stromAn(
|
||||||
@@ -584,7 +804,7 @@ spendenRouter.post("/workspace/api/spenden/melden", express.json({ limit: "4kb"
|
|||||||
.all().map((p) => p.id),
|
.all().map((p) => p.id),
|
||||||
"spende", { was: "offen", karte: alsKarte(z) },
|
"spende", { was: "offen", karte: alsKarte(z) },
|
||||||
);
|
);
|
||||||
res.status(201).json({ ok: true, wartet: true });
|
res.status(201).json({ ok: true, wartet: !sofort, sofort });
|
||||||
} catch (fehler) {
|
} catch (fehler) {
|
||||||
console.error("[spenden] Melden:", fehler?.message);
|
console.error("[spenden] Melden:", fehler?.message);
|
||||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||||
@@ -686,7 +906,21 @@ spendenRouter.post("/workspace/api/spenden/:id(\\d+)/bestaetigen", nurGeld,
|
|||||||
detail: `#${z.id}, ${centInMille(cent)} Tausendstel Dogen`,
|
detail: `#${z.id}, ${centInMille(cent)} Tausendstel Dogen`,
|
||||||
ip: echteIp(req),
|
ip: echteIp(req),
|
||||||
});
|
});
|
||||||
zeigen(neu);
|
/* ==== WAS SCHON IM BILD WAR, LÄUFT NICHT NOCH EINMAL ========
|
||||||
|
(08.10.2026)
|
||||||
|
|
||||||
|
Eine Karte mit fertigem Satz ist beim Melden sofort gelaufen
|
||||||
|
(siehe `melden`). Die Bestätigung holt danach das nach, was
|
||||||
|
bewusst offen geblieben ist: die GUTSCHRIFT. Sie noch einmal
|
||||||
|
zu zeigen hiesse, dieselbe Spende zweimal im Stream zu
|
||||||
|
haben -- und zwar ausgerechnet mit einigen Minuten Abstand,
|
||||||
|
sodass es wie zwei verschiedene aussieht.
|
||||||
|
|
||||||
|
Wer sie trotzdem noch einmal sehen will, hat dafür den Knopf
|
||||||
|
„Nochmal". Das ist dann eine Entscheidung und kein
|
||||||
|
Nebeneffekt. */
|
||||||
|
if (z.gezeigt_am) gutschreiben(neu);
|
||||||
|
else zeigen(neu);
|
||||||
res.json(alsKarte(neu));
|
res.json(alsKarte(neu));
|
||||||
} catch (fehler) {
|
} catch (fehler) {
|
||||||
console.error("[spenden] Bestaetigen:", fehler?.message);
|
console.error("[spenden] Bestaetigen:", fehler?.message);
|
||||||
@@ -757,7 +991,27 @@ spendenRouter.put("/workspace/api/spenden/stufen", nurGeld,
|
|||||||
if (!Number.isFinite(groesse) || groesse < GROESSE_MIN || groesse > GROESSE_MAX) {
|
if (!Number.isFinite(groesse) || groesse < GROESSE_MIN || groesse > GROESSE_MAX) {
|
||||||
return res.status(400).json({ fehler: "groesse_unklar" });
|
return res.status(400).json({ fehler: "groesse_unklar" });
|
||||||
}
|
}
|
||||||
sauber.push({ ab, name, vorlage, farbe, dauer, groesse, id: Number(z?.id) || 0 });
|
/* ==== WIE LANGE JEMAND IM CHAT BESONDERS AUSSIEHT =========
|
||||||
|
Fehlt der Wert ganz, gilt 0 -- „gar nicht". Das ist keine
|
||||||
|
stille Annahme, sondern die einzige, die nichts kaputt
|
||||||
|
machen kann: Eine ältere Oberfläche, die das Feld noch
|
||||||
|
nicht kennt, schaltet damit den Glanz ab, statt ihn auf
|
||||||
|
einen geratenen Wert zu setzen. */
|
||||||
|
const glanz = Math.round(Number(z?.glanz_minuten ?? 0));
|
||||||
|
if (!Number.isFinite(glanz) || glanz < GLANZ_MIN_MINUTEN || glanz > GLANZ_MAX_MINUTEN) {
|
||||||
|
return res.status(400).json({ fehler: "glanz_unklar" });
|
||||||
|
}
|
||||||
|
sauber.push({ ab, name, vorlage, farbe, dauer, groesse, glanz, id: Number(z?.id) || 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== DER PLATZ DER KARTE GEHÖRT IN DENSELBEN KNOPF ========
|
||||||
|
Er steht im selben Register und wird mit demselben
|
||||||
|
„Übernehmen" gespeichert. Ein eigener Knopf daneben wäre ein
|
||||||
|
zweiter Weg zu derselben Handlung -- und einer davon wird
|
||||||
|
dann vergessen. */
|
||||||
|
const platz = req.body?.platz === undefined ? null : String(req.body.platz);
|
||||||
|
if (platz !== null && !PLAETZE.includes(platz)) {
|
||||||
|
return res.status(400).json({ fehler: "platz_unklar" });
|
||||||
}
|
}
|
||||||
|
|
||||||
sauber.sort((a, b2) => a.ab - b2.ab);
|
sauber.sort((a, b2) => a.ab - b2.ab);
|
||||||
@@ -822,17 +1076,18 @@ spendenRouter.put("/workspace/api/spenden/stufen", nurGeld,
|
|||||||
|
|
||||||
const aendern = db().prepare(`UPDATE spenden_stufen SET
|
const aendern = db().prepare(`UPDATE spenden_stufen SET
|
||||||
ab_cent = ?, name = ?, vorlage = ?, farbe = ?, dauer_ms = ?,
|
ab_cent = ?, name = ?, vorlage = ?, farbe = ?, dauer_ms = ?,
|
||||||
groesse = ?, geaendert = ? WHERE id = ?`);
|
groesse = ?, glanz_minuten = ?, geaendert = ? WHERE id = ?`);
|
||||||
const ein = db().prepare(`INSERT INTO spenden_stufen
|
const ein = db().prepare(`INSERT INTO spenden_stufen
|
||||||
(ab_cent, name, vorlage, bild, farbe, dauer_ms, groesse, geaendert)
|
(ab_cent, name, vorlage, bild, farbe, dauer_ms, groesse, glanz_minuten, geaendert)
|
||||||
VALUES (?,?,?,'',?,?,?,?)`);
|
VALUES (?,?,?,'',?,?,?,?,?)`);
|
||||||
for (const z of sauber) {
|
for (const z of sauber) {
|
||||||
if (z.id && kenneIch.has(z.id)) {
|
if (z.id && kenneIch.has(z.id)) {
|
||||||
aendern.run(z.ab, z.name, z.vorlage, z.farbe, z.dauer, z.groesse, jetzt(), z.id);
|
aendern.run(z.ab, z.name, z.vorlage, z.farbe, z.dauer, z.groesse,
|
||||||
|
z.glanz, jetzt(), z.id);
|
||||||
behalten.add(z.id);
|
behalten.add(z.id);
|
||||||
} else {
|
} else {
|
||||||
const { lastInsertRowid } = ein.run(
|
const { lastInsertRowid } = ein.run(
|
||||||
z.ab, z.name, z.vorlage, z.farbe, z.dauer, z.groesse, jetzt());
|
z.ab, z.name, z.vorlage, z.farbe, z.dauer, z.groesse, z.glanz, jetzt());
|
||||||
behalten.add(Number(lastInsertRowid));
|
behalten.add(Number(lastInsertRowid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -851,21 +1106,79 @@ spendenRouter.put("/workspace/api/spenden/stufen", nurGeld,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (platz !== null) einstellungSetzen(PLATZ_NAME, platz);
|
||||||
|
|
||||||
protokolliere("spenden_stufen", {
|
protokolliere("spenden_stufen", {
|
||||||
personId: req.person.id,
|
personId: req.person.id,
|
||||||
detail: `${sauber.length} Stufen gespeichert`,
|
detail: `${sauber.length} Stufen gespeichert`,
|
||||||
ip: echteIp(req),
|
ip: echteIp(req),
|
||||||
});
|
});
|
||||||
res.json({ ok: true, stufen: stufenLesen() });
|
res.json({ ok: true, stufen: stufenLesen(), platz: kartenPlatz() });
|
||||||
} catch (fehler) {
|
} catch (fehler) {
|
||||||
console.error("[spenden] Stufen:", fehler?.message);
|
console.error("[spenden] Stufen:", fehler?.message);
|
||||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* ======================================================================
|
||||||
|
DIE FERTIGEN SÄTZE PFLEGEN
|
||||||
|
|
||||||
|
ALLE AUF EINMAL, wie die Stufenleiter -- und aus demselben Grund:
|
||||||
|
Eine Liste, die man Zeile für Zeile speichert, geht durch
|
||||||
|
Zwischenstände, in denen sie halb die alte und halb die neue ist.
|
||||||
|
Mitten in einer Sendung wählt dann jemand einen Satz aus, den es
|
||||||
|
eine Sekunde später nicht mehr gibt.
|
||||||
|
|
||||||
|
SIE BEKOMMEN NEUE KENNUNGEN, UND DAS IST HIER IN ORDNUNG. Anders
|
||||||
|
als an einer Stufe hängt an einem Satz nichts (kein Bild, keine
|
||||||
|
Datei). Was schon im Bild stand, trägt seinen Text längst als Text
|
||||||
|
in der Spendenzeile -- ein gelöschter Satz ändert rückwirkend also
|
||||||
|
nichts an dem, was jemand einmal gesagt hat.
|
||||||
|
====================================================================== */
|
||||||
|
spendenRouter.put("/workspace/api/spenden/fertige-saetze", nurGeld,
|
||||||
|
express.json({ limit: "8kb" }), (req, res) => {
|
||||||
|
try {
|
||||||
|
const roh = Array.isArray(req.body?.fertige_saetze) ? req.body.fertige_saetze : null;
|
||||||
|
if (!roh) return res.status(400).json({ fehler: "saetze_fehlen" });
|
||||||
|
if (roh.length > SAETZE_MAX) return res.status(400).json({ fehler: "zu_viele_saetze" });
|
||||||
|
|
||||||
|
const sauber = [];
|
||||||
|
for (const z of roh) {
|
||||||
|
const t = String(z ?? "").trim().slice(0, GRUSS_MAX);
|
||||||
|
/* Leere Zeilen werden weggelassen und nicht abgelehnt: Wer
|
||||||
|
einen Satz löschen will, leert sein Feld -- das ist der
|
||||||
|
naheliegendste Weg, und ihn mit einer Fehlermeldung zu
|
||||||
|
beantworten wäre eine Belehrung. */
|
||||||
|
if (t) sauber.push(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
db().exec("BEGIN IMMEDIATE");
|
||||||
|
try {
|
||||||
|
db().exec("DELETE FROM spenden_saetze");
|
||||||
|
const ein = db().prepare("INSERT INTO spenden_saetze (text, platz, geaendert)"
|
||||||
|
+ " VALUES (?,?,?)");
|
||||||
|
sauber.forEach((t, i) => ein.run(t, i, jetzt()));
|
||||||
|
db().exec("COMMIT");
|
||||||
|
} catch (f) {
|
||||||
|
db().exec("ROLLBACK");
|
||||||
|
throw f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protokolliere("spenden_saetze", {
|
||||||
|
personId: req.person.id,
|
||||||
|
detail: `${sauber.length} fertige Sätze gespeichert`,
|
||||||
|
ip: echteIp(req),
|
||||||
|
});
|
||||||
|
res.json({ ok: true, fertige_saetze: saetzeLesen() });
|
||||||
|
} catch (fehler) {
|
||||||
|
console.error("[spenden] Sätze:", fehler?.message);
|
||||||
|
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function stufenLesen() {
|
function stufenLesen() {
|
||||||
return db().prepare("SELECT id, ab_cent, name, vorlage, bild, farbe, dauer_ms,"
|
return db().prepare("SELECT id, ab_cent, name, vorlage, bild, farbe, dauer_ms,"
|
||||||
+ " groesse FROM spenden_stufen ORDER BY ab_cent").all()
|
+ " groesse, glanz_minuten FROM spenden_stufen ORDER BY ab_cent").all()
|
||||||
.map((z) => ({
|
.map((z) => ({
|
||||||
id: z.id,
|
id: z.id,
|
||||||
/* AUCH DIE GRENZE IST EINE ZAHL IN DOGEN. `ab_cent` bleibt der
|
/* AUCH DIE GRENZE IST EINE ZAHL IN DOGEN. `ab_cent` bleibt der
|
||||||
@@ -877,6 +1190,7 @@ function stufenLesen() {
|
|||||||
name: z.name, vorlage: z.vorlage, bild: bildAdresse(z.bild),
|
name: z.name, vorlage: z.vorlage, bild: bildAdresse(z.bild),
|
||||||
farbe: z.farbe, dauer_ms: z.dauer_ms,
|
farbe: z.farbe, dauer_ms: z.dauer_ms,
|
||||||
groesse: Number(z.groesse) || 1,
|
groesse: Number(z.groesse) || 1,
|
||||||
|
glanz_minuten: Number(z.glanz_minuten) || 0,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-14
@@ -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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/anleitung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/anleitung.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="halle">
|
<body class="start" data-buehne="halle">
|
||||||
@@ -289,16 +289,16 @@
|
|||||||
|
|
||||||
Und anleitung.js braucht es doppelt: Symbol, Farbe, Name und
|
Und anleitung.js braucht es doppelt: Symbol, Farbe, Name und
|
||||||
Adresse jeder Karte kommen von dort, nicht vom Server. -->
|
Adresse jeder Karte kommen von dort, nicht vom Server. -->
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" 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=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/anleitung.js?v=202610072346" defer></script>
|
<script src="assets/js/anleitung.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -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=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<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=202610072346" defer></script>
|
<script src="assets/js/anruf-probe.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -23,25 +23,25 @@
|
|||||||
},
|
},
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/workspace-192.png?v=202610072346",
|
"src": "/assets/img/app-symbole/workspace-192.png?v=202610080131",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/workspace-512.png?v=202610072346",
|
"src": "/assets/img/app-symbole/workspace-512.png?v=202610080131",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202610072346",
|
"src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202610080131",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202610072346",
|
"src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202610080131",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,28 +1,151 @@
|
|||||||
/* =====================================================================
|
/* =====================================================================
|
||||||
DIE SPENDENKARTE (28.09.2026)
|
DIE SPENDENKARTE (28.09.2026, Mitte und Tiefe am 08.10.2026)
|
||||||
|
|
||||||
Eigenes Stilblatt, weil dieselbe Karte an zwei Orten laeuft: in der
|
Eigenes Stilblatt, weil dieselbe Karte an zwei Orten laeuft: in der
|
||||||
Reaction-Seite und -- spaeter -- als eigene Seite fuer OBS und
|
Reaction-Seite und als eigene Seite (`tafel.html`) fuer OBS und
|
||||||
TikTok Studio. Zweimal gestaltet hiesse: Bei der naechsten
|
TikTok Studio. Zweimal gestaltet hiesse: Bei der naechsten
|
||||||
Aenderung sieht sie an einem der beiden Orte anders aus, und man
|
Aenderung sieht sie an einem der beiden Orte anders aus, und man
|
||||||
merkt es erst im Livestream.
|
merkt es erst im Livestream.
|
||||||
|
|
||||||
SIE IST GROSS, KURZ UND WEG. Wer etwas gibt, soll es sehen; wer
|
---------------------------------------------------------------------
|
||||||
zusieht, soll das Video nicht verlieren. Deshalb kommt sie von der
|
SIE STEHT JETZT IN DER MITTE (08.10.2026)
|
||||||
Seite, steht ein paar Sekunden am Rand und geht wieder -- sie
|
|
||||||
deckt nie die Mitte zu.
|
Filipe: „die spende soll auch in der mitte vom bild angezeigt
|
||||||
|
werden. es soll richtig geil angezeigt werden so richtig in 3D
|
||||||
|
modus."
|
||||||
|
|
||||||
|
Hier stand bis heute das Gegenteil, woertlich: „sie deckt nie die
|
||||||
|
Mitte zu." Diese Begruendung war richtig und ist es immer noch —
|
||||||
|
nur beantwortet sie eine andere Frage. Sie schuetzt das VIDEO.
|
||||||
|
Filipe sieht die Spende als das, was in diesem Augenblick zaehlt,
|
||||||
|
und das ist seine Entscheidung.
|
||||||
|
|
||||||
|
DER ALTE PLATZ BLEIBT TROTZDEM ERHALTEN und ist einen Knopf weit
|
||||||
|
weg („Gestaltung → Wo die Karte steht"). Bei einem Film, bei dem
|
||||||
|
ein Deckel in der Mitte stoert, ist er der bessere — und eine
|
||||||
|
Festlegung, die man nicht zuruecknehmen kann, ist keine
|
||||||
|
Einstellung.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
WARUM DIE KARTE AUS ZWEI TEILEN BESTEHT
|
||||||
|
|
||||||
|
Aussen `.spendenkarte-auftritt`, innen `.spendenkarte`. Das ist
|
||||||
|
kein Umweg, sondern die einzige Form, in der echte Tiefe
|
||||||
|
funktioniert:
|
||||||
|
|
||||||
|
`opacity` unter 1, `filter`, `backdrop-filter`, `overflow: hidden`
|
||||||
|
und `mask` zwingen ein Element laut CSS-Transforms-2 auf
|
||||||
|
`transform-style: flat`. Eine Karte, die beim Hereinkommen ihre
|
||||||
|
Deckkraft aendert, ist in genau dieser Zeit also FLACH — und
|
||||||
|
sobald die Deckkraft 1 erreicht, springt sie in einem einzigen
|
||||||
|
Bild in die Tiefe. Dieses Springen sieht man.
|
||||||
|
|
||||||
|
Also: Die Huelle macht das Erscheinen (Deckkraft + Flug aus der
|
||||||
|
Tiefe), die Karte darin macht die Form. Beide haben ihre eigene
|
||||||
|
Umformung, und sie setzen sich durch die Verschachtelung
|
||||||
|
zusammen, statt sich gegenseitig zu ueberschreiben.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
EINE NACH DER ANDEREN
|
||||||
|
|
||||||
|
Zwei Spenden gleichzeitig sind keine Seltenheit — wenn es im Live
|
||||||
|
gut laeuft, kommen drei in zehn Sekunden. Uebereinander gelegt
|
||||||
|
waere keine mehr lesbar, und ausgerechnet die groesste ginge
|
||||||
|
unter. Die Schlange steht in `spendenkarte.js`.
|
||||||
|
===================================================================== */
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DER KASTEN — UND WO DARIN DIE KARTE STEHT
|
||||||
|
|
||||||
|
`perspective` steht HIER und nicht an der Karte: Ein Fluchtpunkt
|
||||||
|
gehoert zum Raum, nicht zum Gegenstand darin. Saesse er an der
|
||||||
|
Karte, haette jede Karte ihren eigenen, und zwei nacheinander
|
||||||
|
kaemen aus verschiedenen Richtungen.
|
||||||
|
|
||||||
|
1200 Pixel sind gemessen und nicht gegriffen: Darunter kippt die
|
||||||
|
Karte beim Hereinkommen so stark, dass die Schrift auf der
|
||||||
|
oberen Haelfte zerlaeuft; darueber ist von der Tiefe nichts mehr
|
||||||
|
zu sehen und man haette sie auch weglassen koennen.
|
||||||
===================================================================== */
|
===================================================================== */
|
||||||
.spendentafel {
|
.spendentafel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0; right: 0; bottom: 84px;
|
inset: 0;
|
||||||
z-index: 45;
|
z-index: 45;
|
||||||
display: grid; gap: 10px;
|
display: grid;
|
||||||
justify-items: start;
|
gap: 10px;
|
||||||
padding: 0 18px;
|
padding: 18px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
perspective: 1200px;
|
||||||
|
perspective-origin: 50% 44%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==== DIE GROESSE ==================================================
|
/* MITTE: die Karte steht im Bild, nicht daneben. */
|
||||||
|
.spendentafel[data-platz="mitte"] {
|
||||||
|
align-content: center;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
/* RAND: der alte Platz — unten links, ueber dem unteren Bildrand.
|
||||||
|
Die 84 Pixel sind der Abstand zur Transportleiste; eine Karte
|
||||||
|
darauf waere halb verdeckt. */
|
||||||
|
.spendentafel[data-platz="rand"] {
|
||||||
|
align-content: end;
|
||||||
|
justify-items: start;
|
||||||
|
padding: 0 18px 84px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DIE HUELLE — SIE MACHT DAS ERSCHEINEN
|
||||||
|
===================================================================== */
|
||||||
|
.spendenkarte-auftritt {
|
||||||
|
/* Damit die Tiefe durch die Huelle hindurch bis zur Karte reicht.
|
||||||
|
Ohne das projiziert der Browser die Karte in die Ebene der
|
||||||
|
Huelle, und jede Drehung darin sieht aus wie eine Verzerrung. */
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
max-width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
|
||||||
|
/* ==== DER FLUG AUS DER TIEFE ====================================
|
||||||
|
Von weit hinten, leicht nach hinten gekippt, nach vorn auf
|
||||||
|
ihren Platz. `translate3d` und `rotateX` rechnet der Browser auf
|
||||||
|
der Grafikkarte — alles andere (Breite, Rand, Abstand) laesst
|
||||||
|
das Bild ruckeln, und ein ruckelnder Dank ist schlimmer als
|
||||||
|
keiner.
|
||||||
|
|
||||||
|
Die Kurve (.16, 1, .3, 1) bremst am Ende sehr weich aus. Eine
|
||||||
|
lineare Bewegung sieht aus wie ein Dia, das eingeschoben wird;
|
||||||
|
diese sieht aus wie etwas, das ankommt. */
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(0, 14px, -360px) rotateX(26deg) scale(.94);
|
||||||
|
transition:
|
||||||
|
opacity .42s ease,
|
||||||
|
transform .62s cubic-bezier(.16, 1, .3, 1);
|
||||||
|
}
|
||||||
|
.spendenkarte-auftritt[data-da="ja"] {
|
||||||
|
opacity: 1;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
/* Beim Gehen faellt sie nach hinten weg statt einfach zu
|
||||||
|
verblassen — dieselbe Richtung, aus der sie kam. */
|
||||||
|
.spendenkarte-auftritt[data-da="nein"] {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(0, -10px, -220px) rotateX(-14deg) scale(.97);
|
||||||
|
transition:
|
||||||
|
opacity .34s ease,
|
||||||
|
transform .42s cubic-bezier(.4, 0, .9, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Am Rand kommt sie weiterhin von der Seite. Das ist dort richtig:
|
||||||
|
Eine Karte, die am unteren Bildrand aus der Tiefe geflogen kommt,
|
||||||
|
waere eine grosse Bewegung fuer eine kleine Nebensache. */
|
||||||
|
.spendentafel[data-platz="rand"] .spendenkarte-auftritt {
|
||||||
|
transform: translate3d(-28px, 0, 0) scale(.96);
|
||||||
|
}
|
||||||
|
.spendentafel[data-platz="rand"] .spendenkarte-auftritt[data-da="nein"] {
|
||||||
|
transform: translate3d(-18px, 0, 0) scale(.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
DIE GROESSE
|
||||||
|
|
||||||
Filipe: „auch so dass ich das anders gestalten kann oder die
|
Filipe: „auch so dass ich das anders gestalten kann oder die
|
||||||
größe verändern kann."
|
größe verändern kann."
|
||||||
@@ -33,15 +156,17 @@
|
|||||||
Faktor, und die ganze Karte wächst gleichmäßig mit.
|
Faktor, und die ganze Karte wächst gleichmäßig mit.
|
||||||
|
|
||||||
Der naheliegende Weg wäre `transform: scale()` gewesen. Der geht
|
Der naheliegende Weg wäre `transform: scale()` gewesen. Der geht
|
||||||
hier nicht: Die Karte kommt mit `transform: translateX()` herein,
|
hier nicht: `scale()` skaliert auch die Schriftglättung mit, und
|
||||||
und zwei `transform` an derselben Stelle schließen einander aus —
|
Text wird dabei sichtbar matschig. Eine Schriftgröße tut das
|
||||||
entweder die Größe oder die Bewegung. Außerdem skaliert `scale()`
|
nicht. (Bis zum 08.10. stand hier zusätzlich, dass `transform`
|
||||||
auch die Schriftglättung mit, und Text wird dabei sichtbar
|
schon für die Bewegung gebraucht wird — das stimmt seit der
|
||||||
matschig. Eine Schriftgröße tut das nicht. */
|
Huelle nicht mehr, der erste Grund genügt aber allein.)
|
||||||
|
===================================================================== */
|
||||||
.spendenkarte {
|
.spendenkarte {
|
||||||
--sp-farbe: #8ec9ff;
|
--sp-farbe: #8ec9ff;
|
||||||
--sp-gross: 1;
|
--sp-gross: 1;
|
||||||
font-size: calc(1rem * var(--sp-gross));
|
font-size: calc(1rem * var(--sp-gross));
|
||||||
|
position: relative;
|
||||||
display: flex; align-items: center; gap: .875em;
|
display: flex; align-items: center; gap: .875em;
|
||||||
max-width: min(30em, 78%);
|
max-width: min(30em, 78%);
|
||||||
padding: .8125em 1.25em .8125em .875em;
|
padding: .8125em 1.25em .8125em .875em;
|
||||||
@@ -57,21 +182,133 @@
|
|||||||
inset 0 1px 0 color-mix(in srgb, var(--sp-farbe) 40%, transparent);
|
inset 0 1px 0 color-mix(in srgb, var(--sp-farbe) 40%, transparent);
|
||||||
backdrop-filter: blur(14px) saturate(1.25);
|
backdrop-filter: blur(14px) saturate(1.25);
|
||||||
-webkit-backdrop-filter: blur(14px) saturate(1.25);
|
-webkit-backdrop-filter: blur(14px) saturate(1.25);
|
||||||
/* Die Karte kommt von links herein. `translate` und `opacity`
|
|
||||||
rechnet der Browser auf der Grafikkarte -- alles andere
|
|
||||||
(Breite, Rand, Abstand) laesst das Bild ruckeln, und ein
|
|
||||||
ruckelnder Dank ist schlimmer als keiner. */
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateX(-28px) scale(.96);
|
|
||||||
transition: opacity .45s ease, transform .45s cubic-bezier(.22, 1, .3, 1);
|
|
||||||
}
|
}
|
||||||
.spendenkarte[data-da="ja"] { opacity: 1; transform: none; }
|
|
||||||
|
/* =====================================================================
|
||||||
|
IN DER MITTE WIRD AUS DER ZEILE EIN AUFSTELLER (08.10.2026)
|
||||||
|
|
||||||
|
Eine waagerechte Karte ist am Bildrand richtig: Sie nimmt wenig
|
||||||
|
Höhe und liest sich im Vorbeischauen. In der Mitte des Bildes
|
||||||
|
wirkt dieselbe Form wie ein Hinweisbalken — man schiebt sie
|
||||||
|
gedanklich weg.
|
||||||
|
|
||||||
|
Hier steht sie deshalb als Säule: Münze oben, Betrag groß darunter,
|
||||||
|
dann wer, dann was er geschrieben hat. Das ist die Reihenfolge,
|
||||||
|
in der man es wissen will, und es ist die Form, die jeder von
|
||||||
|
Spenden-Einblendungen kennt.
|
||||||
|
===================================================================== */
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: .45em;
|
||||||
|
/* Grösser als am Rand — hier IST sie der Augenblick. Der Faktor
|
||||||
|
der Stufe multipliziert weiter mit. */
|
||||||
|
font-size: calc(1.3rem * var(--sp-gross));
|
||||||
|
max-width: min(20em, 88%);
|
||||||
|
padding: 1.45em 1.6em 1.5em;
|
||||||
|
border-radius: 1.4em;
|
||||||
|
background:
|
||||||
|
/* Ein Lichtkegel von oben statt eines Farbverlaufs von links.
|
||||||
|
Er macht aus der Fläche einen Körper, der angestrahlt wird. */
|
||||||
|
radial-gradient(120% 86% at 50% -8%,
|
||||||
|
color-mix(in srgb, var(--sp-farbe) 34%, transparent), transparent 62%),
|
||||||
|
linear-gradient(180deg, rgba(18, 15, 28, .94), rgba(8, 6, 14, .96));
|
||||||
|
box-shadow:
|
||||||
|
/* Der Hof. Er liegt WEIT draußen und sehr schwach — ein harter
|
||||||
|
Schein um eine Karte in der Bildmitte wäre genau das Grelle,
|
||||||
|
das in diesem Haus nirgends vorkommt. */
|
||||||
|
0 0 160px -40px var(--sp-farbe),
|
||||||
|
0 42px 80px -30px #000,
|
||||||
|
inset 0 1px 0 color-mix(in srgb, var(--sp-farbe) 52%, transparent),
|
||||||
|
inset 0 -1px 0 rgba(0, 0, 0, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Die Kante, die den Körper macht -------------------------------
|
||||||
|
Ein einzelner Rahmen ist eine Linie. Zwei Linien mit einem
|
||||||
|
Zwischenraum sind eine KANTE — und eine Kante hat eine Dicke, also
|
||||||
|
eine Tiefe. Das ist derselbe Trick wie an einem Möbelstück: Man
|
||||||
|
sieht nicht das Holz, man sieht die Fase. */
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 1px;
|
||||||
|
border-radius: inherit;
|
||||||
|
border: 1px solid color-mix(in srgb, var(--sp-farbe) 16%, transparent);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Der Lichtstreifen ----------------------------------------------
|
||||||
|
Er läuft EINMAL über die Karte, von links unten nach rechts oben,
|
||||||
|
und ist danach weg.
|
||||||
|
|
||||||
|
EINMAL UND NICHT IN EINER SCHLEIFE. Ein Glanz, der alle zwei
|
||||||
|
Sekunden wiederkommt, ist ein Blinken — und daneben läuft ein
|
||||||
|
Video. Ein einziger Streifen sagt „das hier ist gerade passiert";
|
||||||
|
ein wiederkehrender sagt gar nichts mehr und belastet die Augen.
|
||||||
|
|
||||||
|
`overflow: hidden` steht am Streifen und NICHT an der Karte: An
|
||||||
|
der Karte würde es sie flachdrücken (siehe der Kopf dieser Datei)
|
||||||
|
und obendrein den Hof abschneiden. */
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
border-radius: inherit;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
background:
|
||||||
|
linear-gradient(104deg,
|
||||||
|
transparent 38%,
|
||||||
|
rgba(255, 255, 255, .13) 48%,
|
||||||
|
rgba(255, 255, 255, .2) 50%,
|
||||||
|
rgba(255, 255, 255, .13) 52%,
|
||||||
|
transparent 62%);
|
||||||
|
background-size: 260% 100%;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 170% 0;
|
||||||
|
animation: sp-glanz 1.25s .34s cubic-bezier(.3, .1, .2, 1) 1 both;
|
||||||
|
}
|
||||||
|
@keyframes sp-glanz {
|
||||||
|
from { background-position: 170% 0; }
|
||||||
|
to { background-position: -70% 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Das sanfte Wiegen ----------------------------------------------
|
||||||
|
Zweieinhalb Grad, hin und her, in neun Sekunden. Das ist so
|
||||||
|
langsam, dass man es nicht als Bewegung liest, sondern als Tiefe:
|
||||||
|
Das Licht auf der Kante wandert, und erst daran sieht das Auge,
|
||||||
|
dass die Karte im Raum steht und nicht auf dem Glas klebt.
|
||||||
|
|
||||||
|
Sie sitzt an der KARTE und nicht an der Hülle: Die Hülle macht das
|
||||||
|
Erscheinen, und zwei Bewegungen an derselben Eigenschaft
|
||||||
|
überschreiben einander (die spätere gewinnt vollständig — sie
|
||||||
|
mischen sich nicht).
|
||||||
|
|
||||||
|
Die Verzögerung von 0,8 s ist der Flug: Während die Hülle noch
|
||||||
|
unterwegs ist, ist sie wegen ihrer Deckkraft ohnehin flach, und
|
||||||
|
eine Drehung darin wäre dort eine Verzerrung. */
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte {
|
||||||
|
animation: sp-wiegen 9s .8s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes sp-wiegen {
|
||||||
|
0% { transform: rotateY(-2.5deg) rotateX(1.1deg); }
|
||||||
|
50% { transform: rotateY(2.5deg) rotateX(-1.1deg); }
|
||||||
|
100% { transform: rotateY(-2.5deg) rotateX(1.1deg); }
|
||||||
|
}
|
||||||
|
|
||||||
.spendenkarte__bild {
|
.spendenkarte__bild {
|
||||||
flex: none;
|
flex: none;
|
||||||
width: 3.375em; height: 3.375em;
|
width: 3.375em; height: 3.375em;
|
||||||
display: grid; place-items: center;
|
display: grid; place-items: center;
|
||||||
}
|
}
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__bild {
|
||||||
|
width: 4.6em; height: 4.6em;
|
||||||
|
/* Die Münze wirft einen eigenen Schatten auf die Karte. Damit
|
||||||
|
liegt sie DARAUF und ist nicht hineingedruckt — das ist die
|
||||||
|
billigste und zugleich deutlichste Tiefe, die es gibt. */
|
||||||
|
filter: drop-shadow(0 .22em .3em rgba(0, 0, 0, .66));
|
||||||
|
}
|
||||||
.spendenkarte__bild svg { width: 100%; height: 100%; }
|
.spendenkarte__bild svg { width: 100%; height: 100%; }
|
||||||
.spendenkarte__bild img {
|
.spendenkarte__bild img {
|
||||||
width: 100%; height: 100%;
|
width: 100%; height: 100%;
|
||||||
@@ -83,11 +320,41 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.spendenkarte__text { display: grid; gap: 1px; min-width: 0; }
|
.spendenkarte__text { display: grid; gap: 1px; min-width: 0; }
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__text {
|
||||||
|
gap: .2em;
|
||||||
|
justify-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== IN DER MITTE STEHT DER BETRAG OBEN ==========================
|
||||||
|
|
||||||
|
Am Rand liest man die Karte wie eine Zeile: wer, wie viel. In der
|
||||||
|
Mitte ist sie ein Augenblick, und darin ist die ZAHL das Erste —
|
||||||
|
so macht es jede Einblendung, die man kennt, und aus gutem Grund:
|
||||||
|
Sie steht drei Sekunden da, und in drei Sekunden liest niemand
|
||||||
|
zwei Zeilen von oben nach unten.
|
||||||
|
|
||||||
|
DAS DOKUMENT BLEIBT, WIE ES IST. `order` ändert nur die Anzeige;
|
||||||
|
ein Vorleseprogramm hört weiterhin „Lenny, 2,5 Dogen, Starke
|
||||||
|
Runde, …" und damit den Satz, der sich von selbst versteht. Die
|
||||||
|
Reihenfolge im Quelltext umzubauen hätte die Karte am Rand
|
||||||
|
mitgedreht — zwei Fassungen desselben Dinges, und eine davon
|
||||||
|
wäre nach dem nächsten Umbau falsch. */
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__betrag { order: 1; }
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__wer { order: 2; }
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__stufe { order: 3; }
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__gruss { order: 4; }
|
||||||
.spendenkarte__wer {
|
.spendenkarte__wer {
|
||||||
font-size: .8em; font-weight: 700;
|
font-size: .8em; font-weight: 700;
|
||||||
letter-spacing: .03em;
|
letter-spacing: .03em;
|
||||||
color: color-mix(in srgb, var(--sp-farbe) 30%, #ffffff);
|
color: color-mix(in srgb, var(--sp-farbe) 30%, #ffffff);
|
||||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__wer {
|
||||||
|
font-size: .86em;
|
||||||
|
letter-spacing: .09em; text-transform: uppercase;
|
||||||
|
opacity: .9;
|
||||||
}
|
}
|
||||||
.spendenkarte__betrag {
|
.spendenkarte__betrag {
|
||||||
font-size: 1.62em; font-weight: 900;
|
font-size: 1.62em; font-weight: 900;
|
||||||
@@ -97,12 +364,22 @@
|
|||||||
einen eigenen Schein. */
|
einen eigenen Schein. */
|
||||||
text-shadow: 0 0 22px color-mix(in srgb, var(--sp-farbe) 60%, transparent);
|
text-shadow: 0 0 22px color-mix(in srgb, var(--sp-farbe) 60%, transparent);
|
||||||
}
|
}
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__betrag {
|
||||||
|
font-size: 2.15em;
|
||||||
|
/* Zwei Schatten: einer eng und dunkel (er hebt die Ziffern von der
|
||||||
|
Fläche ab), einer weit und farbig (er ist der Schein). Mit nur
|
||||||
|
dem farbigen verschwimmt die Zahl auf hellem Grund. */
|
||||||
|
text-shadow:
|
||||||
|
0 .04em .06em rgba(0, 0, 0, .55),
|
||||||
|
0 0 .7em color-mix(in srgb, var(--sp-farbe) 62%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
/* ==== ZAHL, ZEICHEN UND WORT GEHOEREN ZUSAMMEN =====================
|
/* ==== ZAHL, ZEICHEN UND WORT GEHOEREN ZUSAMMEN =====================
|
||||||
|
|
||||||
Filipe: „man soll nie die summe sehen sondern die dogen auch mit
|
Filipe: „man soll nie die summe sehen sondern die dogen auch mit
|
||||||
dem symbol."
|
dem symbol."
|
||||||
|
|
||||||
Das Stueck steht auf der Karte, in den Listen im Pult, an den
|
Das Stueck steht auf der Karte, in zwei Listen im Pult, an den
|
||||||
Knoepfen und beim eigenen Stand -- und ueberall gleich. Es rechnet
|
Knoepfen und beim eigenen Stand -- und ueberall gleich. Es rechnet
|
||||||
in `em`, damit es die Groesse seiner Umgebung annimmt: auf der
|
in `em`, damit es die Groesse seiner Umgebung annimmt: auf der
|
||||||
Karte gross, in einer Liste klein, ohne eine einzige zweite Zahl.
|
Karte gross, in einer Liste klein, ohne eine einzige zweite Zahl.
|
||||||
@@ -166,6 +443,18 @@
|
|||||||
letter-spacing: .12em; text-transform: uppercase;
|
letter-spacing: .12em; text-transform: uppercase;
|
||||||
color: color-mix(in srgb, var(--sp-farbe) 22%, #ffffff);
|
color: color-mix(in srgb, var(--sp-farbe) 22%, #ffffff);
|
||||||
}
|
}
|
||||||
|
/* In der Mitte wird aus dem Wort ein Schild. Es benennt den Rang und
|
||||||
|
trägt dessen Farbe — damit ist es das Einzige auf der Karte, das
|
||||||
|
die Stufe NENNT statt sie nur anzudeuten. */
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__stufe {
|
||||||
|
margin-top: .15em;
|
||||||
|
padding: .28em .85em .32em;
|
||||||
|
border-radius: 999px;
|
||||||
|
color: color-mix(in srgb, var(--sp-farbe) 30%, #ffffff);
|
||||||
|
background: color-mix(in srgb, var(--sp-farbe) 17%, transparent);
|
||||||
|
border: 1px solid color-mix(in srgb, var(--sp-farbe) 42%, transparent);
|
||||||
|
box-shadow: inset 0 1px 0 color-mix(in srgb, var(--sp-farbe) 34%, transparent);
|
||||||
|
}
|
||||||
.spendenkarte__gruss {
|
.spendenkarte__gruss {
|
||||||
margin: .3125em 0 0;
|
margin: .3125em 0 0;
|
||||||
font-size: .86em; line-height: 1.4;
|
font-size: .86em; line-height: 1.4;
|
||||||
@@ -175,19 +464,67 @@
|
|||||||
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
|
display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__gruss {
|
||||||
|
margin-top: .45em;
|
||||||
|
font-size: .78em;
|
||||||
|
color: #d9d4e8;
|
||||||
|
/* Anführungszeichen, weil es ein Zitat ist: Das hat jemand
|
||||||
|
geschrieben, das sagt nicht die Sendung. */
|
||||||
|
quotes: "\201E" "\201C";
|
||||||
|
}
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__gruss::before { content: open-quote; }
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__gruss::after { content: close-quote; }
|
||||||
|
|
||||||
/* Wer weniger Bewegung eingestellt hat, bekommt die Karte trotzdem --
|
/* =====================================================================
|
||||||
sie steht dann einfach da. Die Aussage ist wichtiger als der Weg. */
|
WER WENIGER BEWEGUNG EINGESTELLT HAT
|
||||||
|
|
||||||
|
Bekommt die Karte trotzdem — sie steht dann einfach da. Die
|
||||||
|
Aussage ist wichtiger als der Weg.
|
||||||
|
|
||||||
|
ALLE DREI BEWEGUNGEN GEHEN WEG, nicht nur die auffälligste: der
|
||||||
|
Flug, das Wiegen und der Lichtstreifen. Eine davon stehen zu
|
||||||
|
lassen, weil sie „ja klein ist", ist genau die Entscheidung, die
|
||||||
|
man nicht für jemand anderen treffen darf.
|
||||||
|
===================================================================== */
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.spendenkarte { transition: opacity .2s linear; transform: none; }
|
.spendenkarte-auftritt {
|
||||||
|
transition: opacity .2s linear;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
.spendenkarte-auftritt[data-da="nein"] {
|
||||||
|
transition: opacity .2s linear;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
.spendentafel[data-platz="rand"] .spendenkarte-auftritt,
|
||||||
|
.spendentafel[data-platz="rand"] .spendenkarte-auftritt[data-da="nein"] {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte { animation: none; }
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte::after { animation: none; opacity: 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =====================================================================
|
||||||
|
AM HANDY
|
||||||
|
|
||||||
|
Die Mitte bleibt die Mitte — nur kleiner. Ein Aufsteller, der auf
|
||||||
|
einem 390 Pixel breiten Bild in seiner Rechnergröße erschiene,
|
||||||
|
deckte das ganze Video zu.
|
||||||
|
===================================================================== */
|
||||||
@media (max-width: 860px) {
|
@media (max-width: 860px) {
|
||||||
.spendentafel { bottom: 12px; padding: 0 10px; }
|
.spendentafel { padding: 10px; }
|
||||||
|
.spendentafel[data-platz="rand"] { padding: 0 10px 12px; }
|
||||||
.spendenkarte {
|
.spendenkarte {
|
||||||
max-width: 92%;
|
max-width: 92%;
|
||||||
gap: .625em; padding: .625em .875em .625em .625em;
|
gap: .625em; padding: .625em .875em .625em .625em;
|
||||||
}
|
}
|
||||||
.spendenkarte__bild { width: 2.625em; height: 2.625em; }
|
.spendenkarte__bild { width: 2.625em; height: 2.625em; }
|
||||||
.spendenkarte__betrag { font-size: 1.3em; }
|
.spendenkarte__betrag { font-size: 1.3em; }
|
||||||
|
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte {
|
||||||
|
font-size: calc(1rem * var(--sp-gross));
|
||||||
|
max-width: 86%;
|
||||||
|
padding: 1.1em 1.2em 1.2em;
|
||||||
|
}
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__bild { width: 3.5em; height: 3.5em; }
|
||||||
|
.spendentafel[data-platz="mitte"] .spendenkarte__betrag { font-size: 1.85em; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,6 +325,33 @@
|
|||||||
sendest_nicht:
|
sendest_nicht:
|
||||||
'Kamera und Mikro schaltet nur, wer gerade sendet – '
|
'Kamera und Mikro schaltet nur, wer gerade sendet – '
|
||||||
+ 'der Host oder ein Gast auf der Bühne.',
|
+ 'der Host oder ein Gast auf der Bühne.',
|
||||||
|
/* ---- Die Einladung (08.10.2026) ---- */
|
||||||
|
keine_einladung:
|
||||||
|
'Für dich liegt gerade keine Einladung vor. '
|
||||||
|
+ 'Vielleicht wurde sie zurückgezogen – DogFather kann dich neu einladen.',
|
||||||
|
einladung_abgelaufen:
|
||||||
|
'Diese Einladung ist abgelaufen. Sag kurz Bescheid, '
|
||||||
|
+ 'dann lädt DogFather dich neu ein.',
|
||||||
|
/* ---- Die Spenden (08.10.2026) ---- */
|
||||||
|
/* `fertigsatz_` und nicht `satz_`: `satz_unbekannt` gehört seit
|
||||||
|
dem 28.09.2026 dem MÜNZSATZ. Zwei Bedeutungen unter einem Wort
|
||||||
|
heißen, dass eine von beiden irgendwann den falschen Satz
|
||||||
|
bekommt — und gefunden hätte man es erst an der Fehlermeldung
|
||||||
|
vor einem Zuschauer. Die Prüfung hat die Dopplung gemeldet,
|
||||||
|
bevor sie jemand gesehen hat. */
|
||||||
|
fertigsatz_unbekannt:
|
||||||
|
'Diesen fertigen Satz gibt es nicht mehr. '
|
||||||
|
+ 'Lade die Seite neu – dann stehen die aktuellen da.',
|
||||||
|
glanz_unklar:
|
||||||
|
'Die Zeit, wie lange jemand im Chat besonders aussieht, '
|
||||||
|
+ 'muss zwischen 0 und 180 Minuten liegen. 0 heißt: gar nicht.',
|
||||||
|
platz_unklar:
|
||||||
|
'Die Karte steht entweder in der Mitte oder am Rand – etwas anderes gibt es nicht.',
|
||||||
|
saetze_fehlen:
|
||||||
|
'Es ist keine Liste von Sätzen angekommen. Versuch es noch einmal.',
|
||||||
|
zu_viele_saetze:
|
||||||
|
'Höchstens acht fertige Sätze. Eine Liste, die man scrollen muss, '
|
||||||
|
+ 'liest beim Spenden niemand.',
|
||||||
nichts_zu_tun:
|
nichts_zu_tun:
|
||||||
'Da war nichts zu schalten.',
|
'Da war nichts zu schalten.',
|
||||||
chatmodus_unbekannt:
|
chatmodus_unbekannt:
|
||||||
|
|||||||
+1273
-15
File diff suppressed because it is too large
Load Diff
@@ -209,28 +209,71 @@
|
|||||||
const eile = Math.min(1, 4 / Math.max(1, schlange.length + 1));
|
const eile = Math.min(1, 4 / Math.max(1, schlange.length + 1));
|
||||||
const dauer = Math.max(2200, Math.round((karte.stufe?.dauer_ms || 7000) * eile));
|
const dauer = Math.max(2200, Math.round((karte.stufe?.dauer_ms || 7000) * eile));
|
||||||
|
|
||||||
const tafel = bauen(karte);
|
/* ==== DER PLATZ STEHT AM KASTEN, NICHT AN DER KARTE ==========
|
||||||
kasten.append(tafel);
|
(08.10.2026)
|
||||||
|
|
||||||
|
Er entscheidet die ANORDNUNG -- also etwas, das der Kasten tut
|
||||||
|
und nicht sein Inhalt. An der Karte stuende dieselbe Auskunft
|
||||||
|
einmal je Karte, und zwei gleichzeitig angezeigte koennten
|
||||||
|
sich widersprechen.
|
||||||
|
|
||||||
|
Eine unbekannte Angabe faellt auf „mitte" zurueck: Das ist der
|
||||||
|
Platz, den Filipe bestellt hat, und ein leerer Wert kommt nur
|
||||||
|
von einer aelteren Fassung des Servers. */
|
||||||
|
const platz = karte.platz === 'rand' ? 'rand' : 'mitte';
|
||||||
|
/* AUSSER JEMAND HAT ES FUER DIESE QUELLE AUSDRUECKLICH GESETZT.
|
||||||
|
Die Spendentafel in OBS kennt `?pos=` -- dort liegt im Stream
|
||||||
|
oft noch etwas anderes im Bild. Was in der Adresse steht, ist
|
||||||
|
eine Entscheidung fuer DIESE Szene und muss schwerer wiegen
|
||||||
|
als die Hauseinstellung; sonst zoege sie bei der naechsten
|
||||||
|
Spende zurueck, und niemand wuesste, warum. */
|
||||||
|
if (kasten.dataset.posFest !== 'ja' && kasten.dataset.platz !== platz) {
|
||||||
|
kasten.dataset.platz = platz;
|
||||||
|
}
|
||||||
|
|
||||||
|
const huelle = bauen(karte);
|
||||||
|
kasten.append(huelle);
|
||||||
/* Ein Bild in derselben Umdrehung anzuhaengen und gleich zu
|
/* Ein Bild in derselben Umdrehung anzuhaengen und gleich zu
|
||||||
bewegen, ueberspringt der Browser -- er fasst beides zusammen.
|
bewegen, ueberspringt der Browser -- er fasst beides zusammen.
|
||||||
Ein Bildaufbau dazwischen, dann laeuft es. */
|
Ein Bildaufbau dazwischen, dann laeuft es. */
|
||||||
requestAnimationFrame(() => requestAnimationFrame(() => {
|
requestAnimationFrame(() => requestAnimationFrame(() => {
|
||||||
tafel.dataset.da = 'ja';
|
huelle.dataset.da = 'ja';
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tafel.dataset.da = 'nein';
|
huelle.dataset.da = 'nein';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
tafel.remove();
|
huelle.remove();
|
||||||
laeuft = false;
|
laeuft = false;
|
||||||
naechste(kasten);
|
naechste(kasten);
|
||||||
}, 600);
|
}, 600);
|
||||||
}, dauer);
|
}, dauer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Baut die Huelle und die Karte darin.
|
||||||
|
*
|
||||||
|
* ==== WARUM ZWEI ELEMENTE UND NICHT EINS (08.10.2026)
|
||||||
|
*
|
||||||
|
* Die Huelle macht das ERSCHEINEN (Deckkraft und Flug aus der
|
||||||
|
* Tiefe), die Karte darin macht die FORM (Wiegen, Glanz).
|
||||||
|
*
|
||||||
|
* Das ist kein Umweg: `opacity` unter 1 zwingt ein Element laut
|
||||||
|
* CSS-Transforms-2 auf `transform-style: flat`. Eine Karte, die
|
||||||
|
* beim Hereinkommen ihre Deckkraft aendert, ist in genau dieser
|
||||||
|
* Zeit flach -- und springt in dem einen Bild, in dem die
|
||||||
|
* Deckkraft 1 erreicht, in die Tiefe. Dieses Springen sieht man.
|
||||||
|
* Mit zwei Elementen setzen sich beide Umformungen durch die
|
||||||
|
* Verschachtelung zusammen, statt einander zu ueberschreiben.
|
||||||
|
*
|
||||||
|
* Dass die Werte (`--sp-farbe`, `--sp-gross`) an der HUELLE
|
||||||
|
* stehen, ist Absicht: Sie werden vererbt, und damit kann auch
|
||||||
|
* die Huelle sie benutzen, ohne dass sie zweimal gesetzt werden. */
|
||||||
function bauen(karte) {
|
function bauen(karte) {
|
||||||
const farbe = karte.stufe?.farbe || '#8ec9ff';
|
const farbe = karte.stufe?.farbe || '#8ec9ff';
|
||||||
|
const huelle = el('div', 'spendenkarte-auftritt');
|
||||||
const tafel = el('div', 'spendenkarte');
|
const tafel = el('div', 'spendenkarte');
|
||||||
|
huelle.append(tafel);
|
||||||
|
huelle.style.setProperty('--sp-farbe', farbe);
|
||||||
tafel.style.setProperty('--sp-farbe', farbe);
|
tafel.style.setProperty('--sp-farbe', farbe);
|
||||||
/* DIE GROESSE KOMMT VON DER STUFE. Genau das ist „spezielle
|
/* DIE GROESSE KOMMT VON DER STUFE. Genau das ist „spezielle
|
||||||
sachen bei speziellen spenden": Eine Rudel-Legende darf
|
sachen bei speziellen spenden": Eine Rudel-Legende darf
|
||||||
@@ -240,8 +283,9 @@
|
|||||||
Bühnenstrom. Eine Zahl, die aus der Leitung kommt, wird nicht
|
Bühnenstrom. Eine Zahl, die aus der Leitung kommt, wird nicht
|
||||||
ungeprüft in ein Stilblatt geschrieben. */
|
ungeprüft in ein Stilblatt geschrieben. */
|
||||||
const g = Number(karte.stufe?.groesse);
|
const g = Number(karte.stufe?.groesse);
|
||||||
tafel.style.setProperty('--sp-gross',
|
const gross = String(Number.isFinite(g) && g >= 1 && g <= 2.5 ? g : 1);
|
||||||
String(Number.isFinite(g) && g >= 1 && g <= 2.5 ? g : 1));
|
huelle.style.setProperty('--sp-gross', gross);
|
||||||
|
tafel.style.setProperty('--sp-gross', gross);
|
||||||
tafel.dataset.stufe = karte.stufe?.name || '';
|
tafel.dataset.stufe = karte.stufe?.name || '';
|
||||||
tafel.setAttribute('role', 'status');
|
tafel.setAttribute('role', 'status');
|
||||||
|
|
||||||
@@ -295,7 +339,7 @@
|
|||||||
}
|
}
|
||||||
if (karte.gruss) text.append(el('p', 'spendenkarte__gruss', karte.gruss));
|
if (karte.gruss) text.append(el('p', 'spendenkarte__gruss', karte.gruss));
|
||||||
tafel.append(text);
|
tafel.append(text);
|
||||||
return tafel;
|
return huelle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Eine Karte zeigen. Kasten und Karte, sonst nichts. */
|
/** Eine Karte zeigen. Kasten und Karte, sonst nichts. */
|
||||||
|
|||||||
@@ -55,14 +55,50 @@
|
|||||||
const faktor = Number.isFinite(g) && g >= 0.5 && g <= 4 ? g : 1.4;
|
const faktor = Number.isFinite(g) && g >= 0.5 && g <= 4 ? g : 1.4;
|
||||||
document.documentElement.style.fontSize = `${Math.round(16 * faktor)}px`;
|
document.documentElement.style.fontSize = `${Math.round(16 * faktor)}px`;
|
||||||
|
|
||||||
|
/* ==== WO DIE KARTE STEHT — EINE ANTWORT, EINE AUSNAHME =======
|
||||||
|
(geändert 08.10.2026)
|
||||||
|
|
||||||
|
Seit heute entscheidet das Regiepult, ob die Karte in der
|
||||||
|
MITTE des Bildes steht oder am RAND; die Karte bringt den
|
||||||
|
Platz mit („Gestaltung → Wo die Karte steht"), und derselbe
|
||||||
|
Wert gilt im Saal und hier. Das ist die eine Antwort — wer
|
||||||
|
umstellt, stellt beide Orte zugleich um und muss nicht daran
|
||||||
|
denken, in OBS eine Adresse nachzuziehen.
|
||||||
|
|
||||||
|
`pos` IN DER ADRESSE BLEIBT TROTZDEM, UND ZWAR ALS AUSNAHME.
|
||||||
|
Im Stream liegt oft noch etwas anderes im Bild — ein
|
||||||
|
Kamerakasten, ein Alert, ein Rahmen. Dafür braucht es eine
|
||||||
|
Stelle, an der man die Karte für DIESE Szene wegschiebt, ohne
|
||||||
|
den Saal mitzuverstellen.
|
||||||
|
|
||||||
|
UND SIE GILT NUR, WENN SIE AUSDRÜCKLICH DASTEHT. Vorher stand
|
||||||
|
hier `p.get('pos') || 'ul'` — damit hatte JEDE Adresse eine
|
||||||
|
Lage, auch die, in der nie jemand eine angegeben hat, und die
|
||||||
|
Hauseinstellung wäre an dieser Seite wirkungslos verpufft.
|
||||||
|
Das ist der Unterschied zwischen einer Ausnahme und einer
|
||||||
|
zweiten Regel.
|
||||||
|
|
||||||
|
Die Werte heißen `align-content`/`justify-items` und nicht
|
||||||
|
`justify-content`/`align-items`: Die Tafel ist seit dem
|
||||||
|
08.10. ein Raster mit einer Spalte, und dort sind das die
|
||||||
|
Eigenschaften, die wirken. */
|
||||||
const lagen = {
|
const lagen = {
|
||||||
ul: ['flex-end', 'flex-start'], ur: ['flex-end', 'flex-end'],
|
ul: ['end', 'start'], ur: ['end', 'end'],
|
||||||
ol: ['flex-start', 'flex-start'], or: ['flex-start', 'flex-end'],
|
ol: ['start', 'start'], or: ['start', 'end'],
|
||||||
mitte: ['center', 'center'],
|
mitte: ['center', 'center'],
|
||||||
};
|
};
|
||||||
const [senkrecht, waagerecht] = lagen[String(p.get('pos') || 'ul')] || lagen.ul;
|
const gewuenscht = String(p.get('pos') || '');
|
||||||
tafel.style.justifyContent = senkrecht;
|
if (gewuenscht && lagen[gewuenscht]) {
|
||||||
tafel.style.alignItems = waagerecht;
|
const [senkrecht, waagerecht] = lagen[gewuenscht];
|
||||||
|
tafel.style.alignContent = senkrecht;
|
||||||
|
tafel.style.justifyItems = waagerecht;
|
||||||
|
/* Die FORM muss zur Lage passen: In der Mitte steht die Karte
|
||||||
|
als Aufsteller (Münze oben, Betrag darunter), an jeder
|
||||||
|
anderen Lage als Zeile. Ohne diese Zeile stünde mitten im
|
||||||
|
Bild die flache Randfassung. */
|
||||||
|
tafel.dataset.platz = gewuenscht === 'mitte' ? 'mitte' : 'rand';
|
||||||
|
tafel.dataset.posFest = 'ja';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const schluessel = new URLSearchParams(location.search).get('s') || '';
|
const schluessel = new URLSearchParams(location.search).get('s') || '';
|
||||||
|
|
||||||
|
|||||||
+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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="garage">
|
<body class="start" data-buehne="garage">
|
||||||
@@ -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=202610072346"></script>
|
<script src="assets/js/textform.js?v=202610080131"></script>
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610072346" defer></script>
|
<script src="assets/js/hochladen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/zuteilung.js?v=202610072346" defer></script>
|
<script src="assets/js/zuteilung.js?v=202610080131" 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=202610072346" defer></script>
|
<script src="assets/js/vorlagenbrett.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/aufgaben.js?v=202610072346" defer></script>
|
<script src="assets/js/aufgaben.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/automation.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/automation.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="garage">
|
<body class="start" data-buehne="garage">
|
||||||
@@ -168,15 +168,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/automation.js?v=202610072346" defer></script>
|
<script src="assets/js/automation.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -197,16 +197,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/befinden.js?v=202610072346" defer></script>
|
<script src="assets/js/befinden.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+24
-24
@@ -12,29 +12,29 @@
|
|||||||
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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/bereich.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/bereich.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610080131" />
|
||||||
<!-- Die Bildschau: ein Banner wird darin mittig gezeigt statt als nackte
|
<!-- Die Bildschau: ein Banner wird darin mittig gezeigt statt als nackte
|
||||||
Datei in einem neuen Tab. Sie ist seit dem 07.10.2026 eine eigene
|
Datei in einem neuen Tab. Sie ist seit dem 07.10.2026 eine eigene
|
||||||
Datei und keine Kopie aus chat.css -- dieselbe Schau im Chat und
|
Datei und keine Kopie aus chat.css -- dieselbe Schau im Chat und
|
||||||
hier, ein Stil. -->
|
hier, ein Stil. -->
|
||||||
<link rel="stylesheet" href="assets/css/bildschau.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/bildschau.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -413,20 +413,20 @@
|
|||||||
<!-- 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=202610072346"></script>
|
<script src="assets/js/textform.js?v=202610080131"></script>
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/checkliste.js?v=202610072346" defer></script>
|
<script src="assets/js/checkliste.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/ampel.js?v=202610072346" defer></script>
|
<script src="assets/js/ampel.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/schulung.js?v=202610072346" defer></script>
|
<script src="assets/js/schulung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bildschau.js?v=202610072346"></script>
|
<script src="assets/js/bildschau.js?v=202610080131"></script>
|
||||||
<script src="assets/js/bereich.js?v=202610072346" defer></script>
|
<script src="assets/js/bereich.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/bereich.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/bereich.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/treff.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/treff.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</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=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/auskunft.js?v=202610072346" defer></script>
|
<script src="assets/js/auskunft.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bewerben.js?v=202610072346" defer></script>
|
<script src="assets/js/bewerben.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -80,16 +80,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/auskunft.js?v=202610072346" defer></script>
|
<script src="assets/js/auskunft.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bewerbungen.js?v=202610072346" defer></script>
|
<script src="assets/js/bewerbungen.js?v=202610080131" 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/werbung.css?v=202610080131" />
|
||||||
</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=202610072346" defer></script>
|
<script src="assets/js/werbung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/buehne.js?v=202610072346" defer></script>
|
<script src="assets/js/buehne.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/calls.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/calls.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="lounge">
|
<body class="start" data-buehne="lounge">
|
||||||
@@ -89,15 +89,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202610072346" defer></script>
|
<script src="assets/js/ki.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/calls.js?v=202610072346" defer></script>
|
<script src="assets/js/calls.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+21
-21
@@ -12,31 +12,31 @@
|
|||||||
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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/chat.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/chat.css?v=202610080131" />
|
||||||
<!-- Die Bildschau stand bis zum 07.10.2026 in chat.css. Sie wird jetzt
|
<!-- Die Bildschau stand bis zum 07.10.2026 in chat.css. Sie wird jetzt
|
||||||
auch vom Event-Banner benutzt (bereich.html) und hat deshalb eine
|
auch vom Event-Banner benutzt (bereich.html) und hat deshalb eine
|
||||||
eigene Datei. Sie steht GENAU HIER -- direkt hinter chat.css, also
|
eigene Datei. Sie steht GENAU HIER -- direkt hinter chat.css, also
|
||||||
an derselben Stelle im Ladeweg wie der Block vorher. -->
|
an derselben Stelle im Ladeweg wie der Block vorher. -->
|
||||||
<link rel="stylesheet" href="assets/css/bildschau.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/bildschau.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="lounge">
|
<body class="start" data-buehne="lounge">
|
||||||
@@ -744,24 +744,24 @@
|
|||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script src="assets/js/bereiche.js?v=202610072346"></script>
|
<script src="assets/js/bereiche.js?v=202610080131"></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=202610072346"></script>
|
<script src="assets/js/textform.js?v=202610080131"></script>
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610072346" defer></script>
|
<script src="assets/js/hochladen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346"></script>
|
<script src="assets/js/kopf.js?v=202610080131"></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346"></script>
|
<script src="assets/js/glocke.js?v=202610080131"></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=202610072346"></script>
|
<script src="assets/js/anruf.js?v=202610080131"></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
|
||||||
@@ -772,8 +772,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=202610072346"></script>
|
<script src="assets/js/bildschau.js?v=202610080131"></script>
|
||||||
<script src="assets/js/chat.js?v=202610072346"></script>
|
<script src="assets/js/chat.js?v=202610080131"></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/content.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/content.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="portal">
|
<body class="start" data-buehne="portal">
|
||||||
@@ -179,15 +179,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/checkliste.js?v=202610072346" defer></script>
|
<script src="assets/js/checkliste.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/content.js?v=202610072346" defer></script>
|
<script src="assets/js/content.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/crew-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/crew-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/crew-haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="gate gate--crew">
|
<body class="gate gate--crew">
|
||||||
@@ -459,7 +459,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/gate.js?v=202610072346" defer></script>
|
<script src="assets/js/gate.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -23,25 +23,25 @@
|
|||||||
},
|
},
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/crew-192.png?v=202610072346",
|
"src": "/assets/img/app-symbole/crew-192.png?v=202610080131",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/crew-512.png?v=202610072346",
|
"src": "/assets/img/app-symbole/crew-512.png?v=202610080131",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any"
|
"purpose": "any"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202610072346",
|
"src": "/assets/img/app-symbole/crew-192-maskable.png?v=202610080131",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202610072346",
|
"src": "/assets/img/app-symbole/crew-512-maskable.png?v=202610080131",
|
||||||
"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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/dateien.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/dateien.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="arena">
|
<body class="start" data-buehne="arena">
|
||||||
@@ -108,15 +108,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610072346" defer></script>
|
<script src="assets/js/hochladen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/dateien.js?v=202610072346" defer></script>
|
<script src="assets/js/dateien.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -306,20 +306,20 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" 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=202610072346" defer></script>
|
<script src="assets/js/vorlagenbrett.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/entwicklung.js?v=202610072346" defer></script>
|
<script src="assets/js/entwicklung.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/hilfe.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/hilfe.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -146,14 +146,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/hilfe.js?v=202610072346" defer></script>
|
<script src="assets/js/hilfe.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="gate">
|
<body class="gate">
|
||||||
@@ -427,7 +427,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/gate.js?v=202610072346" defer></script>
|
<script src="assets/js/gate.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/kalender.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/kalender.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="skyline">
|
<body class="start" data-buehne="skyline">
|
||||||
@@ -383,15 +383,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kalender.js?v=202610072346" defer></script>
|
<script src="assets/js/kalender.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kalender-abo.js?v=202610072346" defer></script>
|
<script src="assets/js/kalender-abo.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/leistung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/leistung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="arena">
|
<body class="start" data-buehne="arena">
|
||||||
@@ -444,13 +444,13 @@
|
|||||||
</form>
|
</form>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346"></script>
|
<script src="assets/js/meldung.js?v=202610080131"></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346"></script>
|
<script src="assets/js/nachfrage.js?v=202610080131"></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346"></script>
|
<script src="assets/js/wahl.js?v=202610080131"></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346"></script>
|
<script src="assets/js/bereiche.js?v=202610080131"></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346"></script>
|
<script src="assets/js/kopf.js?v=202610080131"></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346"></script>
|
<script src="assets/js/glocke.js?v=202610080131"></script>
|
||||||
<script src="assets/js/leistung.js?v=202610072346"></script>
|
<script src="assets/js/leistung.js?v=202610080131"></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/manager-ziele.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/manager-ziele.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="arena">
|
<body class="start" data-buehne="arena">
|
||||||
@@ -230,16 +230,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=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" 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=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/manager-ziele.js?v=202610072346" defer></script>
|
<script src="assets/js/manager-ziele.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/material.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/material.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</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=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610072346" defer></script>
|
<script src="assets/js/hochladen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/material.js?v=202610072346" defer></script>
|
<script src="assets/js/material.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/notizen.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/notizen.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</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=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/notizen.js?v=202610072346" defer></script>
|
<script src="assets/js/notizen.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/personen.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/personen.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="halle">
|
<body class="start" data-buehne="halle">
|
||||||
@@ -453,14 +453,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/personen.js?v=202610072346" defer></script>
|
<script src="assets/js/personen.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/profil.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/profil.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="halle">
|
<body class="start" data-buehne="halle">
|
||||||
@@ -214,16 +214,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610072346" defer></script>
|
<script src="assets/js/hochladen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/steckbrief.js?v=202610072346" defer></script>
|
<script src="assets/js/steckbrief.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/profil.js?v=202610072346" defer></script>
|
<script src="assets/js/profil.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+267
-40
@@ -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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/reaktion.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/reaktion.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/spendenkarte.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/spendenkarte.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/werbung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/werbung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start reaktion-seite" data-stand="laedt">
|
<body class="start reaktion-seite" data-stand="laedt">
|
||||||
@@ -270,6 +270,29 @@
|
|||||||
<span id="s-mikro-wort">Mikro</span><kbd class="sender-taste">M</kbd>
|
<span id="s-mikro-wort">Mikro</span><kbd class="sender-taste">M</kbd>
|
||||||
</button>
|
</button>
|
||||||
<span class="sender-pegel" id="s-pegel" aria-hidden="true"><i></i></span>
|
<span class="sender-pegel" id="s-pegel" aria-hidden="true"><i></i></span>
|
||||||
|
<!-- ==== GERÄTE AUCH FÜR GÄSTE (08.10.2026) ============
|
||||||
|
Filipe: „auch bei den gästen."
|
||||||
|
|
||||||
|
Das Regiepult sehen nur die zwei, die die Sendung
|
||||||
|
führen — ein Gast käme also nach dem Vorraum nie mehr
|
||||||
|
an seine Gerätewahl. Genau dann braucht er sie aber:
|
||||||
|
wenn mitten in der Sendung auffällt, dass der falsche
|
||||||
|
Weg läuft. Der Knopf steht deshalb in der
|
||||||
|
Senderleiste, bei Kamera und Mikro, denn er gehört zu
|
||||||
|
derselben Frage.
|
||||||
|
|
||||||
|
Er steht auch beim Host da. Zwei Wege zur selben
|
||||||
|
Einstellung sind hier kein Widerspruch, sondern
|
||||||
|
derselbe Bauplan an zwei Griffen — dahinter liegt
|
||||||
|
dieselbe Funktion. -->
|
||||||
|
<button type="button" class="sender-knopf sender-knopf--klein" id="s-geraete"
|
||||||
|
title="Mikrofon, Kamera und Mischpult">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M5 4v16M12 4v16M19 4v16" />
|
||||||
|
<path d="M2.5 9.5h5M9.5 14.5h5M16.5 7.5h5" />
|
||||||
|
</svg>
|
||||||
|
<span class="sender-knopf__wort">Geräte</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" class="ton-an" id="ton-an" hidden>
|
<button type="button" class="ton-an" id="ton-an" hidden>
|
||||||
@@ -365,8 +388,26 @@
|
|||||||
<input type="text" id="geben-name" maxlength="40"
|
<input type="text" id="geben-name" maxlength="40"
|
||||||
autocomplete="off" placeholder="So wie du dastehen willst" />
|
autocomplete="off" placeholder="So wie du dastehen willst" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<!-- ==== DIE FERTIGEN SÄTZE (08.10.2026) ===============
|
||||||
|
Filipe: „es soll fertige sätze geben und wenn jemand
|
||||||
|
die auswählt muss keiner es bestätigen dan wird es
|
||||||
|
sofort angezeigt und wenn jemand selber was schreibt
|
||||||
|
dan muss bestätigt werden damit es angezeigt wird."
|
||||||
|
|
||||||
|
SIE STEHEN VOR DEM FREIEN FELD und nicht daneben.
|
||||||
|
Das ist der ganze Punkt: Der schnelle Weg soll der
|
||||||
|
naheliegende sein. Wer tippen will, tippt darunter
|
||||||
|
weiter — nur dauert es dann, bis es im Bild steht,
|
||||||
|
und genau das steht auch dort. -->
|
||||||
|
<div class="geben__saetze" id="geben-saetze" hidden>
|
||||||
|
<span class="geben__saetze-wort">Ein fertiger Satz — steht sofort im Bild</span>
|
||||||
|
<div class="geben__satzreihe" id="geben-satzreihe" role="group"
|
||||||
|
aria-label="Fertige Sätze"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label class="geben__feld">
|
<label class="geben__feld">
|
||||||
<span>Dein Text <span class="geben__rest" id="geben-rest"></span></span>
|
<span>Oder selbst schreiben <span class="geben__rest" id="geben-rest"></span></span>
|
||||||
<textarea id="geben-text" rows="2" maxlength="140"
|
<textarea id="geben-text" rows="2" maxlength="140"
|
||||||
placeholder="Was soll im Bild stehen?"></textarea>
|
placeholder="Was soll im Bild stehen?"></textarea>
|
||||||
</label>
|
</label>
|
||||||
@@ -477,9 +518,9 @@
|
|||||||
auch bevor etwas eingetragen ist. Vorher stand hier
|
auch bevor etwas eingetragen ist. Vorher stand hier
|
||||||
nur ein Titel, und wenn keiner da war, ein schwarzes
|
nur ein Titel, und wenn keiner da war, ein schwarzes
|
||||||
Loch neben einer vollen Spalte. -->
|
Loch neben einer vollen Spalte. -->
|
||||||
<section class="regiekachel kachel--laeuft" id="spur">
|
<section class="regiekachel regiekachel--laeuft" id="spur">
|
||||||
<div class="regieregiekachel__kopf">
|
<div class="regiekachel__kopf">
|
||||||
<h4 class="regieregiekachel__ueber">Was läuft</h4>
|
<h4 class="regiekachel__ueber">Was läuft</h4>
|
||||||
<span class="spur__marke" id="spur-marke">Läuft</span>
|
<span class="spur__marke" id="spur-marke">Läuft</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -498,15 +539,15 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ==== RECHTS OBEN: DIE SENDUNG ==================== -->
|
<!-- ==== RECHTS OBEN: DIE SENDUNG ==================== -->
|
||||||
<section class="regiekachel kachel--sendung">
|
<section class="regiekachel regiekachel--sendung">
|
||||||
<div class="regieregiekachel__kopf">
|
<div class="regiekachel__kopf">
|
||||||
<h4 class="regieregiekachel__ueber">Die Sendung</h4>
|
<h4 class="regiekachel__ueber">Die Sendung</h4>
|
||||||
</div>
|
</div>
|
||||||
<label class="pult__feld">
|
<label class="pult__feld">
|
||||||
<span>Titel der Sendung</span>
|
<span>Titel der Sendung</span>
|
||||||
<input type="text" id="p-titel" maxlength="120" placeholder="Worum geht es?" />
|
<input type="text" id="p-titel" maxlength="120" placeholder="Worum geht es?" />
|
||||||
</label>
|
</label>
|
||||||
<div class="regieregiekachel__paar">
|
<div class="regiekachel__paar">
|
||||||
<label class="pult__feld">
|
<label class="pult__feld">
|
||||||
<span>YouTube</span>
|
<span>YouTube</span>
|
||||||
<input type="text" id="p-video" placeholder="Adresse oder Kennung" />
|
<input type="text" id="p-video" placeholder="Adresse oder Kennung" />
|
||||||
@@ -516,6 +557,18 @@
|
|||||||
<input type="datetime-local" id="p-beginn" />
|
<input type="datetime-local" id="p-beginn" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- ==== DAS VORSCHAUBILD GEHÖRT ZUR SENDUNG ========
|
||||||
|
Es stand bis zum 08.10.2026 unter „Bereitlegen",
|
||||||
|
direkt neben dem zweiten Video — und sah damit aus,
|
||||||
|
als gehöre es dazu. Es ist aber das Bild der
|
||||||
|
WARTETAFEL, also eine Eigenschaft dieser Sendung wie
|
||||||
|
Titel und Beginn. Zwei Felder nebeneinander, von
|
||||||
|
denen eines etwas ganz anderes meint, sind eine
|
||||||
|
Falle, die man nur einmal braucht. -->
|
||||||
|
<label class="pult__feld">
|
||||||
|
<span>Vorschaubild (freiwillig)</span>
|
||||||
|
<input type="text" id="p-vorschau" placeholder="Adresse eines Bildes" />
|
||||||
|
</label>
|
||||||
<div class="pult__zeile pult__zeile--ende">
|
<div class="pult__zeile pult__zeile--ende">
|
||||||
<button type="button" class="knopf-still knopf-still--haupt"
|
<button type="button" class="knopf-still knopf-still--haupt"
|
||||||
id="p-sichern">Übernehmen</button>
|
id="p-sichern">Übernehmen</button>
|
||||||
@@ -523,22 +576,47 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ==== RECHTS UNTEN: BEREITLEGEN =================== -->
|
<!-- ==== RECHTS UNTEN: BEREITLEGEN =================== -->
|
||||||
<section class="regiekachel kachel--bereit">
|
<section class="regiekachel regiekachel--bereit">
|
||||||
<div class="regieregiekachel__kopf">
|
<div class="regiekachel__kopf">
|
||||||
<h4 class="regieregiekachel__ueber">Bereitlegen</h4>
|
<h4 class="regiekachel__ueber">Bereitlegen</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="regieregiekachel__paar">
|
<!-- ==== WAS BEREITLIEGT, SIEHT MAN JETZT (08.10.2026)
|
||||||
|
Filipe: „perfektioniere das ganze system auch für das
|
||||||
|
zweite video. auch so dass ich während einer sendung
|
||||||
|
auch immer ein zweites vorbereiten kann oder ändern
|
||||||
|
kann."
|
||||||
|
|
||||||
|
Vorher stand hier nur ein Textfeld mit einer
|
||||||
|
YouTube-Kennung darin. Ob das Richtige bereitlag,
|
||||||
|
wusste man erst nach dem Umschalten — also vor
|
||||||
|
Publikum. Jetzt stehen Bild, Titel und die GEMERKTE
|
||||||
|
STELLE da, und die ist der eigentliche Grund für das
|
||||||
|
zweite Video: Man schaltet mittendrin weg und später
|
||||||
|
dort weiter. -->
|
||||||
|
<div class="laufbild" id="zweitbild" data-bild="nein">
|
||||||
|
<img id="zweit-bild" alt="" />
|
||||||
|
<span class="laufbild__leer" id="zweit-leer">
|
||||||
|
Noch kein zweites Video — trag unten eine Adresse ein
|
||||||
|
oder nimm eines aus der Warteschlange.
|
||||||
|
</span>
|
||||||
|
<span class="laufbild__stelle" id="zweit-stelle" hidden></span>
|
||||||
|
</div>
|
||||||
|
<strong class="spur__titel" id="zweit-titel">Nichts bereitgelegt</strong>
|
||||||
|
|
||||||
<label class="pult__feld">
|
<label class="pult__feld">
|
||||||
<span>Zweites Video</span>
|
<span>Zweites Video</span>
|
||||||
<input type="text" id="p-zweit" placeholder="Adresse — leer räumt es weg" />
|
<input type="text" id="p-zweit" placeholder="Adresse — leer räumt es weg" />
|
||||||
</label>
|
</label>
|
||||||
<label class="pult__feld">
|
|
||||||
<span>Vorschaubild</span>
|
|
||||||
<input type="text" id="p-vorschau" placeholder="Adresse eines Bildes" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="pult__zeile pult__zeile--ende">
|
<div class="pult__zeile pult__zeile--ende">
|
||||||
<button type="button" class="knopf-still" id="p-zweit-sichern">Bereitlegen</button>
|
<button type="button" class="knopf-still" id="p-zweit-sichern">Bereitlegen</button>
|
||||||
|
<!-- Derselbe Tausch wie in der Transportleiste, nur von
|
||||||
|
hier aus. Er steht an BEIDEN Stellen, weil man ihn
|
||||||
|
an beiden braucht: unten, während man sendet, und
|
||||||
|
hier, während man einrichtet. Dahinter liegt
|
||||||
|
dieselbe Funktion — zwei wären zwei, die
|
||||||
|
auseinanderlaufen. -->
|
||||||
|
<button type="button" class="knopf-still" id="p-zweit-tausch"
|
||||||
|
disabled>Jetzt wechseln</button>
|
||||||
<!-- ==== ALLES ZURÜCKSETZEN ====================
|
<!-- ==== ALLES ZURÜCKSETZEN ====================
|
||||||
Filipe: „brauch ich auch noch einen button wo ich
|
Filipe: „brauch ich auch noch einen button wo ich
|
||||||
alles easy zurücksetzen kann."
|
alles easy zurücksetzen kann."
|
||||||
@@ -577,6 +655,21 @@
|
|||||||
id="tafel-ton" aria-labelledby="reiter-ton">
|
id="tafel-ton" aria-labelledby="reiter-ton">
|
||||||
<div class="regler-reihe" id="regler"></div>
|
<div class="regler-reihe" id="regler"></div>
|
||||||
<p class="pult__klein" id="ton-hinweis"></p>
|
<p class="pult__klein" id="ton-hinweis"></p>
|
||||||
|
|
||||||
|
<!-- ==== DIE GERÄTE (08.10.2026) ========================
|
||||||
|
Filipe: „ich will dass du das auch mit meinem
|
||||||
|
mischpult, also meinen rodeduo verbindest. also soll
|
||||||
|
mit und ohne gehen bitte."
|
||||||
|
|
||||||
|
Bis heute nahm diese Seite immer das, was Windows
|
||||||
|
gerade für den Standard hielt — bei fünfzehn
|
||||||
|
RØDE-Einträgen ist das Glückssache. Und sie schaltete
|
||||||
|
Echo- und Rauschunterdrückung fest EIN, also genau die
|
||||||
|
zwei Automatiken, die über einem Pult nichts zu suchen
|
||||||
|
haben. Beides steht jetzt hier. -->
|
||||||
|
<h3 class="pult__ueber">Geräte & Mischpult</h3>
|
||||||
|
<div class="geraete" id="geraete"></div>
|
||||||
|
<p class="pult__klein" id="geraete-hinweis"></p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ==== Gäste ========================================== -->
|
<!-- ==== Gäste ========================================== -->
|
||||||
@@ -586,7 +679,7 @@
|
|||||||
<div class="gast-reihe" id="gast-reihe"></div>
|
<div class="gast-reihe" id="gast-reihe"></div>
|
||||||
<div class="pult__zeile">
|
<div class="pult__zeile">
|
||||||
<select id="p-wen" class="pult__wahl" aria-label="Wen holen?"></select>
|
<select id="p-wen" class="pult__wahl" aria-label="Wen holen?"></select>
|
||||||
<button type="button" class="knopf-still" id="p-holen">Dazuholen</button>
|
<button type="button" class="knopf-still" id="p-holen">Einladen</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -693,12 +786,31 @@
|
|||||||
in Drittel geteilt.
|
in Drittel geteilt.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- ==== WO DIE KARTE STEHT (08.10.2026) ================
|
||||||
|
Filipe: „die spende soll auch in der mitte vom bild
|
||||||
|
angezeigt werden."
|
||||||
|
|
||||||
|
Der Knopf bleibt trotzdem: Bei einem Film, bei dem ein
|
||||||
|
Deckel in der Mitte stört, ist der alte Platz der
|
||||||
|
bessere — und eine Festlegung, die man nicht
|
||||||
|
zurücknehmen kann, ist keine Einstellung. Er gilt für
|
||||||
|
den Saal UND für die Tafel in OBS. -->
|
||||||
|
<h3 class="pult__ueber">Wo die Karte steht</h3>
|
||||||
|
<div class="platzwahl" id="platzwahl" role="group"
|
||||||
|
aria-label="Wo die Spendenkarte im Bild steht"></div>
|
||||||
|
<p class="pult__klein">
|
||||||
|
In der Mitte steht sie als Aufsteller und kommt aus der
|
||||||
|
Tiefe nach vorn — am Rand liegt sie flach unten links und
|
||||||
|
lässt das Bild frei. Beides gilt auch für die Tafel in OBS.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 class="pult__ueber">Wie eine Spende aussieht</h3>
|
<h3 class="pult__ueber">Wie eine Spende aussieht</h3>
|
||||||
<p class="pult__klein">
|
<p class="pult__klein">
|
||||||
Je Stufe: ab wie vielen Dogen sie gilt, wie sie heißt,
|
Je Stufe: ab wie vielen Dogen sie gilt, wie sie heißt,
|
||||||
welches Zeichen, welche Farbe, wie lange sie steht und wie
|
welches Zeichen, welche Farbe, wie lange sie steht, wie
|
||||||
groß. Eine Spende bekommt immer die höchste Stufe, die auf
|
groß — und wie lange der Spender danach im Chat besonders
|
||||||
sie passt.
|
aussieht. Eine Spende bekommt immer die höchste Stufe, die
|
||||||
|
auf sie passt.
|
||||||
</p>
|
</p>
|
||||||
<div class="stufen" id="stufen"></div>
|
<div class="stufen" id="stufen"></div>
|
||||||
<div class="pult__zeile">
|
<div class="pult__zeile">
|
||||||
@@ -711,6 +823,28 @@
|
|||||||
„Ausprobieren“ zeigt dir eine Karte — nur bei dir, und es wird
|
„Ausprobieren“ zeigt dir eine Karte — nur bei dir, und es wird
|
||||||
keine Spende daraus. Im Saal sieht das niemand.
|
keine Spende daraus. Im Saal sieht das niemand.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- ==== DIE FERTIGEN SÄTZE (08.10.2026) ================
|
||||||
|
Was hier steht, kann ein Zuschauer beim Spenden
|
||||||
|
auswählen — und was er auswählt, geht OHNE Bestätigung
|
||||||
|
sofort ins Bild. Das ist der Grund, warum die Liste
|
||||||
|
hier steht und nicht irgendwo: Wer sie schreibt, hat
|
||||||
|
damit vorher entschieden, was später ungesehen im
|
||||||
|
Stream erscheinen darf. -->
|
||||||
|
<h3 class="pult__ueber">Fertige Sätze</h3>
|
||||||
|
<p class="pult__klein">
|
||||||
|
Wählt jemand einen davon aus, läuft seine Karte
|
||||||
|
<strong>sofort</strong> — niemand muss sie bestätigen. Nur
|
||||||
|
selbst geschriebene Texte warten im Register „Spenden" auf
|
||||||
|
dich. Ein leeres Feld nimmt den Satz weg.
|
||||||
|
</p>
|
||||||
|
<div class="saetze" id="saetze"></div>
|
||||||
|
<div class="pult__zeile">
|
||||||
|
<button type="button" class="knopf-still" id="satz-neu">Satz dazu</button>
|
||||||
|
<button type="button" class="knopf-still knopf-still--haupt"
|
||||||
|
id="saetze-sichern">Übernehmen</button>
|
||||||
|
<span class="pult__klein" id="saetze-stand"></span>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ==== Spenden ======================================= -->
|
<!-- ==== Spenden ======================================= -->
|
||||||
@@ -903,17 +1037,110 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<!-- ======================================================================
|
||||||
|
DIE ZWEI VORHAENGE STEHEN AUSSERHALB DES SAALS (08.10.2026)
|
||||||
|
|
||||||
|
Sie lagen zuerst in `<main class="saal">` -- und kamen damit nie
|
||||||
|
ueber die Kopfleiste des Hauses. Der Grund ist ein STAPELKONTEXT
|
||||||
|
und keine zu kleine Zahl: `body.start > main` traegt `position:
|
||||||
|
relative; z-index: 1`, die Kopfleiste steht bei 6. Alles INNERHALB
|
||||||
|
von main wird mit main zusammen eingeordnet -- ein `z-index: 500`
|
||||||
|
darin bleibt unter der 6 daneben. Gemessen: An der Stelle, an der
|
||||||
|
der Vorhang liegen sollte, fand `elementFromPoint` die Kopfleiste.
|
||||||
|
|
||||||
|
Das ist dieselbe Falle wie eine zweite CSS-Regel fuer dieselbe
|
||||||
|
Frage: Man dreht an der Zahl und wundert sich, dass nichts
|
||||||
|
passiert. Hier steht der Vorhang jetzt dort, wo ein Vorhang
|
||||||
|
hingehoert -- als letztes Kind des Dokuments, neben main und
|
||||||
|
Kopfleiste statt darin.
|
||||||
|
====================================================================== -->
|
||||||
|
<!-- ============ GERÄTE WÄHREND DER SENDUNG ====================
|
||||||
|
Dieselbe Oberfläche wie im Vorraum und im Register „Ton" —
|
||||||
|
gebaut von derselben Stelle im Programm (`geraeteBauen`).
|
||||||
|
Dreimal nachgebaut hiesse: Beim nächsten Umbau sieht eine
|
||||||
|
davon anders aus, und gemerkt würde es mitten in einer
|
||||||
|
Sendung. -->
|
||||||
|
<div class="vorraum" id="geraetefenster" hidden role="dialog" aria-modal="true"
|
||||||
|
aria-labelledby="geraetefenster-titel">
|
||||||
|
<div class="vorraum__karte">
|
||||||
|
<h2 class="vorraum__titel" id="geraetefenster-titel">Mikrofon, Kamera, Mischpult</h2>
|
||||||
|
<p class="vorraum__satz">
|
||||||
|
Die Umstellung gilt sofort — die Verbindungen bleiben dabei
|
||||||
|
stehen, es wird nichts neu aufgebaut.
|
||||||
|
</p>
|
||||||
|
<div class="geraete" id="geraetefenster-inhalt"></div>
|
||||||
|
<div class="vorraum__knoepfe">
|
||||||
|
<button type="button" class="knopf-still knopf-still--haupt"
|
||||||
|
id="geraetefenster-zu">Fertig</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ============ DER VORRAUM FÜR EINGELADENE GÄSTE ============
|
||||||
|
Filipe: „wenn gäste eingeladen werden, sollen die akzeptieren
|
||||||
|
oder ablehnen können. bevor die auch angezeigt werden sollen
|
||||||
|
die auswählen können ob die kamera an ist oder aus ist. also
|
||||||
|
iohre eigene."
|
||||||
|
|
||||||
|
ER LIEGT ÜBER ALLEM UND IST NICHT WEGZUKLICKEN — aber er hat
|
||||||
|
immer zwei Ausgänge: „Dabei sein" und „Lieber nicht". Ein
|
||||||
|
Vorhang ohne zweiten Ausgang wäre eine Falle, und zwar
|
||||||
|
ausgerechnet für den, der gerade nur zuschauen wollte.
|
||||||
|
|
||||||
|
DAS BILD LÄUFT DARIN, BEVOR ES HINAUSGEHT. Das ist der ganze
|
||||||
|
Sinn: Man sieht sich selbst, bevor einen jemand anderes sieht
|
||||||
|
— und entscheidet dann, ob die Kamera an sein soll. -->
|
||||||
|
<div class="vorraum" id="vorraum" hidden role="dialog" aria-modal="true"
|
||||||
|
aria-labelledby="vorraum-titel">
|
||||||
|
<div class="vorraum__karte">
|
||||||
|
<h2 class="vorraum__titel" id="vorraum-titel">Du bist eingeladen</h2>
|
||||||
|
<p class="vorraum__satz" id="vorraum-satz">
|
||||||
|
Du sollst mit auf die Bühne. Du entscheidest, ob deine Kamera
|
||||||
|
und dein Mikro dabei an sind.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="vorraum__bild">
|
||||||
|
<!-- Stumm, und zwar für immer: Sich selbst mit Verzögerung zu
|
||||||
|
hören ist der schnellste Weg, dass jemand aufhört zu
|
||||||
|
reden. -->
|
||||||
|
<video id="vorraum-video" autoplay playsinline muted></video>
|
||||||
|
<span class="vorraum__aus" id="vorraum-aus" hidden>Kamera aus</span>
|
||||||
|
<span class="vorraum__pegel" id="vorraum-pegel" aria-hidden="true"><i></i></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vorraum__schalter">
|
||||||
|
<button type="button" class="vorraum__schalt" id="vorraum-kamera"
|
||||||
|
aria-pressed="true">Kamera an</button>
|
||||||
|
<button type="button" class="vorraum__schalt" id="vorraum-mikro"
|
||||||
|
aria-pressed="true">Mikro an</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Dieselbe Geräteauswahl wie im Register „Ton" — gebaut von
|
||||||
|
derselben Stelle im Programm. Filipe: „auch bei den
|
||||||
|
gästen." -->
|
||||||
|
<div class="geraete vorraum__geraete" id="vorraum-geraete"></div>
|
||||||
|
|
||||||
|
<p class="vorraum__frist" id="vorraum-frist" aria-live="polite"></p>
|
||||||
|
<div class="vorraum__knoepfe">
|
||||||
|
<button type="button" class="knopf-still knopf-still--haupt"
|
||||||
|
id="vorraum-ja">Dabei sein</button>
|
||||||
|
<button type="button" class="knopf-still knopf-still--leise"
|
||||||
|
id="vorraum-nein">Lieber nicht</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 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=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/spendenkarte.js?v=202610072346" defer></script>
|
<script src="assets/js/spendenkarte.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/werbung.js?v=202610072346" defer></script>
|
<script src="assets/js/werbung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/reaktion.js?v=202610072346" defer></script>
|
<script src="assets/js/reaktion.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/treff.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/treff.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</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=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/rechte.js?v=202610072346" defer></script>
|
<script src="assets/js/rechte.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/report.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/report.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="showbuehne">
|
<body class="start" data-buehne="showbuehne">
|
||||||
@@ -106,17 +106,17 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202610072346" defer></script>
|
<script src="assets/js/ki.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/report.js?v=202610072346" defer></script>
|
<script src="assets/js/report.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/scouting.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/scouting.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="wald">
|
<body class="start" data-buehne="wald">
|
||||||
@@ -194,14 +194,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/scouting.js?v=202610072346" defer></script>
|
<script src="assets/js/scouting.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+19
-19
@@ -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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/heim.css?v=202610080131" />
|
||||||
<!-- Die Einweisung bringt ihr Aussehen mit. Sie steht in
|
<!-- Die Einweisung bringt ihr Aussehen mit. Sie steht in
|
||||||
anleitung.css, weil sie dorthin gehoert -- und nicht in
|
anleitung.css, weil sie dorthin gehoert -- und nicht in
|
||||||
start.css, wo sie zwischen 48 Kachelfarben verschwinden
|
start.css, wo sie zwischen 48 Kachelfarben verschwinden
|
||||||
wuerde. -->
|
wuerde. -->
|
||||||
<link rel="stylesheet" href="assets/css/anleitung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/anleitung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -768,22 +768,22 @@
|
|||||||
</p>
|
</p>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/live.js?v=202610072346" defer></script>
|
<script src="assets/js/live.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/start.js?v=202610072346" defer></script>
|
<script src="assets/js/start.js?v=202610080131" defer></script>
|
||||||
<!-- Die Begruessung und der Rundgang beim ersten Anmelden.
|
<!-- Die Begruessung und der Rundgang beim ersten Anmelden.
|
||||||
EIGENE DATEI und nicht ein Stueck start.js: Sie laeuft auf der
|
EIGENE DATEI und nicht ein Stueck start.js: Sie laeuft auf der
|
||||||
meistbenutzten Seite des Hauses, und wenn hier etwas schiefgeht,
|
meistbenutzten Seite des Hauses, und wenn hier etwas schiefgeht,
|
||||||
darf davon nichts anderes betroffen sein. -->
|
darf davon nichts anderes betroffen sein. -->
|
||||||
<script src="assets/js/rundgang.js?v=202610072346" defer></script>
|
<script src="assets/js/rundgang.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/aufstieg.js?v=202610072346" defer></script>
|
<script src="assets/js/aufstieg.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/startcheck.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/startcheck.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="wald">
|
<body class="start" data-buehne="wald">
|
||||||
@@ -85,16 +85,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/ki.js?v=202610072346" defer></script>
|
<script src="assets/js/ki.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/startcheck.js?v=202610072346" defer></script>
|
<script src="assets/js/startcheck.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/profil.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/profil.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="halle">
|
<body class="start" data-buehne="halle">
|
||||||
@@ -150,16 +150,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610072346" defer></script>
|
<script src="assets/js/hochladen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/auskunft.js?v=202610072346" defer></script>
|
<script src="assets/js/auskunft.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/steckbrief.js?v=202610072346" defer></script>
|
<script src="assets/js/steckbrief.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/support.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/support.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="studio">
|
<body class="start" data-buehne="studio">
|
||||||
@@ -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=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" 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=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/support.js?v=202610072346" defer></script>
|
<script src="assets/js/support.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+38
-9
@@ -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=202610072346" />
|
<link rel="stylesheet" href="assets/css/spendenkarte.css?v=202610080131" />
|
||||||
<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. */
|
||||||
@@ -34,19 +34,29 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
|
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
|
||||||
}
|
}
|
||||||
/* Der Kasten für die Karten füllt das Bild. Wo sie erscheinen,
|
/* Der Kasten für die Karten füllt das Bild.
|
||||||
entscheidet die Ausrichtung — unten links, wie im Saal. */
|
|
||||||
|
WO SIE STEHEN, ENTSCHEIDET SEIT DEM 08.10.2026 DAS REGIEPULT.
|
||||||
|
Die Anordnung kommt aus `spendenkarte.css` über `data-platz`,
|
||||||
|
damit Saal und Stream dieselbe Karte an derselben Stelle zeigen
|
||||||
|
— hier stand vorher eine zweite, feste Antwort („unten links"),
|
||||||
|
und die hätte jede Umstellung im Pult stillschweigend
|
||||||
|
überstimmt. `?pos=` in der Adresse bleibt als ausdrückliche
|
||||||
|
Ausnahme für eine Szene; das regelt `tafel.js`.
|
||||||
|
|
||||||
|
Hier bleibt nur, was wirklich zu DIESER Quelle gehört: Sie
|
||||||
|
liegt fest im Bild und nimmt keine Klicks an. */
|
||||||
.obs-tafel {
|
.obs-tafel {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 48px;
|
padding: 48px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
/* Am Rand braucht sie im Stream mehr Abstand als im Saal: Dort
|
||||||
|
grenzt sie an eine Bedienleiste, hier an den Bildrand, und ein
|
||||||
|
Rand von 18 Pixeln sieht auf 1080 Zeilen aus wie ein Versehen. */
|
||||||
|
.obs-tafel[data-platz="rand"] { padding: 48px; }
|
||||||
/* Auf der Bühne darf sie größer sein als im Saal: Hier deckt sie
|
/* Auf der Bühne darf sie größer sein als im Saal: Hier deckt sie
|
||||||
nichts zu, was man lesen müsste. */
|
nichts zu, was man lesen müsste. */
|
||||||
/* ALLES IN rem. Ein einziger Wert am Wurzelelement (`&g=` in der
|
/* ALLES IN rem. Ein einziger Wert am Wurzelelement (`&g=` in der
|
||||||
@@ -65,6 +75,25 @@
|
|||||||
.obs-tafel .spendenkarte__stufe { font-size: .8rem; }
|
.obs-tafel .spendenkarte__stufe { font-size: .8rem; }
|
||||||
.obs-tafel .spendenkarte__gruss { font-size: 1rem; }
|
.obs-tafel .spendenkarte__gruss { font-size: 1rem; }
|
||||||
|
|
||||||
|
/* ---- Und in der Mitte als Aufsteller (08.10.2026) --------------
|
||||||
|
Dieselben Werte eine Stufe größer. Im Stream ist die Karte in
|
||||||
|
der Bildmitte das, was in diesem Augenblick zählt — und sie
|
||||||
|
steht dort nur ein paar Sekunden.
|
||||||
|
|
||||||
|
Alles weiterhin in `rem`: Ein einziger Wert am Wurzelelement
|
||||||
|
(`&g=` in der Adresse) nimmt damit Schrift, Bild, Polsterung und
|
||||||
|
Rundung gleichmäßig mit. */
|
||||||
|
.obs-tafel[data-platz="mitte"] .spendenkarte {
|
||||||
|
max-width: 26rem;
|
||||||
|
padding: 1.6rem 1.8rem 1.7rem;
|
||||||
|
border-radius: 1.5rem;
|
||||||
|
}
|
||||||
|
.obs-tafel[data-platz="mitte"] .spendenkarte__betrag { font-size: 3rem; }
|
||||||
|
.obs-tafel[data-platz="mitte"] .spendenkarte__bild { width: 5.6rem; height: 5.6rem; }
|
||||||
|
.obs-tafel[data-platz="mitte"] .spendenkarte__wer { font-size: 1.05rem; }
|
||||||
|
.obs-tafel[data-platz="mitte"] .spendenkarte__stufe { font-size: .85rem; }
|
||||||
|
.obs-tafel[data-platz="mitte"] .spendenkarte__gruss { font-size: 1.1rem; }
|
||||||
|
|
||||||
/* Steht hier gar nichts, ist das der Normalfall — keine Spende,
|
/* Steht hier gar nichts, ist das der Normalfall — keine Spende,
|
||||||
keine Karte. Ein Hinweis darauf wäre im Stream zu sehen. */
|
keine Karte. Ein Hinweis darauf wäre im Stream zu sehen. */
|
||||||
.obs-fehler {
|
.obs-fehler {
|
||||||
@@ -80,7 +109,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=202610072346" defer></script>
|
<script src="assets/js/spendenkarte.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/tafel.js?v=202610072346" defer></script>
|
<script src="assets/js/tafel.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/bewerbung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -111,15 +111,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/talente.js?v=202610072346" defer></script>
|
<script src="assets/js/talente.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/team.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/team.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="halle">
|
<body class="start" data-buehne="halle">
|
||||||
@@ -110,15 +110,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/team.js?v=202610072346" defer></script>
|
<script src="assets/js/team.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/team.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/team.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</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=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/teamlage.js?v=202610072346" defer></script>
|
<script src="assets/js/teamlage.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/bereich.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/bereich.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -112,15 +112,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/teilen.js?v=202610072346" defer></script>
|
<script src="assets/js/teilen.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/treff.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/treff.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -126,14 +126,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/treff-moderation.js?v=202610072346" defer></script>
|
<script src="assets/js/treff-moderation.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/treff.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/treff.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</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=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/auskunft.js?v=202610072346" defer></script>
|
<script src="assets/js/auskunft.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/treff-regeln.js?v=202610072346" defer></script>
|
<script src="assets/js/treff-regeln.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/uebersicht.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="showbuehne">
|
<body class="start" data-buehne="showbuehne">
|
||||||
@@ -149,16 +149,16 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/uebersicht.js?v=202610072346" defer></script>
|
<script src="assets/js/uebersicht.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/unsere-seiten.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/unsere-seiten.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -335,14 +335,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/live.js?v=202610072346" defer></script>
|
<script src="assets/js/live.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/unsere-seiten.js?v=202610072346" defer></script>
|
<script src="assets/js/unsere-seiten.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/unterstuetzen.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/unterstuetzen.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</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=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/holen.js?v=202610072346" defer></script>
|
<script src="assets/js/holen.js?v=202610080131" 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=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/unterstuetzen.js?v=202610072346" defer></script>
|
<script src="assets/js/unterstuetzen.js?v=202610080131" 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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/entwicklung.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/werdegang.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/werdegang.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/haus.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start">
|
<body class="start">
|
||||||
@@ -144,14 +144,14 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/werdegang.js?v=202610072346" defer></script>
|
<script src="assets/js/werdegang.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
veraltet beim naechsten Umbau. -->
|
veraltet beim naechsten Umbau. -->
|
||||||
<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=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Bewusst ohne eigenes Stilblatt: Die Seite ist in aller Regel nur
|
/* Bewusst ohne eigenes Stilblatt: Die Seite ist in aller Regel nur
|
||||||
|
|||||||
+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=202610072346" />
|
<link rel="icon" type="image/png" href="/assets/img/app-symbole/workspace-32.png?v=202610080131" />
|
||||||
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610072346" />
|
<link rel="apple-touch-icon" href="/assets/img/app-symbole/workspace-180.png?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/gate.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/gate.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/start.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/start.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/aufgaben.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/wissen.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/wissen.css?v=202610080131" />
|
||||||
<link rel="stylesheet" href="assets/css/module.css?v=202610072346" />
|
<link rel="stylesheet" href="assets/css/module.css?v=202610080131" />
|
||||||
<!-- 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=202610072346" />
|
<link rel="stylesheet" href="assets/css/haus.css?v=202610080131" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="start" data-buehne="arena">
|
<body class="start" data-buehne="arena">
|
||||||
@@ -190,15 +190,15 @@
|
|||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="assets/js/meldung.js?v=202610072346" defer></script>
|
<script src="assets/js/meldung.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/hochladen.js?v=202610072346" defer></script>
|
<script src="assets/js/hochladen.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/nachfrage.js?v=202610072346" defer></script>
|
<script src="assets/js/nachfrage.js?v=202610080131" defer></script>
|
||||||
|
|
||||||
<script src="assets/js/wahl.js?v=202610072346" defer></script>
|
<script src="assets/js/wahl.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/bereiche.js?v=202610072346" defer></script>
|
<script src="assets/js/bereiche.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/installieren.js?v=202610072346" defer></script>
|
<script src="assets/js/installieren.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/kopf.js?v=202610072346" defer></script>
|
<script src="assets/js/kopf.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/glocke.js?v=202610072346" defer></script>
|
<script src="assets/js/glocke.js?v=202610080131" defer></script>
|
||||||
<script src="assets/js/wissen.js?v=202610072346" defer></script>
|
<script src="assets/js/wissen.js?v=202610080131" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user