diff --git a/pruef-start-computer.png b/pruef-start-computer.png index 0c08eca1..4a061d70 100644 Binary files a/pruef-start-computer.png and b/pruef-start-computer.png differ diff --git a/pruef-start-creator.png b/pruef-start-creator.png index 3f12157e..130008ab 100644 Binary files a/pruef-start-creator.png and b/pruef-start-creator.png differ diff --git a/pruef-start-handy.png b/pruef-start-handy.png index ff1d459c..d8ccd90f 100644 Binary files a/pruef-start-handy.png and b/pruef-start-handy.png differ diff --git a/server/pruef-start-ansicht.mjs b/server/pruef-start-ansicht.mjs index 626dfb05..8ff0532c 100644 --- a/server/pruef-start-ansicht.mjs +++ b/server/pruef-start-ansicht.mjs @@ -99,6 +99,10 @@ const lesen = (seite) => seite.evaluate(() => ({ .filter((z) => z.offsetParent !== null).length, hinweiseGesamt: document.querySelectorAll("#dran .dran__punkt").length, zeichenGroesse: Math.round(document.querySelector(".kachel__zeichen")?.getBoundingClientRect().width || 0), + wasserzeichen: document.querySelectorAll(".kachel__wasserzeichen").length, + wasserzeichenDeckung: getComputedStyle(document.querySelector(".kachel__wasserzeichen") || document.body).opacity, + wasserzeichenSchwach: Number(getComputedStyle( + document.querySelector(".kachel__wasserzeichen") || document.body).opacity) <= 0.15, namenGroesse: Math.round(parseFloat(getComputedStyle(document.querySelector(".kachel__name")).fontSize) || 0), kachelHoehe: Math.round(document.querySelectorAll(".kachel")[1]?.getBoundingClientRect().height || 0), zahlenLeer: !document.getElementById("zahlen-leer")?.hidden, @@ -131,6 +135,13 @@ for (const [breite, wie] of [[1440, "Computer"], [390, "Handy"]]) { /* Jede Kachel muss ein Zeichen haben -- eine ohne waere ein leeres Kaestchen und faellt sofort auf. */ + /* Das Wasserzeichen: dasselbe Zeichen noch einmal, riesig und schwach + im Hintergrund. Es macht jede Kachel unverwechselbar -- fehlt es, + sehen alle wieder gleich aus. */ + ok(r.wasserzeichen === r.kacheln.length, + `jede Kachel trägt ihr Wasserzeichen (${r.wasserzeichen} von ${r.kacheln.length})`); + ok(r.wasserzeichenSchwach, `und es ist schwach genug, um nicht zu stören (${r.wasserzeichenDeckung})`); + ok(r.kacheln.every((k) => k.pfade > 0), `jede Kachel hat ein Zeichen (${r.kacheln.filter((k) => !k.pfade).map((k) => k.name).join(", ") || "alle"})`); ok(r.kacheln.every((k) => k.unter && k.unter.length > 4), "jede Kachel sagt, was drin ist"); @@ -138,7 +149,12 @@ for (const [breite, wie] of [[1440, "Computer"], [390, "Handy"]]) { /* Acht verschiedene Farben, und nirgends steht "ÖFFNEN" mehr. */ const toene = new Set(r.kacheln.map((k) => k.farbe)); - ok(toene.size === 8, `acht verschiedene Farbtöne im Einsatz (${toene.size})`); + /* JEDE Kachel ihre eigene Farbe -- siebzehn verschiedene, keine + doppelt. (Der Creator sieht "Mein Profil" statt "Creator-Profile"; + das sind zwei Namen fuer denselben Bereich und teilen sich einen + Ton -- deshalb wird hier gegen die Zahl der KACHELN geprueft.) */ + ok(toene.size === r.kacheln.length, + `jede Kachel hat ihre eigene Farbe (${toene.size} Farben auf ${r.kacheln.length} Kacheln)`); const oeffnen = await seite.evaluate(() => document.body.textContent.includes("ÖFFNEN")); ok(!oeffnen, "das Wort ÖFFNEN kommt nicht mehr vor"); diff --git a/tools/kachel-farben.mjs b/tools/kachel-farben.mjs new file mode 100644 index 00000000..e42779f8 --- /dev/null +++ b/tools/kachel-farben.mjs @@ -0,0 +1,143 @@ +/* =================================================================== + Die 17 Kachelfarben der Startseite -- und wer welche bekommt. + + Filipe wollte, dass JEDE Kachel ihre eigene Farbe hat. Ein erster + Versuch mit frei gewaehlten Farben ergab Paare mit einem Abstand von + 1,4 -- also praktisch dieselbe Farbe. Das sieht nach Zufall aus, nicht + nach Absicht. + + Deshalb wird hier gerechnet statt gewaehlt: + + 1. 17 Farbtoene, gleichmaessig um den Farbkreis verteilt, in OKLCH + gerechnet (dort sind gleiche Abstaende auch fuer das Auge gleich). + Helligkeit und Farbstaerke bleiben konstant -- dadurch wirken alle + gleich stark und keine draengt sich vor. Wo eine Farbstaerke den + darstellbaren Bereich verliesse (Gelb und Gruen tun das frueher), + wird sie so weit gesenkt, bis sie hineinpasst. + + 2. Die Zuordnung ist eine Suche, kein Geschmack. Verglichen wird vom + Auge nur, was NEBENEINANDER liegt -- 17 Farben muessen sich also + nicht alle voneinander unterscheiden, sondern nur von ihren + Nachbarn im Raster. Gesucht wird die Anordnung, bei der der + kleinste Abstand zweier Nachbarn so gross wie moeglich ist. + + 3. Unter allen Anordnungen, die eine harte Untergrenze schaffen, wird + die genommen, deren Farben am besten zur Sache passen: LIVE rot, + weil "on air" rot ist. Technik gelb wie ein Warnschild. Reports + gruen wie ein Ergebnis. Personen golden wie ein Schluessel. + + Aufrufen mit: node tools/kachel-farben.mjs + Die Ausgabe wird nach start.css uebertragen (Abschnitt "Kacheln"). + =================================================================== */ + +const L = 0.655, C_MAX = 0.148; + +function oklchZuRgb(L, C, hGrad) { + const h = hGrad * Math.PI / 180; + const a = C * Math.cos(h), b = C * Math.sin(h); + const l_ = L + 0.3963377774 * a + 0.2158037573 * b; + const m_ = L - 0.1055613458 * a - 0.0638541728 * b; + const s_ = L - 0.0894841775 * a - 1.2914855480 * b; + const l = l_ ** 3, m = m_ ** 3, s = s_ ** 3; + const r = 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s; + const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s; + const bl = -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s; + const gam = (v) => (v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055); + return [gam(r), gam(g), gam(bl)]; +} +const imRaum = (rgb) => rgb.every((v) => v >= -0.001 && v <= 1.001); +const hex = (rgb) => "#" + rgb.map((v) => + Math.round(Math.min(1, Math.max(0, v)) * 255).toString(16).padStart(2, "0")).join(""); + +const winkel = (i) => (i * 360 / 17 + 250) % 360; +function farbe(i) { + let C = C_MAX; + while (C > 0.02 && !imRaum(oklchZuRgb(L, C, winkel(i)))) C -= 0.004; + return hex(oklchZuRgb(L, C, winkel(i))); +} + +const KACHELN = [ + "Dashboard", "Aufgaben", "Kalender", "Calls", "Dateien", + "Creator-Profile", "Start-Check", "LIVE", "Content", "Community", + "Technik", "Schutz", "Reports", + "Personen", "Scout", "Bibliothek", "Automationen", +]; +const N = (n) => KACHELN.indexOf(n); + +/* Nachbarschaft aus dem tatsaechlichen Aufbau der Seite: drei Spalten, + Dashboard ueber zwei. Nebeneinander UND untereinander. */ +const NACHBARN = [ + ["Dashboard", "Aufgaben"], ["Dashboard", "Kalender"], ["Dashboard", "Calls"], + ["Aufgaben", "Dateien"], ["Kalender", "Calls"], ["Calls", "Dateien"], + ["Creator-Profile", "Start-Check"], ["Start-Check", "LIVE"], + ["Content", "Community"], ["Community", "Technik"], ["Schutz", "Reports"], + ["Creator-Profile", "Content"], ["Start-Check", "Community"], ["LIVE", "Technik"], + ["Content", "Schutz"], ["Community", "Reports"], + ["Personen", "Scout"], ["Scout", "Bibliothek"], ["Personen", "Automationen"], +].map(([a, b]) => [N(a), N(b)]); + +const abstand = (a, b) => { + const d = Math.abs(winkel(a) - winkel(b)) % 360; + return Math.min(d, 360 - d); +}; + +const WUNSCH = { + LIVE: 17, Content: 38, Technik: 81, Reports: 144, Personen: 59, + Schutz: 250, Community: 335, Dashboard: 250, Kalender: 208, + Bibliothek: 271, "Start-Check": 165, +}; +function wunschNaehe(z) { + let punkte = 0; + for (const [name, wunsch] of Object.entries(WUNSCH)) { + const d = Math.abs(winkel(z[N(name)]) - wunsch) % 360; + punkte += 180 - Math.min(d, 360 - d); + } + return punkte; +} + +/* Erst die Unterscheidbarkeit sichern, dann unter allem, was das + schafft, die passendste Anordnung waehlen. */ +const MINDEST = 95; +function bewerte(z) { + let schlechtestes = 999; + for (const [a, b] of NACHBARN) schlechtestes = Math.min(schlechtestes, abstand(z[a], z[b])); + if (schlechtestes < MINDEST) return schlechtestes; // noch nicht gut genug + return 1e6 + schlechtestes * 1000 + wunschNaehe(z); +} + +/* Fester Zufall: Dieselbe Eingabe muss dieselbe Ausgabe ergeben, sonst + waeren die Farben nach jedem Lauf andere. */ +let saat = 987654321; +const zufall = () => (saat = (saat * 1103515245 + 12345) % 2147483648) / 2147483648; + +let beste = null, besteNote = -1; +for (let lauf = 0; lauf < 900; lauf++) { + const z = [...Array(17).keys()]; + for (let i = 16; i > 0; i--) { const j = Math.floor(zufall() * (i + 1)); [z[i], z[j]] = [z[j], z[i]]; } + let note = bewerte(z), besser = true; + while (besser) { + besser = false; + for (let a = 0; a < 17; a++) for (let b = a + 1; b < 17; b++) { + [z[a], z[b]] = [z[b], z[a]]; + const neu = bewerte(z); + if (neu > note) { note = neu; besser = true; } else { [z[a], z[b]] = [z[b], z[a]]; } + } + } + if (note > besteNote) { besteNote = note; beste = [...z]; } +} + +let schlechtestes = 999, paar = ""; +for (const [a, b] of NACHBARN) { + const d = abstand(beste[a], beste[b]); + if (d < schlechtestes) { schlechtestes = d; paar = `${KACHELN[a]} / ${KACHELN[b]}`; } +} + +console.log(`Kleinster Abstand zweier Nachbarn: ${schlechtestes.toFixed(1)}° (${paar})\n`); +console.log("--- fuer start.css ---"); +KACHELN.forEach((k, i) => { + console.log(`.kachel[data-ton="${beste[i] + 1}"] { --ton: ${farbe(beste[i])}; } /* ${k}, ${Math.round(winkel(beste[i]))}° */`); +}); +console.log("\n--- fuer start.js (ton je Kachel) ---"); +console.log(JSON.stringify(Object.fromEntries(KACHELN.map((k, i) => [k, beste[i] + 1])))); +console.log("\n--- alle Farben in der Reihenfolge der Plaetze ---"); +console.log([...Array(17).keys()].map((i) => farbe(i)).join(",")); diff --git a/workspace/assets/css/start.css b/workspace/assets/css/start.css index 4a4cfeef..6031d5ac 100644 --- a/workspace/assets/css/start.css +++ b/workspace/assets/css/start.css @@ -266,16 +266,39 @@ body.start { grid-template-columns: repeat(3, minmax(0, 1fr)); } -/* Die acht geprüften Töne. Zugewiesen wird der PLATZ, nicht der Rang -- - so behält ein Bereich seine Farbe, auch wenn andere dazukommen. */ -.kachel[data-ton="1"] { --ton: #3987e5; } -.kachel[data-ton="2"] { --ton: #d95926; } -.kachel[data-ton="3"] { --ton: #199e70; } -.kachel[data-ton="4"] { --ton: #c98500; } -.kachel[data-ton="5"] { --ton: #d55181; } -.kachel[data-ton="6"] { --ton: #4d9e4d; } -.kachel[data-ton="7"] { --ton: #9085e9; } -.kachel[data-ton="8"] { --ton: #e66767; } +/* Siebzehn eigene Töne -- einer je Kachel. Nicht gewählt, sondern + gerechnet: gleichmäßig um den Farbkreis verteilt, in OKLCH bei + konstanter Helligkeit und Farbstärke, damit keine sich vordrängt. + Erzeugt von tools/kachel-farben.mjs; dort steht auch, warum. + + Die ZUORDNUNG ist ebenfalls gerechnet. Das Auge vergleicht nur, was + NEBENEINANDER liegt -- gesucht wurde deshalb die Anordnung mit dem + größtmöglichen kleinsten Abstand zweier Nachbarn im Raster. Ergebnis: + mindestens 105,9 Grad zwischen allen Nachbarn. Zum Vergleich: Der + erste Versuch mit frei gewählten Farben hatte Paare bei 1,4 Grad. + + Unter allen Anordnungen, die das schaffen, wurde die passendste + genommen -- LIVE rot, Technik gelb, Reports grün, Personen rot-gold. + + Geprüft gegen genau diesen Hintergrund: Helligkeitsband, Farbstärke + und Kontrast bestehen für alle siebzehn. */ +.kachel[data-ton="1"] { --ton: #3e95e7; } /* 250° */ +.kachel[data-ton="2"] { --ton: #7089ea; } /* 271° */ +.kachel[data-ton="3"] { --ton: #947de2; } /* 292° */ +.kachel[data-ton="4"] { --ton: #b173d0; } /* 314° */ +.kachel[data-ton="5"] { --ton: #c66ab5; } /* 335° */ +.kachel[data-ton="6"] { --ton: #d56694; } /* 356° */ +.kachel[data-ton="7"] { --ton: #dc666f; } /* 17° */ +.kachel[data-ton="8"] { --ton: #db6c48; } /* 38° */ +.kachel[data-ton="9"] { --ton: #d17717; } /* 59° */ +.kachel[data-ton="10"] { --ton: #ba8610; } /* 81° */ +.kachel[data-ton="11"] { --ton: #a29205; } /* 102° */ +.kachel[data-ton="12"] { --ton: #809e23; } /* 123° */ +.kachel[data-ton="13"] { --ton: #50a752; } /* 144° */ +.kachel[data-ton="14"] { --ton: #07aa7c; } /* 165° */ +.kachel[data-ton="15"] { --ton: #12a69b; } /* 186° */ +.kachel[data-ton="16"] { --ton: #04a3b4; } /* 208° */ +.kachel[data-ton="17"] { --ton: #059ece; } /* 229° */ .kachel { --ton: var(--akzent); @@ -336,10 +359,39 @@ body.start { .kachel__link { position: relative; z-index: 1; - display: flex; align-items: center; gap: 14px; - padding: 18px 18px 18px 21px; + display: flex; align-items: center; gap: 15px; + padding: 21px 20px 21px 23px; color: inherit; text-decoration: none; } + +/* Das Wasserzeichen. Dasselbe Zeichen wie im Feld links, aber riesig, + angeschnitten und fast unsichtbar in der rechten unteren Ecke. + + Es ist der Grund, warum siebzehn Kacheln nicht mehr wie siebzehn + Kästen aussehen: Jede bekommt eine eigene große Form, ohne dass ein + einziges zusätzliches Bild geladen wird. Bewusst so schwach, dass man + es nicht liest, sondern nur spürt -- eine Kachel soll ihren Namen + tragen, nicht ihr Zeichen. */ +.kachel__wasserzeichen { + position: absolute; right: -14px; bottom: -26px; + width: 132px; height: 132px; + pointer-events: none; z-index: 0; + opacity: .07; + transform: rotate(-8deg); + transition: opacity var(--tempo), transform var(--tempo); +} +.kachel__wasserzeichen svg { + width: 100%; height: 100%; + fill: none; stroke: var(--ton); + stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round; +} +.kachel:hover .kachel__wasserzeichen { + opacity: .13; + transform: rotate(-8deg) translate(-4px, -4px) scale(1.04); +} +.kachel[data-gross="ja"] .kachel__wasserzeichen { + width: 168px; height: 168px; right: -18px; bottom: -34px; +} .kachel__link:focus-visible { outline: 2px solid var(--ton); outline-offset: -4px; border-radius: 15px; } @@ -348,40 +400,50 @@ body.start { eine Fläche, ohne dass die ganze Kachel farbig wird. Der Verlauf und der innere Lichtrand darin lassen es geprägt statt gemalt wirken. */ .kachel__zeichen { + position: relative; z-index: 1; flex: none; display: grid; place-items: center; - width: 46px; height: 46px; border-radius: 14px; + width: 52px; height: 52px; border-radius: 15px; background: linear-gradient(160deg, - color-mix(in srgb, var(--ton) 26%, transparent), - color-mix(in srgb, var(--ton) 9%, transparent)); - border: 1px solid color-mix(in srgb, var(--ton) 30%, transparent); - box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ton) 32%, transparent); - transition: background var(--tempo), border-color var(--tempo), transform var(--tempo); + color-mix(in srgb, var(--ton) 30%, transparent), + color-mix(in srgb, var(--ton) 10%, transparent)); + border: 1px solid color-mix(in srgb, var(--ton) 32%, transparent); + /* Lichtkante innen oben, weicher Schein nach aussen -- dadurch wirkt + das Feld geprägt statt gemalt. Der Schein bleibt schwach; ein + leuchtender Kasten wäre in einer dunklen Oberfläche eine Lampe. */ + box-shadow: + inset 0 1px 0 color-mix(in srgb, var(--ton) 38%, transparent), + 0 4px 14px -8px color-mix(in srgb, var(--ton) 60%, transparent); + transition: background var(--tempo), border-color var(--tempo), + transform var(--tempo), box-shadow var(--tempo); } .kachel:hover .kachel__zeichen { background: linear-gradient(160deg, - color-mix(in srgb, var(--ton) 40%, transparent), - color-mix(in srgb, var(--ton) 14%, transparent)); - border-color: color-mix(in srgb, var(--ton) 58%, transparent); - transform: scale(1.04); + color-mix(in srgb, var(--ton) 46%, transparent), + color-mix(in srgb, var(--ton) 16%, transparent)); + border-color: color-mix(in srgb, var(--ton) 62%, transparent); + transform: scale(1.05); + box-shadow: + inset 0 1px 0 color-mix(in srgb, var(--ton) 55%, transparent), + 0 6px 20px -8px color-mix(in srgb, var(--ton) 85%, transparent); } -.kachel[data-gross="ja"] .kachel__zeichen { width: 56px; height: 56px; border-radius: 17px; } +.kachel[data-gross="ja"] .kachel__zeichen { width: 62px; height: 62px; border-radius: 18px; } .kachel__svg { - width: 23px; height: 23px; + width: 25px; height: 25px; fill: none; stroke: var(--ton); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; } -.kachel[data-gross="ja"] .kachel__svg { width: 28px; height: 28px; } +.kachel[data-gross="ja"] .kachel__svg { width: 31px; height: 31px; } -.kachel__text { display: grid; gap: 3px; min-width: 0; } +.kachel__text { position: relative; z-index: 1; display: grid; gap: 3px; min-width: 0; } .kachel__name { - font-size: 1.02rem; font-weight: 650; letter-spacing: -.012em; line-height: 1.25; + font-size: 1.06rem; font-weight: 650; letter-spacing: -.014em; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } -.kachel[data-gross="ja"] .kachel__name { font-size: 1.18rem; } +.kachel[data-gross="ja"] .kachel__name { font-size: 1.24rem; } .kachel__unter { font-size: .78rem; color: var(--text-still); line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -392,6 +454,7 @@ body.start { liegt -- eine Kachel, die "3" sagt, ist zehnmal mehr wert als eine, die "öffnen" sagt. */ .kachel__zahl { + position: relative; z-index: 1; flex: none; margin-left: auto; min-width: 32px; padding: 5px 11px; text-align: center; font-size: .9rem; font-weight: 700; @@ -418,6 +481,7 @@ body.start { } .kachel__pfeil { + position: relative; z-index: 1; flex: none; margin-left: auto; color: var(--text-still); font-size: 1rem; transition: color var(--tempo), transform var(--tempo); @@ -537,6 +601,10 @@ body.start { .dran__link:hover .dran__pfeil { color: var(--akzent); transform: translateX(3px); } @media (prefers-reduced-motion: reduce) { + .kachel__wasserzeichen, .kachel__zeichen { transition: none; } + .kachel:hover .kachel__wasserzeichen { transform: rotate(-8deg); } + .kachel:hover .kachel__zeichen { transform: none; } + .dran__punkt, .dran__pfeil { transition: none; } .dran__link:hover .dran__pfeil { transform: none; } } diff --git a/workspace/assets/js/start.js b/workspace/assets/js/start.js index ade92a9a..0370478b 100644 --- a/workspace/assets/js/start.js +++ b/workspace/assets/js/start.js @@ -75,30 +75,35 @@ `rollen` steuert, wem ein Bereich überhaupt erscheint -- serverseitig wird es ohnehin noch einmal geprüft, das hier ist nur Höflichkeit. - `ton` ist der Farbplatz 1..8. Warum acht und nicht siebzehn: Siebzehn - unterscheidbare Farben gibt es nicht. Ein erster Versuch mit einer - eigenen Farbe je Kachel ergab Paare mit einem Abstand von 1.4 -- also - praktisch dieselbe Farbe, und das sieht nach Zufall aus statt nach - Absicht. Diese acht sind gegen genau diesen Hintergrund geprüft - (Helligkeit, Farbstärke, Farbfehlsichtigkeit, Kontrast, alles - bestanden) und so verteilt, dass in einer Zeile nie zweimal derselbe - Ton steht. Die Farbe stützt nur -- was die Kachel IST, sagen Zeichen - und Name. */ + `ton` ist der Farbplatz 1..17 -- JEDE Kachel hat ihre eigene Farbe. + + Ein erster Versuch mit frei gewählten Farben ergab Paare mit einem + Abstand von 1,4: praktisch dieselbe Farbe, das sieht nach Zufall aus + statt nach Absicht. Deshalb sind Farben UND Zuordnung gerechnet, von + tools/kachel-farben.mjs. Die Überlegung dahinter: Das Auge vergleicht + nur, was nebeneinander liegt. Siebzehn Farben müssen sich also nicht + alle voneinander unterscheiden, sondern nur von ihren Nachbarn im + Raster -- und da sind es jetzt mindestens 105,9 Grad. + + Wer hier Kacheln umsortiert oder eine hinzufügt, ändert damit die + Nachbarschaften. Dann gehört tools/kachel-farben.mjs neu gelaufen + (dort die Liste NACHBARN anpassen), sonst stimmt der Abstand nicht + mehr und niemand merkt es. */ const GRUPPEN = [ { name: 'Täglich', unter: 'Was du sowieso jeden Tag aufmachst', bereiche: [ - { name: 'Dashboard', unter: 'Alle Creator auf einen Blick', zeichen: 'dashboard', ton: 1, + { name: 'Dashboard', unter: 'Alle Creator auf einen Blick', zeichen: 'dashboard', ton: 3, gross: true, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'uebersicht.html' }, - { name: 'Aufgaben', unter: 'Offen, in Arbeit, Review', zeichen: 'aufgaben', ton: 7, + { name: 'Aufgaben', unter: 'Offen, in Arbeit, Review', zeichen: 'aufgaben', ton: 9, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'aufgaben.html' }, - { name: 'Kalender', unter: 'Termine und Calls', zeichen: 'kalender', ton: 3, + { name: 'Kalender', unter: 'Termine und Calls', zeichen: 'kalender', ton: 15, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'kalender.html' }, - { name: 'Calls & Protokolle', unter: 'Gespräche mit To-dos', zeichen: 'calls', ton: 5, + { name: 'Calls & Protokolle', unter: 'Gespräche mit To-dos', zeichen: 'calls', ton: 8, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'calls.html' }, - { name: 'Dateien', unter: 'Ablage und Freigaben', zeichen: 'dateien', ton: 4, + { name: 'Dateien', unter: 'Ablage und Freigaben', zeichen: 'dateien', ton: 16, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'dateien.html' }, ], }, @@ -106,23 +111,23 @@ name: 'Rund um den Creator', unter: 'Die Betreuungsakte – Stand, Zahlen, Verlauf', bereiche: [ - { name: 'Creator-Profile', unter: 'Ziele und 90-Tage-Plan', zeichen: 'profil', ton: 1, + { name: 'Creator-Profile', unter: 'Ziele und 90-Tage-Plan', zeichen: 'profil', ton: 4, rollen: ['admin', 'manager', 'scout'], ziel: 'profil.html' }, - { name: 'Mein Profil', unter: 'Deine Ziele und Pläne', zeichen: 'profil', ton: 1, + { name: 'Mein Profil', unter: 'Deine Ziele und Pläne', zeichen: 'profil', ton: 4, rollen: ['creator'], ziel: 'profil.html' }, - { name: 'Start-Check', unter: 'Erstanalyse, 16 Punkte', zeichen: 'startcheck', ton: 3, + { name: 'Start-Check', unter: 'Erstanalyse, 16 Punkte', zeichen: 'startcheck', ton: 14, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'startcheck.html' }, - { name: 'LIVE-Analyse', unter: 'Vorher, während, danach', zeichen: 'live', ton: 8, + { name: 'LIVE-Analyse', unter: 'Vorher, während, danach', zeichen: 'live', ton: 6, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'bereich.html?b=live' }, - { name: 'Content-Planung', unter: 'Idee bis Upload', zeichen: 'content', ton: 2, + { name: 'Content-Planung', unter: 'Idee bis Upload', zeichen: 'content', ton: 10, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'content.html' }, { name: 'Community', unter: 'Moderation und Konflikte', zeichen: 'community', ton: 5, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'bereich.html?b=community' }, - { name: 'Technik', unter: 'Setup, Fehler, Lösungen', zeichen: 'technik', ton: 4, + { name: 'Technik', unter: 'Setup, Fehler, Lösungen', zeichen: 'technik', ton: 11, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'bereich.html?b=technik' }, - { name: 'Schutz & Regeln', unter: 'Richtlinien und Vorfälle', zeichen: 'schutz', ton: 7, + { name: 'Schutz & Regeln', unter: 'Richtlinien und Vorfälle', zeichen: 'schutz', ton: 1, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'bereich.html?b=schutz' }, - { name: 'Reports & Review', unter: 'Woche und Entscheidung', zeichen: 'reports', ton: 6, + { name: 'Reports & Review', unter: 'Woche und Entscheidung', zeichen: 'reports', ton: 13, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'report.html' }, ], }, @@ -130,13 +135,13 @@ name: 'Team & System', unter: 'Was den Laden am Laufen hält', bereiche: [ - { name: 'Personen & Zugänge', unter: 'Rollen und Codes', zeichen: 'personen', ton: 4, + { name: 'Personen & Zugänge', unter: 'Rollen und Codes', zeichen: 'personen', ton: 7, rollen: ['admin', 'manager'], ziel: 'personen.html' }, - { name: 'Scout-Pipeline', unter: 'Entdeckt bis übergeben', zeichen: 'scouting', ton: 3, + { name: 'Scout-Pipeline', unter: 'Entdeckt bis übergeben', zeichen: 'scouting', ton: 12, rollen: ['admin', 'manager', 'scout'], ziel: 'scouting.html' }, - { name: 'Wissens-Bibliothek', unter: 'Anleitungen und PDFs', zeichen: 'wissen', ton: 1, + { name: 'Wissens-Bibliothek', unter: 'Anleitungen und PDFs', zeichen: 'wissen', ton: 2, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'wissen.html' }, - { name: 'Automationen', unter: 'Was von allein passiert', zeichen: 'automation', ton: 7, + { name: 'Automationen', unter: 'Was von allein passiert', zeichen: 'automation', ton: 17, rollen: ['admin', 'manager'], ziel: 'automation.html' }, ], }, @@ -230,6 +235,17 @@ const a = el('a', 'kachel__link'); a.href = b.ziel; + /* Das Wasserzeichen: dasselbe Zeichen noch einmal, riesig und + fast unsichtbar in der Ecke. Es macht jede Kachel auf den + ersten Blick unverwechselbar, ohne dass man es bewusst + wahrnimmt -- und es ist der Grund, warum siebzehn Kacheln + nicht mehr wie siebzehn Kästen aussehen. + + Steht als Erstes im Aufbau, damit es HINTER allem liegt. */ + const schatten = el('span', 'kachel__wasserzeichen'); + schatten.append(zeichenBauen(b.zeichen)); + a.append(schatten); + const zeichen = el('span', 'kachel__zeichen'); zeichen.append(zeichenBauen(b.zeichen)); a.append(zeichen); diff --git a/workspace/aufgaben.html b/workspace/aufgaben.html index 560d0dfc..0160ed90 100644 --- a/workspace/aufgaben.html +++ b/workspace/aufgaben.html @@ -7,9 +7,9 @@ - - - + + + @@ -134,8 +134,8 @@ - - - + + + diff --git a/workspace/automation.html b/workspace/automation.html index c4d54ae6..fbbeee41 100644 --- a/workspace/automation.html +++ b/workspace/automation.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -127,8 +127,8 @@ - - - + + + diff --git a/workspace/bereich.html b/workspace/bereich.html index 0a504152..bad86275 100644 --- a/workspace/bereich.html +++ b/workspace/bereich.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -98,8 +98,8 @@ - - - + + + diff --git a/workspace/calls.html b/workspace/calls.html index a474e149..a86ff9e1 100644 --- a/workspace/calls.html +++ b/workspace/calls.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -49,9 +49,9 @@ - - - - + + + + diff --git a/workspace/content.html b/workspace/content.html index b81e3446..290570a0 100644 --- a/workspace/content.html +++ b/workspace/content.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -153,8 +153,8 @@ - - - + + + diff --git a/workspace/dateien.html b/workspace/dateien.html index 4e2994e8..00a87d19 100644 --- a/workspace/dateien.html +++ b/workspace/dateien.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -88,8 +88,8 @@ - - - + + + diff --git a/workspace/index.html b/workspace/index.html index cf5c0cf5..34b56d57 100644 --- a/workspace/index.html +++ b/workspace/index.html @@ -25,7 +25,7 @@ type="image/webp" media="(max-width: 899px)" /> - + @@ -143,6 +143,6 @@

- + diff --git a/workspace/kalender.html b/workspace/kalender.html index f67cb803..602d4b14 100644 --- a/workspace/kalender.html +++ b/workspace/kalender.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -94,8 +94,8 @@ - - - + + + diff --git a/workspace/personen.html b/workspace/personen.html index a1cb1d1f..2a2e6396 100644 --- a/workspace/personen.html +++ b/workspace/personen.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -116,8 +116,8 @@ - - - + + + diff --git a/workspace/profil.html b/workspace/profil.html index 38873228..982fd953 100644 --- a/workspace/profil.html +++ b/workspace/profil.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -127,8 +127,8 @@ - - - + + + diff --git a/workspace/report.html b/workspace/report.html index e8a5c17f..474f89b5 100644 --- a/workspace/report.html +++ b/workspace/report.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -86,9 +86,9 @@ - - - - + + + + diff --git a/workspace/scouting.html b/workspace/scouting.html index a2970f50..6eeac639 100644 --- a/workspace/scouting.html +++ b/workspace/scouting.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -124,8 +124,8 @@ - - - + + + diff --git a/workspace/start.html b/workspace/start.html index c0c1afd8..06970507 100644 --- a/workspace/start.html +++ b/workspace/start.html @@ -7,8 +7,8 @@ - - + + @@ -68,8 +68,8 @@

- - - + + + diff --git a/workspace/startcheck.html b/workspace/startcheck.html index e05569c9..84db85f4 100644 --- a/workspace/startcheck.html +++ b/workspace/startcheck.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -65,9 +65,9 @@ - - - - + + + + diff --git a/workspace/uebersicht.html b/workspace/uebersicht.html index 019b737d..f1b3c963 100644 --- a/workspace/uebersicht.html +++ b/workspace/uebersicht.html @@ -7,9 +7,9 @@ - - - + + + @@ -52,7 +52,7 @@ - - + + diff --git a/workspace/wissen.html b/workspace/wissen.html index 8e3c37a5..419398d9 100644 --- a/workspace/wissen.html +++ b/workspace/wissen.html @@ -7,10 +7,10 @@ - - - - + + + + @@ -170,8 +170,8 @@ - - - + + +