diff --git a/tools/art-farben.mjs b/tools/art-farben.mjs new file mode 100644 index 00000000..8a15544f --- /dev/null +++ b/tools/art-farben.mjs @@ -0,0 +1,357 @@ +/* ===================================================================== + EIN TON JE ART -- UND DER BEWEIS, DASS MAN SIE UNTERSCHEIDET + + Aufruf: node tools/art-farben.mjs (nur messen) + node tools/art-farben.mjs schreiben (CSS erzeugen) + + --------------------------------------------------------------------- + WARUM ÜBERHAUPT + + Alle Etiketten trugen denselben blauen Ton. Auf „Regeln & Hilfe" + stehen siebzehn Karten untereinander, auf dem Treff acht -- und das + Auge hatte nichts, woran es sich festhalten konnte. Man liest dann + jede Überschrift, statt die Seite zu überfliegen. + + --------------------------------------------------------------------- + NACH BEDEUTUNG, NICHT NACH REIHENFOLGE + + Der Ton folgt dem, was die Art SAGT: Lob grün, „etwas stimmt nicht" + warmrot, Fragen blau, Regeln golden. Deshalb trägt `frage` auf drei + Brettern denselben Ton -- wer das Muster einmal gelernt hat, soll es + überall wiedererkennen. Eine Vergabe nach Position („die erste Art + wird blau") würde genau das verhindern. + + --------------------------------------------------------------------- + UND DESHALB MISST DIESES WERKZEUG ZWEIERLEI + + 1. ABSTAND: Zwei Arten, die auf DEMSELBEN Brett vorkommen, müssen + im OKLab-Raum weit genug auseinanderliegen. Über Bretter hinweg + ist eine Wiederholung dagegen erlaubt -- man sieht nie zwei + Bretter gleichzeitig. + 2. KONTRAST: Jeder Ton muss auf dem dunklen Grund lesbar sein. + Ein hübscher Ton, den man nicht lesen kann, ist kein Ton. + + Ohne diese Messung wäre die Farbwahl eine Behauptung. Bei den + Kacheln hat genau dieselbe Rechnung sieben Töne aussortiert, die + „eigentlich verschieden aussahen". + ===================================================================== */ +import { readFileSync, writeFileSync } from "node:fs"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const HIER = dirname(fileURLToPath(import.meta.url)); +const CSS = join(HIER, "..", "workspace", "assets", "css", "bereich.css"); + +/* Der Grund, auf dem die Etiketten liegen. */ +const GRUND = "#0a121e"; + +/* ---------- Farbrechnung (aus tools/kachel-farben.mjs) --------------- */ +const linear = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4); +const zurueck = (c) => (c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055); +const srgb = (hex) => [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255); + +function oklab(hex) { + const [r, g, b] = srgb(hex).map(linear); + const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b); + const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b); + const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b); + return [ + 0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s, + 1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s, + 0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s, + ]; +} + +function ausOklch(L, C, Hgrad) { + const h = (Hgrad * Math.PI) / 180; + const a = C * Math.cos(h), b2 = C * Math.sin(h); + const l_ = (L + 0.3963377774 * a + 0.2158037573 * b2) ** 3; + const m_ = (L - 0.1055613458 * a - 0.0638541728 * b2) ** 3; + const s_ = (L - 0.0894841775 * a - 1.2914855480 * b2) ** 3; + const r = +4.0767416621 * l_ - 3.3077115913 * m_ + 0.2309699292 * s_; + const g = -1.2684380046 * l_ + 2.6097574011 * m_ - 0.3413193965 * s_; + const b = -0.0041960863 * l_ - 0.7034186147 * m_ + 1.7076147010 * s_; + const kanal = (x) => { + const v = zurueck(x); + if (v < -0.001 || v > 1.001) return null; + return Math.round(Math.min(1, Math.max(0, v)) * 255); + }; + const [R, G, B] = [kanal(r), kanal(g), kanal(b)]; + if (R === null || G === null || B === null) return null; + return "#" + [R, G, B].map((x) => x.toString(16).padStart(2, "0")).join(""); +} + +const abstand = (a, b) => { + const [x, y] = [oklab(a), oklab(b)]; + return Math.hypot(x[0] - y[0], x[1] - y[1], x[2] - y[2]); +}; + +const leuchte = (hex) => { + const [r, g, b] = srgb(hex).map(linear); + return 0.2126 * r + 0.7152 * g + 0.0722 * b; +}; +const kontrast = (a, b) => { + const [x, y] = [leuchte(a), leuchte(b)].sort((p, q) => q - p); + return (x + 0.05) / (y + 0.05); +}; + +/* ===================================================================== + DIE TÖNE -- hier steht nur die BEDEUTUNG, also der Farbwinkel + + Helligkeit und Buntheit sucht das Werkzeug selbst (siehe unten). + + WARUM NICHT VON HAND: Genau das war der erste Versuch -- feste + Helligkeit 0.80 für alle, Buntheit nach Gefühl. Ergebnis: vier Töne + lagen ausserhalb des darstellbaren Bereichs, drei Paare zu nah + beieinander. Nach dem Nachbessern waren es fünf zu nahe Paare: Wer + die Buntheit eines Violetts senkt, schiebt es näher an alles andere + Gedämpfte heran. Zwei Zahlen von Hand zu stimmen, während eine + dritte Bedingung mitläuft, geht nicht auf -- das ist eine Suche, + keine Wahl. + + Der Farbwinkel dagegen IST die Entscheidung und bleibt von Hand: + Lob grün, „etwas stimmt nicht" warmrot, Fragen blau. + ===================================================================== */ +const TOENE = { + /* Begrüßen, fragen, loben, melden -- der Treff */ + hallo: 200, // Türkis: freundlich, offen + frage: 245, // Blau: die neutrale Frage + lob: 140, // Grün: etwas war gut + problem: 25, // Warmrot: hier stimmt etwas nicht + + /* Das Anschlagbrett -- was gilt */ + ansage: 50, // Gold: eine Ansage des Teams + regel: 100, // Oliv-Gold: was fest gilt + hinweis: 255, // Blaugrau: zur Kenntnis + danke: 340, // Rosé: Dank an die Community + + /* Was ansteht -- Termine */ + stream: 300, // Violett: die Sendung + event: 345, // Magenta: der besondere Abend + turnier: 45, // Orange: Wettkampf + pause: 250, // fast grau: es fällt aus + + /* Die Wunschliste */ + technik: 220, // Stahlblau: Geräte und Ton + gemeinsam: 165, // Grün-Türkis: miteinander + sonstiges: 300, // gedämpft: alles Übrige + + /* Highlights */ + clip: 285, // Violett: bewegtes Bild + bild: 195, // Türkis: Standbild + fanart: 325, // Rosé: selbst gemacht + moment: 60, // Bernstein: der Augenblick + + /* Regeln & Hilfe */ + hilfe: 155, // Grün: hier wird geholfen + folge: 5, // Rot: was passiert, wenn + + /* Mitmachen */ + gesucht: 85, // Gold: wir suchen + lust: 135, // Grün: ich hätte Lust +}; + +/* Welche Arten auf DEMSELBEN Brett stehen -- nur hier muss der + Abstand stimmen. Abgeleitet aus den Brettern selbst, nicht von Hand + gepflegt: eine Liste, die niemand pflegt, kann nicht veralten. */ +const BRETTER = { + treff: ["hallo", "frage", "lob", "problem"], + anschlag: ["ansage", "regel", "hinweis", "danke"], + ansteht: ["stream", "event", "turnier", "pause"], + wunsch: ["stream", "technik", "gemeinsam", "sonstiges"], + highlight: ["clip", "bild", "fanart", "moment"], + regeln: ["regel", "frage", "hilfe", "folge"], + mitmachen: ["gesucht", "lust", "frage"], +}; + +/* Ab hier gilt ein Unterschied als erkennbar. Bei den Kacheln war die + Grenze 0.14; Etiketten sind kleiner und stehen direkt untereinander, + deshalb hier etwas strenger. */ +const MIN_ABSTAND = 0.10; +/* WCAG AA für kleine Schrift. */ +const MIN_KONTRAST = 4.5; + +/* --------------------------------------------------------------------- + MESSEN + --------------------------------------------------------------------- */ +/* --------------------------------------------------------------------- + DIE SUCHE + + Für jede Art steht der Farbwinkel fest. Gesucht werden Helligkeit + und Buntheit -- so bunt wie möglich, aber nur, wenn der Ton + + 1. in sRGB liegt, + 2. auf dunklem Grund lesbar ist und + 3. von jeder Art, die auf DEMSELBEN Brett steht, weit genug + entfernt bleibt. + + Die Arten werden nach Anzahl der Nachbarn sortiert: Wer die meisten + Bedingungen erfüllen muss, wählt zuerst. Umgekehrt bliebe für ihn am + Ende nichts übrig -- dieselbe Überlegung wie bei den Kacheln. + --------------------------------------------------------------------- */ +const nachbarn = {}; +for (const arten of Object.values(BRETTER)) { + for (const a of arten) { + nachbarn[a] = nachbarn[a] || new Set(); + for (const b of arten) if (b !== a) nachbarn[a].add(b); + } +} + +const hex = {}; +let fehlt = 0; +const reihenfolge = Object.keys(TOENE) + .sort((a, b) => (nachbarn[b]?.size || 0) - (nachbarn[a]?.size || 0)); + +for (const art of reihenfolge) { + const H = TOENE[art]; + /* SO GEDECKT WIE MOEGLICH, nicht so bunt wie moeglich. + + Der erste Versuch suchte die kraeftigste Fassung -- heraus kamen + Toene wie #35f695 und #f584fd: Neongruen und Neonviolett. Das + widerspricht der Hausregel („gedeckte statt reisserisch-grelle + Neon-Optik"), und auf einem Brett mit siebzehn Karten waere es + eine Leuchtreklame. + + Gesucht wird deshalb die LEISESTE Farbe, die noch reicht: gerade + bunt genug, um sie von den Nachbarn zu unterscheiden, und gerade + hell genug, um lesbar zu sein. Buntheit ist hier eine Kostenstelle, + kein Ziel. + + Helligkeit von der Mitte aus nach aussen: 0.78 ist die Vorgabe; + nur wo sie nicht reicht, wird abgewichen. */ + let bester = null, besteBuntheit = 9; + const helligkeiten = [0.78]; + for (let d = 0.01; d <= 0.10; d += 0.01) helligkeiten.push(0.78 + d, 0.78 - d); + + for (const Lv of helligkeiten) { + for (let C = 0.03; C <= 0.20; C += 0.005) { + const f = ausOklch(Lv, C, H); + if (!f) continue; + if (kontrast(f, GRUND) < MIN_KONTRAST) continue; + let passt = true; + for (const n of (nachbarn[art] || [])) { + if (hex[n] && abstand(f, hex[n]) < MIN_ABSTAND) { passt = false; break; } + } + if (!passt) continue; + /* Der erste Treffer je Helligkeit ist schon der leiseste. */ + if (C < besteBuntheit) { besteBuntheit = C; bester = f; } + break; + } + /* Reicht die Vorgabe-Helligkeit, wird gar nicht weitergesucht. */ + if (bester && besteBuntheit <= 0.08) break; + } + if (!bester) { + console.log(`FEHL ${art}: kein Ton gefunden, der alle drei Bedingungen erfuellt`); + fehlt++; + continue; + } + hex[art] = bester; +} + +console.log("=== Kontrast auf dunklem Grund ==="); +let zuDunkel = 0; +for (const [art, f] of Object.entries(hex)) { + const k = kontrast(f, GRUND); + if (k < MIN_KONTRAST) { zuDunkel++; console.log(` FEHL ${art.padEnd(10)} ${f} ${k.toFixed(2)}`); } +} +console.log(zuDunkel ? ` ${zuDunkel} Ton/Töne zu dunkel` : ` alle ${Object.keys(hex).length} Töne lesbar`); + +console.log(""); +console.log("=== Abstand INNERHALB eines Bretts ==="); +let zuNah = 0, paare = 0; +for (const [brett, arten] of Object.entries(BRETTER)) { + let kleinster = 9, wo = ""; + for (let i = 0; i < arten.length; i++) { + for (let j = i + 1; j < arten.length; j++) { + if (!hex[arten[i]] || !hex[arten[j]]) continue; + paare++; + const d = abstand(hex[arten[i]], hex[arten[j]]); + if (d < kleinster) { kleinster = d; wo = `${arten[i]}/${arten[j]}`; } + if (d < MIN_ABSTAND) { + zuNah++; + console.log(` FEHL ${brett}: ${arten[i]} und ${arten[j]} nur ${d.toFixed(3)} auseinander`); + } + } + } + console.log(` ${brett.padEnd(11)} engstes Paar ${wo.padEnd(22)} ${kleinster.toFixed(3)}`); +} + +/* --------------------------------------------------------------------- + STIMMT DAS CSS NOCH MIT DIESER RECHNUNG UEBEREIN? + + Ohne diese Frage prueft das Werkzeug nur sich selbst. Jemand aendert + einen Ton von Hand im CSS -- weil er dunkler aussehen soll --, und + die Messung hier bleibt gruen, weil sie ihre eigene Tabelle misst + und nicht das, was ausgeliefert wird. Genau die Art Pruefung, die + immer bestaetigt. + --------------------------------------------------------------------- */ +let abweichend = 0, verglichen = 0; +if (process.argv[2] !== "schreiben") { + let css = ""; + try { css = readFileSync(CSS, "utf8"); } catch { css = ""; } + if (!css) { + console.log(""); + console.log(" -- bereich.css nicht lesbar -- nicht abgeglichen"); + } else { + console.log(""); + console.log("=== Stimmt das CSS mit dieser Rechnung ueberein? ==="); + for (const [art, f] of Object.entries(hex)) { + const treffer = new RegExp( + `\\.marke-art\\[data-art="${art}"\\]\\s*\\{\\s*--art-ton:\\s*(#[0-9a-f]{6})`, "i").exec(css); + verglichen++; + if (!treffer) { + abweichend++; + console.log(` FEHL ${art.padEnd(10)} steht gar nicht im CSS`); + } else if (treffer[1].toLowerCase() !== f.toLowerCase()) { + abweichend++; + console.log(` FEHL ${art.padEnd(10)} CSS ${treffer[1]} statt ${f}`); + } + } + /* Die Anzahl gehoert in die Bedingung -- sonst waere „0 Abweichungen" + auch bei leerer Tabelle wahr. */ + console.log(verglichen >= 20 && abweichend === 0 + ? ` alle ${verglichen} Toene im CSS stimmen` + : ` ${abweichend} von ${verglichen} weichen ab -- „node tools/art-farben.mjs schreiben" hilft`); + } +} + +console.log(""); +if (fehlt || zuDunkel || zuNah || abweichend || (process.argv[2] !== "schreiben" && verglichen < 20)) { + console.log(`NICHT IN ORDNUNG -- ${fehlt} ausserhalb, ${zuDunkel} zu dunkel, ` + + `${zuNah} zu nah, ${abweichend} weichen vom CSS ab`); + process.exit(1); +} +console.log(`ALLES IN ORDNUNG -- ${Object.keys(hex).length} Töne, ${paare} Paare geprüft`); + +/* --------------------------------------------------------------------- + SCHREIBEN + --------------------------------------------------------------------- */ +if (process.argv[2] === "schreiben") { + const zeilen = Object.entries(hex).map(([art, f]) => + `.marke-art[data-art="${art}"] { --art-ton: ${f}; }`); + const block = ` +/* ---- EIN TON JE ART (18.09.2026) ---------------------------------- + Erzeugt von tools/art-farben.mjs -- NICHT von Hand ändern. + Das Werkzeug misst zweierlei und lässt sich nicht überreden: + den Abstand zwischen zwei Arten auf DEMSELBEN Brett (OKLab, ab + ${MIN_ABSTAND}) und den Kontrast auf dunklem Grund (ab ${MIN_KONTRAST}:1). + + Warum überhaupt: Alle Etiketten trugen denselben blauen Ton. Bei + siebzehn Karten untereinander hatte das Auge nichts, woran es sich + festhalten konnte -- man liest dann jede Überschrift, statt zu + überfliegen. Der Ton folgt der BEDEUTUNG, nicht der Reihenfolge: + Lob grün, „etwas stimmt nicht" warmrot, Fragen blau. Deshalb trägt + die Art „frage" auf drei Brettern denselben Ton. */ +.marke-art[data-art] { + background: color-mix(in srgb, var(--art-ton) 16%, transparent); + color: var(--art-ton); +} +${zeilen.join("\n")} +`; + let css = readFileSync(CSS, "utf8"); + const marke = "/* ---- EIN TON JE ART (18.09.2026) ---"; + const i = css.indexOf(marke); + if (i >= 0) css = css.slice(0, i).replace(/\n+$/, "\n"); + writeFileSync(CSS, css + block, "utf8"); + console.log(`\n${zeilen.length} Töne nach bereich.css geschrieben.`); +} diff --git a/workspace/app.webmanifest b/workspace/app.webmanifest index 4ab004d7..8375e538 100644 --- a/workspace/app.webmanifest +++ b/workspace/app.webmanifest @@ -22,25 +22,25 @@ }, "icons": [ { - "src": "/assets/img/app-symbole/workspace-192.png?v=202609181858", + "src": "/assets/img/app-symbole/workspace-192.png?v=202609182010", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/workspace-512.png?v=202609181858", + "src": "/assets/img/app-symbole/workspace-512.png?v=202609182010", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609181858", + "src": "/assets/img/app-symbole/workspace-192-maskable.png?v=202609182010", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { - "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609181858", + "src": "/assets/img/app-symbole/workspace-512-maskable.png?v=202609182010", "sizes": "512x512", "type": "image/png", "purpose": "maskable" diff --git a/workspace/assets/css/bereich.css b/workspace/assets/css/bereich.css index 2bf69abe..c7c8f30e 100644 --- a/workspace/assets/css/bereich.css +++ b/workspace/assets/css/bereich.css @@ -1504,3 +1504,43 @@ } .starthilfe__beispiel:hover { border-color: var(--akzent); } .starthilfe__beispiel:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; } + +/* ---- EIN TON JE ART (18.09.2026) ---------------------------------- + Erzeugt von tools/art-farben.mjs -- NICHT von Hand ändern. + Das Werkzeug misst zweierlei und lässt sich nicht überreden: + den Abstand zwischen zwei Arten auf DEMSELBEN Brett (OKLab, ab + 0.1) und den Kontrast auf dunklem Grund (ab 4.5:1). + + Warum überhaupt: Alle Etiketten trugen denselben blauen Ton. Bei + siebzehn Karten untereinander hatte das Auge nichts, woran es sich + festhalten konnte -- man liest dann jede Überschrift, statt zu + überfliegen. Der Ton folgt der BEDEUTUNG, nicht der Reihenfolge: + Lob grün, „etwas stimmt nicht" warmrot, Fragen blau. Deshalb trägt + die Art „frage" auf drei Brettern denselben Ton. */ +.marke-art[data-art] { + background: color-mix(in srgb, var(--art-ton) 16%, transparent); + color: var(--art-ton); +} +.marke-art[data-art="frage"] { --art-ton: #a8baca; } +.marke-art[data-art="regel"] { --art-ton: #c2b981; } +.marke-art[data-art="stream"] { --art-ton: #bab3c8; } +.marke-art[data-art="hallo"] { --art-ton: #90e1e6; } +.marke-art[data-art="lob"] { --art-ton: #90b888; } +.marke-art[data-art="problem"] { --art-ton: #e4a59f; } +.marke-art[data-art="ansage"] { --art-ton: #e2ccc0; } +.marke-art[data-art="hinweis"] { --art-ton: #a9b9ce; } +.marke-art[data-art="danke"] { --art-ton: #c592b3; } +.marke-art[data-art="event"] { --art-ton: #f8bcdd; } +.marke-art[data-art="turnier"] { --art-ton: #d69b81; } +.marke-art[data-art="pause"] { --art-ton: #7ba2cc; } +.marke-art[data-art="technik"] { --art-ton: #8ed7ef; } +.marke-art[data-art="gemeinsam"] { --art-ton: #86c4a8; } +.marke-art[data-art="sonstiges"] { --art-ton: #dbcaff; } +.marke-art[data-art="clip"] { --art-ton: #b5b5ca; } +.marke-art[data-art="bild"] { --art-ton: #8adbdb; } +.marke-art[data-art="fanart"] { --art-ton: #b88dba; } +.marke-art[data-art="moment"] { --art-ton: #deac83; } +.marke-art[data-art="hilfe"] { --art-ton: #a4deb7; } +.marke-art[data-art="folge"] { --art-ton: #e8a5b4; } +.marke-art[data-art="gesucht"] { --art-ton: #ceb480; } +.marke-art[data-art="lust"] { --art-ton: #bfdbb1; } diff --git a/workspace/assets/js/bereich.js b/workspace/assets/js/bereich.js index 751793f7..68cf7822 100644 --- a/workspace/assets/js/bereich.js +++ b/workspace/assets/js/bereich.js @@ -331,7 +331,12 @@ k.dataset.status = e.status; const kopf = el('div', 'eintrag-kopf'); - kopf.append(el('span', 'marke-art', einstellung.arten[e.art] || e.art)); + const marke = el('span', 'marke-art', einstellung.arten[e.art] || e.art); + /* Die Art als Merkmal am Element -- daran haengt der Ton (siehe + tools/art-farben.mjs). Kein Klassenname je Art: Der waere eine + zweite Liste, die mit der ersten auseinanderlaeuft. */ + if (e.art) marke.dataset.art = e.art; + kopf.append(marke); /* DIE VERTRAULICHE ZEILE SAGT ES SELBST (10.09.2026). Sie kommt ohnehin nur bei DogFather und beim Schreiber an -- der diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index 71cb20f2..7e608cc3 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -12,19 +12,19 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - + + + + + + - + @@ -291,10 +291,10 @@ - - - - - + + + + + diff --git a/workspace/automation.html b/workspace/automation.html index 1841414f..b7ed83cc 100644 --- a/workspace/automation.html +++ b/workspace/automation.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -168,10 +168,10 @@ - - - - - + + + + + diff --git a/workspace/befinden.html b/workspace/befinden.html index 70460843..41d97b87 100644 --- a/workspace/befinden.html +++ b/workspace/befinden.html @@ -7,14 +7,14 @@ - - - - - - - - + + + + + + + + @@ -105,9 +105,9 @@ - - - - + + + + diff --git a/workspace/bereich.html b/workspace/bereich.html index 3343ba62..4a80cf18 100644 --- a/workspace/bereich.html +++ b/workspace/bereich.html @@ -12,24 +12,24 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - + + + + + + - - + + - + @@ -251,14 +251,14 @@ - - - - - - - - - + + + + + + + + + diff --git a/workspace/bewerben.html b/workspace/bewerben.html index feaeea57..80d78e7d 100644 --- a/workspace/bewerben.html +++ b/workspace/bewerben.html @@ -7,17 +7,17 @@ - - - - - - - - - + + + + + + + + + - + @@ -107,10 +107,10 @@ - - - - - + + + + + diff --git a/workspace/bewerbungen.html b/workspace/bewerbungen.html index 3c96b205..8c647944 100644 --- a/workspace/bewerbungen.html +++ b/workspace/bewerbungen.html @@ -7,16 +7,16 @@ - - - - - - - - + + + + + + + + - + @@ -80,10 +80,10 @@ - - - - - + + + + + diff --git a/workspace/calls.html b/workspace/calls.html index 82708639..eb18eabe 100644 --- a/workspace/calls.html +++ b/workspace/calls.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -89,11 +89,11 @@ - - - - - - + + + + + + diff --git a/workspace/chat.html b/workspace/chat.html index d98148dc..97798eb4 100644 --- a/workspace/chat.html +++ b/workspace/chat.html @@ -12,26 +12,26 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - - + + + - + @@ -341,15 +341,15 @@ - - - - + + + + - - + + diff --git a/workspace/content.html b/workspace/content.html index 50cbf5ef..6db56f06 100644 --- a/workspace/content.html +++ b/workspace/content.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -179,12 +179,12 @@ - - - - - - - + + + + + + + diff --git a/workspace/crew-index.html b/workspace/crew-index.html index bb564762..b85d942d 100644 --- a/workspace/crew-index.html +++ b/workspace/crew-index.html @@ -36,15 +36,15 @@ - - - + + + - + @@ -339,6 +339,6 @@ - + diff --git a/workspace/crew.webmanifest b/workspace/crew.webmanifest index afeb8a1a..5f241a83 100644 --- a/workspace/crew.webmanifest +++ b/workspace/crew.webmanifest @@ -22,25 +22,25 @@ }, "icons": [ { - "src": "/assets/img/app-symbole/crew-192.png?v=202609181858", + "src": "/assets/img/app-symbole/crew-192.png?v=202609182010", "sizes": "192x192", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/crew-512.png?v=202609181858", + "src": "/assets/img/app-symbole/crew-512.png?v=202609182010", "sizes": "512x512", "type": "image/png", "purpose": "any" }, { - "src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609181858", + "src": "/assets/img/app-symbole/crew-192-maskable.png?v=202609182010", "sizes": "192x192", "type": "image/png", "purpose": "maskable" }, { - "src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609181858", + "src": "/assets/img/app-symbole/crew-512-maskable.png?v=202609182010", "sizes": "512x512", "type": "image/png", "purpose": "maskable" diff --git a/workspace/dateien.html b/workspace/dateien.html index e6889c15..d286c926 100644 --- a/workspace/dateien.html +++ b/workspace/dateien.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -108,10 +108,10 @@ - - - - - + + + + + diff --git a/workspace/entwicklung.html b/workspace/entwicklung.html index bff39be5..e1e6c3c3 100644 --- a/workspace/entwicklung.html +++ b/workspace/entwicklung.html @@ -7,14 +7,14 @@ - - - - - - - - + + + + + + + + @@ -102,9 +102,9 @@ - - - - + + + + diff --git a/workspace/index.html b/workspace/index.html index 95dbbec2..fb1b7732 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -30,9 +30,9 @@ - - - + + + @@ -401,6 +401,6 @@ - + diff --git a/workspace/kalender.html b/workspace/kalender.html index 093da072..6656e2f1 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -377,11 +377,11 @@ - - - - - - + + + + + + diff --git a/workspace/leistung.html b/workspace/leistung.html index 1914099c..18b2d5e2 100644 --- a/workspace/leistung.html +++ b/workspace/leistung.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -444,10 +444,10 @@ - - - - - + + + + + diff --git a/workspace/personen.html b/workspace/personen.html index 477c0863..985be2ac 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -423,10 +423,10 @@ - - - - - + + + + + diff --git a/workspace/profil.html b/workspace/profil.html index e1761c4d..cf5902a3 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -214,11 +214,11 @@ - - - - - - + + + + + + diff --git a/workspace/rechte.html b/workspace/rechte.html index 62ea8f17..dfa175fb 100644 --- a/workspace/rechte.html +++ b/workspace/rechte.html @@ -7,14 +7,14 @@ - - - - - - - - + + + + + + + + @@ -134,9 +134,9 @@ Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen, die seit dem 07.09. jede Seite danach absucht. --> - - - - + + + + diff --git a/workspace/report.html b/workspace/report.html index fa90c1ac..c63ec172 100644 --- a/workspace/report.html +++ b/workspace/report.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -106,11 +106,11 @@ - - - - - - + + + + + + diff --git a/workspace/scouting.html b/workspace/scouting.html index 8d028e0c..db3c7936 100644 --- a/workspace/scouting.html +++ b/workspace/scouting.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -173,10 +173,10 @@ - - - - - + + + + + diff --git a/workspace/start.html b/workspace/start.html index 4321ec84..9f3e2ce4 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -12,21 +12,21 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - + + - + @@ -674,10 +674,10 @@

- - - - - + + + + + diff --git a/workspace/startcheck.html b/workspace/startcheck.html index d3c95338..6c186247 100644 --- a/workspace/startcheck.html +++ b/workspace/startcheck.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -85,11 +85,11 @@ - - - - - - + + + + + + diff --git a/workspace/steckbrief.html b/workspace/steckbrief.html index ce1a53cc..97e9b3d8 100644 --- a/workspace/steckbrief.html +++ b/workspace/steckbrief.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -146,11 +146,11 @@ - - - - - - + + + + + + diff --git a/workspace/talente.html b/workspace/talente.html index 2864dd42..fd623f76 100644 --- a/workspace/talente.html +++ b/workspace/talente.html @@ -7,18 +7,18 @@ - - - - - - + + + + + + - - - + + + @@ -111,9 +111,9 @@ - - - - + + + + diff --git a/workspace/team.html b/workspace/team.html index 5e5c5a18..02370658 100644 --- a/workspace/team.html +++ b/workspace/team.html @@ -7,20 +7,20 @@ - - - - - - - + + + + + + + - + @@ -110,10 +110,10 @@ - - - - - + + + + + diff --git a/workspace/teamlage.html b/workspace/teamlage.html index a94e56f1..7780ca80 100644 --- a/workspace/teamlage.html +++ b/workspace/teamlage.html @@ -7,20 +7,20 @@ - - - - - - - + + + + + + + - + - - - - + + + + diff --git a/workspace/teilen.html b/workspace/teilen.html index c138d85a..2871657e 100644 --- a/workspace/teilen.html +++ b/workspace/teilen.html @@ -7,13 +7,13 @@ - - - - - - - + + + + + + + @@ -112,9 +112,9 @@ - - - - + + + + diff --git a/workspace/treff-moderation.html b/workspace/treff-moderation.html index 4a7af4bf..d219df6b 100644 --- a/workspace/treff-moderation.html +++ b/workspace/treff-moderation.html @@ -7,14 +7,14 @@ - - - - - - - - + + + + + + + + @@ -126,9 +126,9 @@ - - - - + + + + diff --git a/workspace/treff-regeln.html b/workspace/treff-regeln.html index 097c0929..0746cb4f 100644 --- a/workspace/treff-regeln.html +++ b/workspace/treff-regeln.html @@ -7,18 +7,18 @@ - - - - - - - + + + + + + + - + @@ -211,10 +211,10 @@ Beim ersten Anlauf fehlte die Zeile auf genau diesen beiden neuen Seiten. Gefunden hat das nicht das Auge, sondern pruef-css-klassen, die seit dem 07.09. jede Seite danach absucht. --> - - - - - + + + + + diff --git a/workspace/uebersicht.html b/workspace/uebersicht.html index de245537..30468f68 100644 --- a/workspace/uebersicht.html +++ b/workspace/uebersicht.html @@ -12,22 +12,22 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - + + + + - - - + + + - + @@ -149,11 +149,11 @@ - + - - - - + + + + diff --git a/workspace/wissen.html b/workspace/wissen.html index e6438a40..b66b7332 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -12,20 +12,20 @@ Ton wie die Kopfleiste darunter (#06090f), damit Leiste und Seite eine Flaeche sind statt zweier. --> - - - - - - - + + + + + + + - + @@ -190,10 +190,10 @@ - - - - - + + + + +