Der Server konnte seit gestern rechnen -- und niemand konnte etwas
eintragen. Ein Rechenwerk ohne Oberflaeche ist kein Modul, sondern ein
Versprechen. Das ist jetzt eingeloest:
* leistung.html: Wochenkarten (Wert, Vergleich zur Vorwoche,
Verlaufslinie), Ziele als Fortschrittsbalken, die letzten 14 Tage
zum Eintragen -- auch die LEEREN, denn eine Luecke ist selbst die
Auskunft. Import aus dem TikTok-Export mit Vorschau VOR dem
Schreiben.
* Kachel "Zahlen" als erste der Gruppe "Rund um den Creator", eigenes
Zeichen (steigende Linie, kein zweites Balkendiagramm).
* Dashboard: jede Creator-Karte traegt jetzt Diamanten, LIVE-Tage und
Verweildauer. Bis heute zeigte sie ausschliesslich ARBEIT -- ein
Creator konnte null ueberfaellige Aufgaben haben und gleichzeitig
seit drei Wochen einbrechen, und die Karte sah tadellos aus.
* Die Fruehwarnung steht oben im Dashboard. Sechs benannte Signale im
Klartext mit Beleg, bewusst OHNE Punktzahl -- ein Wert wie
"Abwanderungsrisiko 73" klingt nach Wissenschaft und ist eine
Behauptung, der man nicht widersprechen kann.
* chat.html?mit=<person>: der Weg von der Warnung ins Gespraech. Gab
es vorher nicht; ein Hinweis ohne Weg dahin ist nur ein schlechtes
Gewissen.
GEFUNDEN VON DEN PRUEFUNGEN, nicht von der Theorie:
1. Die Verlaufslinie zeichnete fuer vier der sieben Groessen NICHTS.
Der Server liefert im Verlauf nur drei Reihen; fuer den Rest kam
undefined an. `=== null` faengt das nicht, Number(undefined) ist
NaN, und ein <polyline points="NaN,NaN"> ist im DOM vorhanden und
auf dem Bildschirm unsichtbar -- ohne Fehlermeldung. Die Pruefung
misst deshalb die PUNKTE, nicht die Anwesenheit des Elements.
2. Fuenf Schriftgroessen im CHAT lagen unter 11,5 px (.68/.7 rem) und
waren seit vorgestern drin. Die Grundlinie der Groessenpruefung
stand auf 43, gemessen wurden 48. Nicht die Grundlinie angehoben,
sondern die fuenf Stellen behoben: Eine Grundlinie, die mitwaechst,
ist keine mehr.
pruef-leistung-optik.mjs: 57 Pruefungen, zwei echte Browser, Gegenprobe
zu jeder Aussage -- auch dazu, dass die Vorschau vor dem Bestaetigen
wirklich noch nichts geschrieben hat und dass ein Creator seine Zahlen
zwar SIEHT, sie aber weder eintragen noch die Fruehwarnung ueber sich
lesen kann (auch nicht ueber eine von Hand gebaute Anfrage).
Co-Authored-By: Claude Opus 5 <[email protected]>
710 lines
33 KiB
JavaScript
710 lines
33 KiB
JavaScript
/* ===================================================================
|
||
Die Bereiche -- EINE Quelle für die ganze Anwendung.
|
||
|
||
Zeichen, Farbton, Rolle und Ziel jedes Bereichs standen bis zum
|
||
01.09.2026 nur in start.js. Seit jede Unterseite Zeichen und Farbe
|
||
ihrer Kachel trägt, brauchen sie auch die Kopfleisten -- und eine
|
||
zweite, abgeschriebene Liste wäre der sichere Weg, dass "Aufgaben"
|
||
irgendwann auf der Startseite gelb und auf der Aufgabenseite grün ist.
|
||
|
||
Deshalb liegt beides jetzt hier und wird von start.js UND kopf.js
|
||
benutzt. Wer eine Kachel ändert, ändert damit automatisch auch den
|
||
Kopf der zugehörigen Seite.
|
||
=================================================================== */
|
||
(() => {
|
||
'use strict';
|
||
|
||
/* ---------- Zeichen ------------------------------------------------------
|
||
|
||
Alle im selben Raster (24×24). Seit dem 03.09.2026 besteht jedes
|
||
Zeichen aus ZWEI Teilen:
|
||
|
||
fuellung eine gefüllte Grundform -- der Gegenstand selbst,
|
||
gedeckt hinterlegt
|
||
linien die scharfe Zeichnung darüber
|
||
|
||
Das ist der Unterschied zwischen einem Symbol und einem Piktogramm.
|
||
Eine reine Kontur ist neutral; sobald ein Teil FLÄCHE hat, bekommt
|
||
das Zeichen ein Vorn und ein Hinten, und das Auge erkennt es, ohne
|
||
es zu lesen. Gefüllt wird immer das, worum es geht: beim Kalender
|
||
der Kopf, beim Ordner der Korpus, bei einer Person der Kopf, beim
|
||
Regler die Griffe.
|
||
|
||
WARUM NICHT EINFACH DICKER: Ein früherer Versuch legte eine dicke,
|
||
weichgezeichnete Kopie der LINIE darunter. Das hat die feinen
|
||
Lücken zugeschmiert -- aus dem Kalender wurde ein leerer Kasten
|
||
(siehe start.css). Eine Fläche ist etwas anderes als ein
|
||
aufgeblasener Strich: Sie liegt INNERHALB der Kontur und lässt die
|
||
Zwischenräume unberührt.
|
||
|
||
Eigene Pfade statt einer Fremdbibliothek: siebzehn Zeichen sind
|
||
kleiner als jede Schriftart und kosten keine Lieferkette. */
|
||
|
||
/* ---------- Die Silhouetten -------------------------------------------
|
||
|
||
Der UMRISS jedes Gegenstands als geschlossene Form. Aus ihm entsteht
|
||
die Tiefe: Er wird dreimal übereinander gezeichnet, jedes Mal ein
|
||
Stück versetzt und dunkler -- unten die Grundfläche, darüber die
|
||
Seitenwand, oben die Deckfläche. Das ist dasselbe Verfahren, mit dem
|
||
man einen Körper von Hand zeichnet, und es ist der Grund, warum die
|
||
Zeichen jetzt eine Höhe haben statt nur einen Umriss.
|
||
|
||
Getrennt von den Linien gehalten: Die Linien sind die DETAILS auf der
|
||
Oberfläche (Querstriche, Haken, Wellen). Sie bekommen keine Tiefe --
|
||
ein aufgedruckter Strich steht nicht hervor. */
|
||
const KOERPER = {
|
||
dashboard: [
|
||
'M4 4.5h6.4v6.4H4z',
|
||
'M13.6 4.5h6.4v4.2h-6.4z',
|
||
'M13.6 11.6h6.4v7.9h-6.4z',
|
||
'M4 13.7h6.4v5.8H4z'
|
||
],
|
||
aufgaben: [
|
||
'M4.5 5h4v14h-4z',
|
||
'M10 5h4v9h-4z',
|
||
'M15.5 5h4v11.5h-4z'
|
||
],
|
||
kalender: [
|
||
'M3.5 7h17v12.5h-17z'
|
||
],
|
||
calls: [
|
||
'M3.5 7h11v10h-11z',
|
||
'M14.5 11l6-3.5v9l-6-3.5z'
|
||
],
|
||
dateien: [
|
||
'M3.5 6.5h5.5l2 2h9.5v11h-17z'
|
||
],
|
||
/* Chat (06.09.2026): eine Sprechblase mit Schweif nach links
|
||
unten. Bewusst OHNE die drei Punkte darin -- bei 20 Pixeln
|
||
werden die zu Matsch, und die Blase allein ist eindeutig. */
|
||
chat: [
|
||
'M4 5.5h16v11H9.5L5 20.5V16.5H4z'
|
||
],
|
||
steckbrief: [
|
||
'M3.5 5.5h17v13h-17z'
|
||
],
|
||
profil: [
|
||
'M12 7a3.2 3.2 0 1 0 0 6.4A3.2 3.2 0 0 0 12 7z',
|
||
'M5.5 20c.7-3.3 3.3-5.3 6.5-5.3s5.8 2 6.5 5.3z'
|
||
],
|
||
startcheck: [
|
||
'M6 4.5h12v15H6z'
|
||
],
|
||
live: [
|
||
'M12 10.2a1.8 1.8 0 1 0 0 3.6 1.8 1.8 0 0 0 0-3.6z'
|
||
],
|
||
content: [
|
||
'M3.5 6h17v13h-17z'
|
||
],
|
||
technik: [
|
||
'M9 5.9a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z',
|
||
'M15 10.4a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z',
|
||
'M7.5 14.9a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z'
|
||
],
|
||
community: [
|
||
'M9 8.6a2.7 2.7 0 1 0 0 5.4 2.7 2.7 0 0 0 0-5.4z',
|
||
'M3.5 19.5c.6-2.8 2.8-4.5 5.5-4.5s4.9 1.7 5.5 4.5z'
|
||
],
|
||
schutz: [
|
||
'M12 3.6 5.6 6.3v5.1c0 3.8 2.6 7.2 6.4 8.4 3.8-1.2 6.4-4.6 6.4-8.4V6.3z'
|
||
],
|
||
reports: [
|
||
'M6.6 9.5h1.8v7h-1.8z',
|
||
'M11.1 5.5h1.8v11h-1.8z',
|
||
'M15.6 11.5h1.8v5h-1.8z'
|
||
],
|
||
personen: [
|
||
'M14.4 6.2a4 4 0 1 0 0 8 4 4 0 0 0 0-8z'
|
||
],
|
||
scouting: [
|
||
'M3.5 5.5h17l-6.6 7.6v6.4l-3.8-2.1v-4.3z'
|
||
],
|
||
wissen: [
|
||
'M4 5h6.4c.9 0 1.6.7 1.6 1.6V19c0-.9-.7-1.6-1.6-1.6H4z',
|
||
'M20 5h-6.4c-.9 0-1.6.7-1.6 1.6V19c0-.9.7-1.6 1.6-1.6H20z'
|
||
],
|
||
automation: [
|
||
'M13.2 3.2 6 13.4h5.2l-.8 7.4 7.6-10.6h-5.2z'
|
||
],
|
||
/* Zahlen (06.09.2026): die Flaeche UNTER einem steigenden
|
||
Linienzug. Bewusst kein zweites Balkendiagramm -- "Reports &
|
||
Review" hat schon eins, und zwei Kacheln mit demselben Zeichen
|
||
sind schlimmer als eine ohne: Man klickt zweimal falsch, bevor
|
||
man merkt, dass es zwei verschiedene Sachen sind. Eine Linie
|
||
ist auch die richtige Aussage: Es geht hier nicht um einen
|
||
Bericht, sondern um einen VERLAUF. */
|
||
zahlen: [
|
||
'M4 16 9.5 11.5 13 14 20 6.5 20 19.5 4 19.5z'
|
||
]
|
||
};
|
||
|
||
const ZEICHEN = {
|
||
dashboard: {
|
||
/* Zwei der vier Felder gefüllt, über Eck -- das gibt dem Zeichen
|
||
einen Rhythmus. Alle vier zu füllen wäre ein Klotz. */
|
||
fuellung: ['M4 4.5h6.4v6.4H4z', 'M13.6 11.6h6.4v7.9h-6.4z'],
|
||
linien: ['M4 4.5h6.4v6.4H4z', 'M13.6 4.5h6.4v4.2h-6.4z',
|
||
'M13.6 11.6h6.4v7.9h-6.4z', 'M4 13.7h6.4v5.8H4z'],
|
||
},
|
||
aufgaben: {
|
||
/* Die mittlere Spalte -- "in Arbeit". Das Brett hat drei Spalten,
|
||
und die mittlere ist die, in der gerade etwas passiert. */
|
||
fuellung: ['M10 5h4v9h-4z'],
|
||
linien: ['M4.5 5h4v14h-4z', 'M10 5h4v9h-4z', 'M15.5 5h4v11.5h-4z'],
|
||
},
|
||
kalender: {
|
||
/* Der Kopf des Blattes. Genau der Streifen, an dem man einen
|
||
Kalender auch aus drei Metern erkennt. */
|
||
fuellung: ['M3.5 7h17v4.5h-17z'],
|
||
linien: ['M3.5 7h17v12.5h-17z', 'M3.5 11.5h17', 'M7.5 4v4.6', 'M16.5 4v4.6'],
|
||
},
|
||
calls: {
|
||
/* Das Objektiv. Der Kasten bleibt offen, sonst wird das Zeichen
|
||
schwer. */
|
||
fuellung: ['M14.5 11l6-3.5v9l-6-3.5z'],
|
||
linien: ['M3.5 7h11v10h-11z', 'M14.5 11l6-3.5v9l-6-3.5z'],
|
||
},
|
||
dateien: {
|
||
/* Der Korpus ohne die Lasche -- so bleibt die Stufe oben sichtbar,
|
||
die den Ordner ausmacht. */
|
||
fuellung: ['M3.5 10h17v9.5h-17z'],
|
||
linien: ['M3.5 6.5h5.5l2 2h9.5v11h-17z', 'M3.5 10h17'],
|
||
},
|
||
steckbrief: {
|
||
/* Kopf und Schultern der Person IN der Karte -- unterscheidbar vom
|
||
Profil-Zeichen (nur die Person), damit die beiden Kacheln nicht
|
||
gleich aussehen. */
|
||
fuellung: ['M8.5 11.2a1.9 1.9 0 1 0 0-3.8 1.9 1.9 0 0 0 0 3.8z'],
|
||
linien: ['M3.5 5.5h17v13h-17z', 'M8.5 11.2a1.9 1.9 0 1 0 0-3.8 1.9 1.9 0 0 0 0 3.8z',
|
||
'M5.6 16.2c0-1.7 1.3-3 2.9-3s2.9 1.3 2.9 3', 'M14.5 9.5h4', 'M14.5 13h4'],
|
||
},
|
||
profil: {
|
||
fuellung: ['M12 7a3.2 3.2 0 1 0 0 6.4A3.2 3.2 0 0 0 12 7z'],
|
||
linien: ['M12 7a3.2 3.2 0 1 0 0 6.4A3.2 3.2 0 0 0 12 7z',
|
||
'M5.5 20c.7-3.3 3.3-5.3 6.5-5.3s5.8 2 6.5 5.3'],
|
||
},
|
||
startcheck: {
|
||
/* Nur der Haken ist gefüllt -- er ist die Aussage des Zeichens.
|
||
Ein gefülltes Klemmbrett wäre ein Kasten. */
|
||
fuellung: ['M9.2 9.6l1.7 1.7 3.6-3.7 1 1-4.6 4.7-2.7-2.7z'],
|
||
linien: ['M6 4.5h12v15H6z', 'M9.2 9.6l1.7 1.7 3.6-3.7', 'M9.2 15.2h5.6'],
|
||
},
|
||
live: {
|
||
/* Der Sender in der Mitte. Die Wellen bleiben Linien -- gefüllte
|
||
Wellen sähen aus wie ein Auge. */
|
||
fuellung: ['M12 10.2a1.8 1.8 0 1 0 0 3.6 1.8 1.8 0 0 0 0-3.6z'],
|
||
linien: ['M12 10.2a1.8 1.8 0 1 0 0 3.6 1.8 1.8 0 0 0 0-3.6z',
|
||
'M8.2 8.2a5.4 5.4 0 0 0 0 7.6', 'M15.8 15.8a5.4 5.4 0 0 0 0-7.6',
|
||
'M5.4 5.4a9.4 9.4 0 0 0 0 13.2', 'M18.6 18.6a9.4 9.4 0 0 0 0-13.2'],
|
||
},
|
||
content: {
|
||
/* Die Klappe der Filmklappe. */
|
||
fuellung: ['M3.5 6h17v4h-17z'],
|
||
linien: ['M3.5 6h17v13h-17z', 'M3.5 10h17', 'M8 6l-1.4 4', 'M13 6l-1.4 4', 'M18 6l-1.4 4'],
|
||
},
|
||
technik: {
|
||
/* Die drei Griffe. Sie waren bis zum 03.09.2026 Bögen der Länge
|
||
null und wurden nie gezeichnet -- übrig blieben drei nackte
|
||
Striche, die aussahen wie ein Menü-Symbol. */
|
||
fuellung: ['M9 5.9a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z',
|
||
'M15 10.4a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z',
|
||
'M7.5 14.9a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z'],
|
||
linien: ['M4 7.5h16', 'M4 12h16', 'M4 16.5h16',
|
||
'M9 5.9a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z',
|
||
'M15 10.4a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z',
|
||
'M7.5 14.9a1.6 1.6 0 1 0 0 3.2 1.6 1.6 0 0 0 0-3.2z'],
|
||
},
|
||
community: {
|
||
/* Der vordere Kopf. Der hintere bleibt Kontur -- dadurch entsteht
|
||
die Tiefe, um die es bei zwei Personen geht. */
|
||
fuellung: ['M9 8.6a2.7 2.7 0 1 0 0 5.4 2.7 2.7 0 0 0 0-5.4z'],
|
||
linien: ['M9 8.6a2.7 2.7 0 1 0 0 5.4 2.7 2.7 0 0 0 0-5.4z',
|
||
'M3.5 19.5c.6-2.8 2.8-4.5 5.5-4.5s4.9 1.7 5.5 4.5',
|
||
'M16 8.8a2.4 2.4 0 1 1 1.6 4.3', 'M17 15.2c2 .5 3.3 2 3.7 4.3'],
|
||
},
|
||
schutz: {
|
||
fuellung: ['M12 3.6 5.6 6.3v5.1c0 3.8 2.6 7.2 6.4 8.4 3.8-1.2 6.4-4.6 6.4-8.4V6.3z'],
|
||
linien: ['M12 3.6 5.6 6.3v5.1c0 3.8 2.6 7.2 6.4 8.4 3.8-1.2 6.4-4.6 6.4-8.4V6.3z',
|
||
'M9.4 11.8l1.9 1.9 3.4-3.6'],
|
||
},
|
||
reports: {
|
||
/* Aus drei Strichen werden drei Säulen -- ein Balkendiagramm hat
|
||
Balken, keine Striche. */
|
||
fuellung: ['M6.6 9.5h1.8v7h-1.8z', 'M11.1 5.5h1.8v11h-1.8z', 'M15.6 11.5h1.8v5h-1.8z'],
|
||
linien: ['M4 19.5h16', 'M6.6 9.5h1.8v7h-1.8z', 'M11.1 5.5h1.8v11h-1.8z',
|
||
'M15.6 11.5h1.8v5h-1.8z'],
|
||
},
|
||
personen: {
|
||
/* Der Bart des Schlüssels bleibt Linie, der Kopf wird Fläche. */
|
||
fuellung: ['M14.4 6.2a4 4 0 1 0 0 8 4 4 0 0 0 0-8z'],
|
||
linien: ['M14.4 6.2a4 4 0 1 0 0 8 4 4 0 0 0 0-8z', 'M11.6 12.2 4 19.8',
|
||
'M6.4 17.4l2 2', 'M8.6 15.2l2 2'],
|
||
},
|
||
scouting: {
|
||
/* Der Trichter, aber nur der obere Teil -- der Stiel bleibt offen,
|
||
sonst kippt das Zeichen optisch nach unten. */
|
||
fuellung: ['M3.5 5.5h17l-6.6 7.6h-3.8z'],
|
||
linien: ['M3.5 5.5h17l-6.6 7.6v6.4l-3.8-2.1v-4.3z'],
|
||
},
|
||
wissen: {
|
||
/* Die linke Seite gefüllt: ein aufgeschlagenes Buch hat eine
|
||
Seite im Licht und eine im Schatten. */
|
||
fuellung: ['M4 5h6.4c.9 0 1.6.7 1.6 1.6V19c0-.9-.7-1.6-1.6-1.6H4z'],
|
||
linien: ['M4 5h6.4c.9 0 1.6.7 1.6 1.6V19c0-.9-.7-1.6-1.6-1.6H4z',
|
||
'M20 5h-6.4c-.9 0-1.6.7-1.6 1.6V19c0-.9.7-1.6 1.6-1.6H20z'],
|
||
},
|
||
automation: {
|
||
fuellung: ['M13.2 3.2 6 13.4h5.2l-.8 7.4 7.6-10.6h-5.2z'],
|
||
linien: ['M13.2 3.2 6 13.4h5.2l-.8 7.4 7.6-10.6h-5.2z'],
|
||
},
|
||
zahlen: {
|
||
fuellung: ['M4 16 9.5 11.5 13 14 20 6.5 20 19.5 4 19.5z'],
|
||
/* Der Linienzug selbst, die Grundlinie darunter und ein Punkt am
|
||
oberen Ende -- der letzte Messwert, das Jetzt. Genau dieselbe
|
||
Bildsprache wie die kleine Linie in jeder Zahlkarte: Wer die
|
||
Kachel gesehen hat, erkennt die Karten wieder. */
|
||
linien: ['M4 16 9.5 11.5 13 14 20 6.5', 'M3.6 19.8h16.8',
|
||
'M20 5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z'],
|
||
},
|
||
};
|
||
|
||
/* ---------- Die Bereiche -------------------------------------------------
|
||
|
||
`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..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: 3,
|
||
gross: true, rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'uebersicht.html', szene: 'showbuehne' },
|
||
{ name: 'Aufgaben', unter: 'Offen, in Arbeit, Review', zeichen: 'aufgaben', ton: 11,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'aufgaben.html', szene: 'garage' },
|
||
{ name: 'Kalender', unter: 'Termine und Calls', zeichen: 'kalender', ton: 16,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'kalender.html', szene: 'skyline' },
|
||
{ name: 'Calls & Protokolle', unter: 'Gespräche mit To-dos', zeichen: 'calls', ton: 9,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'calls.html', szene: 'lounge' },
|
||
/* CHAT (06.09.2026). Steht neben "Calls & Protokolle", weil
|
||
beides Gespraech ist -- das eine geplant und protokolliert,
|
||
das andere zwischendurch. Ton 14 (Gruen), weil die taegliche
|
||
Gruppe sonst 3, 11, 16, 9 und 2 traegt und sich der Chat
|
||
davon abheben soll. */
|
||
{ name: 'Chat', unter: 'Nachrichten mit deinem Team', zeichen: 'chat', ton: 14,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'chat.html', szene: 'lounge' },
|
||
{ name: 'Dateien', unter: 'Ablage und Freigaben', zeichen: 'dateien', ton: 2,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'dateien.html', szene: 'arena' },
|
||
],
|
||
},
|
||
{
|
||
name: 'Rund um den Creator',
|
||
unter: 'Die Betreuungsakte – Stand, Zahlen, Verlauf',
|
||
bereiche: [
|
||
/* ZWEI VERSCHIEDENE DINGE, zwei Kacheln (01.09.2026).
|
||
|
||
Vorher war beides dieselbe Seite, und das war verwirrend:
|
||
Oben stand "Profil: SpongBobSchwammKopf" und mitten darin
|
||
"MEIN PROFIL - Dogfather". Zwei Personen auf einem Bildschirm,
|
||
ohne dass klar war, welche gerade gemeint ist.
|
||
|
||
Es sind auch wirklich zwei Sachen:
|
||
MEIN STECKBRIEF gehoert MIR -- Bild, ein Satz ueber mich,
|
||
meine Kanaele. Fuehre ich selbst, hat
|
||
jeder (auch Scouts und Manager).
|
||
CREATOR-PROFILE die BETREUUNGSAKTE eines Creators --
|
||
Ziele, 90-Tage-Plan, interne Notizen.
|
||
Fuehren die Betreuer.
|
||
|
||
Ein Creator sieht nur seine eigene Akte (dort steht auch sein
|
||
Steckbrief mit drin, er hat ja nur eine Seite). Alle anderen
|
||
bekommen beide Kacheln getrennt. */
|
||
/* ZAHLEN STEHT VORN (06.09.2026).
|
||
Der Workspace organisierte bis dahin ARBEIT hervorragend und
|
||
wusste über das GESCHÄFT nichts -- keine Diamanten, keine
|
||
LIVE-Tage, keine Verweildauer. Damit hing die ganze Gruppe
|
||
hier in der Luft: Der Start-Check bewertet, ohne zu messen,
|
||
der Report fragt "was hat funktioniert?" ohne Beleg, und das
|
||
90-Tage-Ziel war ein Satz statt eines Fortschritts. Deshalb
|
||
die erste Kachel der Gruppe, nicht die letzte.
|
||
|
||
Ton 4 (Violett) ist von Hand gewählt und nicht gerechnet: Er
|
||
liegt weit von seinem Nachbarn 15 (Blaugrün) und von 8
|
||
(Orangerot) darunter. Wer diese Gruppe umsortiert, lässt
|
||
tools/kachel-farben.mjs neu laufen -- die Nachbarschaften
|
||
haben sich durch diese Kachel geändert. */
|
||
{ name: 'Zahlen', unter: 'Diamanten, LIVE-Tage, Verweildauer', zeichen: 'zahlen', ton: 4,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'leistung.html', szene: 'arena' },
|
||
{ name: 'Mein Steckbrief', unter: 'Dein Bild und deine Kanäle', zeichen: 'steckbrief', ton: 15,
|
||
rollen: ['admin', 'manager', 'scout'], ziel: 'steckbrief.html', szene: 'halle' },
|
||
{ name: 'Creator-Profile', unter: 'Ziele und 90-Tage-Plan', zeichen: 'profil', ton: 8,
|
||
rollen: ['admin', 'manager', 'scout'], ziel: 'profil.html', szene: 'halle' },
|
||
{ name: 'Mein Profil', unter: 'Dein Steckbrief, Ziele und Pläne', zeichen: 'profil', ton: 8,
|
||
rollen: ['creator'], ziel: 'profil.html', szene: 'halle' },
|
||
{ name: 'Start-Check', unter: 'Erstanalyse, 16 Punkte', zeichen: 'startcheck', ton: 18,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'startcheck.html', szene: 'wald' },
|
||
{ name: 'LIVE-Analyse', unter: 'Vorher, während, danach', zeichen: 'live', ton: 7,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'bereich.html?b=live', szene: 'portal' },
|
||
{ name: 'Content-Ideen', unter: 'Idee bis Upload', zeichen: 'content', ton: 13,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'content.html', szene: 'portal' },
|
||
{ name: 'Community', unter: 'Moderation und Konflikte', zeichen: 'community', ton: 6,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'bereich.html?b=community', szene: 'lounge' },
|
||
{ name: 'Technik', unter: 'Setup, Fehler, Lösungen', zeichen: 'technik', ton: 12,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'bereich.html?b=technik', szene: 'garage' },
|
||
{ name: 'Schutz & Regeln', unter: 'Richtlinien und Vorfälle', zeichen: 'schutz', ton: 1,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'bereich.html?b=schutz', szene: 'halle' },
|
||
{ name: 'Reports & Review', unter: 'Woche und Entscheidung', zeichen: 'reports', ton: 14,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'report.html', szene: 'showbuehne' },
|
||
],
|
||
},
|
||
{
|
||
name: 'Team & System',
|
||
unter: 'Was den Laden am Laufen hält',
|
||
/* Für einen Creator bleibt von dieser Gruppe genau eine Kachel übrig:
|
||
die Wissens-Bibliothek. "Team & System" wäre dann eine Überschrift,
|
||
die etwas verspricht, was gar nicht da ist -- und die klingt, als
|
||
gäbe es dahinter noch einen Bereich, den er nicht sehen darf. Er
|
||
liest stattdessen "Wissen", und das beschreibt genau, was dort
|
||
steht. Der Untertitel wechselt mit. */
|
||
nameCreator: 'Wissen',
|
||
unterCreator: 'Nachschlagen, wenn du etwas brauchst',
|
||
bereiche: [
|
||
/* NUR DogFather (02.09.2026, Wunsch: "die manager sollen diese
|
||
kategorien garnicht sehen").
|
||
|
||
Es war ohnehin ein Widerspruch: In der Rollenauswahl steht seit
|
||
jeher "Manager -- dieselben Rechte wie DogFather, AUSSER der
|
||
Personenverwaltung". Die Kachel stand trotzdem bei ihm, und die
|
||
Seite liess ihn auch hinein. Eine Beschreibung, die etwas
|
||
anderes sagt als die Software, ist schlimmer als beides
|
||
einzeln: Man weiss danach nicht mehr, welcher von beiden man
|
||
glauben soll. */
|
||
{ name: 'Personen & Zugänge', unter: 'Rollen und Codes', zeichen: 'personen', ton: 10,
|
||
rollen: ['admin'], ziel: 'personen.html', szene: 'halle' },
|
||
{ name: 'Scout-Pipeline', unter: 'Entdeckt bis übergeben', zeichen: 'scouting', ton: 17,
|
||
rollen: ['admin', 'manager', 'scout'], ziel: 'scouting.html', szene: 'wald' },
|
||
{ name: 'Wissens-Bibliothek', unter: 'Anleitungen und PDFs', zeichen: 'wissen', ton: 4,
|
||
rollen: ['admin', 'manager', 'creator', 'scout'], ziel: 'wissen.html', szene: 'arena' },
|
||
/* Ebenfalls nur DogFather (02.09.2026). Was von allein passiert,
|
||
legt fest, was ALLEN anderen automatisch zugeschoben wird --
|
||
das gehört in dieselbe Hand wie die Rollenvergabe. */
|
||
{ name: 'Automationen', unter: 'Was von allein passiert', zeichen: 'automation', ton: 5,
|
||
rollen: ['admin'], ziel: 'automation.html', szene: 'garage' },
|
||
],
|
||
},
|
||
];
|
||
|
||
/* Ein Bereich anhand des Dateinamens finden. Die Bereichsseite
|
||
(bereich.html?b=live) trägt ihren Bereich in der Adresse -- deshalb
|
||
wird auch die Abfrage verglichen, nicht nur der Dateiname. */
|
||
function zuSeite(pfad, abfrage) {
|
||
const datei = String(pfad).split('/').pop() || 'start.html';
|
||
const gesucht = datei + (abfrage || '');
|
||
let treffer = null;
|
||
for (const g of GRUPPEN) {
|
||
for (const b of g.bereiche) {
|
||
if (b.ziel === gesucht) return b;
|
||
/* Ohne Abfrage: der erste Bereich mit passendem Dateinamen.
|
||
"Mein Profil" und "Creator-Profile" zeigen auf dieselbe Datei
|
||
und teilen sich Zeichen und Ton -- da ist beides richtig. */
|
||
if (!treffer && b.ziel.split('?')[0] === datei) treffer = b;
|
||
}
|
||
}
|
||
return treffer;
|
||
}
|
||
|
||
/* Ein SVG mit dem Zeichen eines Bereichs. Klasse frei wählbar, damit
|
||
Kachel, Hinweiszeile und Seitenkopf dieselbe Form in
|
||
unterschiedlicher Größe benutzen können. */
|
||
/* ---------- Die Zeichen (überarbeitet 03.09.2026) ------------------------
|
||
|
||
Wunsch: "ich will dass du die symbole perfektionnierst, ich will
|
||
wirklich dass jeder sich denkt woooow."
|
||
|
||
Vorher war jedes Zeichen eine flache Linie in einer Farbe. Sauber,
|
||
aber leblos -- siebzehn gleich starke Striche nebeneinander.
|
||
|
||
Jetzt besteht jedes Zeichen aus ZWEI übereinanderliegenden Lagen
|
||
derselben Form:
|
||
|
||
SCHEIN dick, weich, halbdurchsichtig -- das Licht, das die
|
||
Linie wirft. Sie liegt darunter und wird nie gelesen,
|
||
aber ohne sie sitzt das Zeichen flach auf der Fläche
|
||
statt darüber zu schweben.
|
||
LINIE die eigentliche Zeichnung, mit einem VERLAUF von oben
|
||
hell nach unten gedämpft.
|
||
|
||
Der Verlauf ist der eigentliche Kniff. Er ist EINMAL im Dokument
|
||
definiert und benutzt `currentColor` -- dadurch passt er sich jeder
|
||
der siebzehn Kachelfarben von selbst an, ohne siebzehn Verläufe.
|
||
Eine Lichtquelle oben, wie in der echten Welt: Genau das lässt eine
|
||
Linie geprägt statt gemalt wirken.
|
||
|
||
Kein zusätzliches Bild, keine Schriftart, kein Nachladen -- alles
|
||
entsteht aus den Pfaden, die ohnehin schon da waren. */
|
||
|
||
const NS = 'http://www.w3.org/2000/svg';
|
||
const VERLAUF_ID = 'zeichen-verlaeufe';
|
||
|
||
/* ---------- Die drei Verläufe ------------------------------------------
|
||
|
||
Ein Zeichen wird aus drei Lagen aufgebaut, und jede hat ihren
|
||
eigenen Verlauf. Alle drei stehen EINMAL im Dokument und arbeiten
|
||
mit currentColor -- dadurch nehmen sie den Ton jeder der siebzehn
|
||
Kacheln an, ohne dass es einundfünfzig Verläufe braucht.
|
||
|
||
flaeche die gefüllte Grundform: oben kräftig, unten fast weg.
|
||
Das ist der Körper des Gegenstands.
|
||
linie die Kontur: oben fast WEISS, unten im Farbton. Genau so
|
||
sieht Metall aus, auf das Licht von oben fällt -- und
|
||
genau das lässt ein Zeichen plastisch wirken statt
|
||
gezeichnet.
|
||
glanz ein schmaler heller Streifen quer über die obere Hälfte.
|
||
Die Spiegelung. Sie ist der Unterschied zwischen "gut
|
||
gemacht" und "das will ich anfassen".
|
||
|
||
ALLE in Benutzerkoordinaten (userSpaceOnUse) über die festen 24
|
||
Einheiten des Rasters. In Objektkoordinaten -- der Vorgabe -- würde
|
||
der Verlauf auf den Umriss JEDES einzelnen Pfades gerechnet, und
|
||
eine waagerechte Linie hat die Höhe null: Der Verlauf wäre entartet
|
||
und der Browser zeichnete den Pfad gar nicht. Genau daran sind am
|
||
03.09.2026 die Querlinie im Kalender, die Regler in Technik und die
|
||
Grundlinie der Berichte verschwunden. */
|
||
function verlaufSicherstellen() {
|
||
if (document.getElementById(VERLAUF_ID)) return;
|
||
const svg = document.createElementNS(NS, 'svg');
|
||
svg.setAttribute('id', VERLAUF_ID);
|
||
svg.setAttribute('aria-hidden', 'true');
|
||
svg.setAttribute('width', '0');
|
||
svg.setAttribute('height', '0');
|
||
svg.style.position = 'absolute';
|
||
const defs = document.createElementNS(NS, 'defs');
|
||
|
||
const bauen = (id, stops, x2 = '0', y1 = '2', y2 = '22') => {
|
||
const lg = document.createElementNS(NS, 'linearGradient');
|
||
lg.setAttribute('id', id);
|
||
lg.setAttribute('gradientUnits', 'userSpaceOnUse');
|
||
lg.setAttribute('x1', '0'); lg.setAttribute('y1', y1);
|
||
lg.setAttribute('x2', x2); lg.setAttribute('y2', y2);
|
||
for (const [pos, farbe, deck] of stops) {
|
||
const st = document.createElementNS(NS, 'stop');
|
||
st.setAttribute('offset', pos);
|
||
st.setAttribute('stop-color', farbe);
|
||
st.setAttribute('stop-opacity', deck);
|
||
lg.append(st);
|
||
}
|
||
defs.append(lg);
|
||
};
|
||
|
||
/* Die Deckfläche: oben fast weiss, unten im Farbton. Das ist die
|
||
Seite, auf die das Licht fällt. */
|
||
bauen('zeichen-deck', [
|
||
['0', '#ffffff', '0.92'],
|
||
['0.4', 'currentColor', '0.95'],
|
||
['1', 'currentColor', '0.72'],
|
||
]);
|
||
/* Die Seitenwand: derselbe Ton, deutlich dunkler -- eine Wand, die
|
||
vom Licht abgewandt ist. */
|
||
bauen('zeichen-wand', [
|
||
['0', 'currentColor', '0.5'],
|
||
['1', 'currentColor', '0.28'],
|
||
]);
|
||
|
||
/* Der Körper: oben satt, unten fast durchsichtig. */
|
||
bauen('zeichen-flaeche', [
|
||
['0', 'currentColor', '0.68'],
|
||
['0.45', 'currentColor', '0.38'],
|
||
['1', 'currentColor', '0.12'],
|
||
]);
|
||
/* Der Eigenschatten: eine zweite Fuellung, die von unten dunkel
|
||
hereinkriecht. Ein Koerper ist unten dunkler als oben -- ohne das
|
||
bleibt jede Flaeche eine Farbflaeche. */
|
||
bauen('zeichen-schatten', [
|
||
['0', '#000000', '0'],
|
||
['0.55', '#000000', '0'],
|
||
['1', '#000000', '0.45'],
|
||
]);
|
||
|
||
/* Die Kontur: Licht von oben. Oben fast weiss, unten im Farbton --
|
||
das ist der Trick, der die Zeichen aus der Fläche hebt. */
|
||
/* Die Kontur bekommt ZWEI Lichtquellen -- so wie ein echter
|
||
Gegenstand auf einem Tisch:
|
||
|
||
oben das Hauptlicht, fast weiss
|
||
Mitte der Eigenton des Gegenstands
|
||
unten STREULICHT, das vom Untergrund zurueckgeworfen wird
|
||
|
||
Der letzte Stopp ist der Unterschied zwischen "Zeichnung" und
|
||
"Ding". Ohne ihn laeuft jede Form nach unten ins Dunkle aus und
|
||
sieht aus wie gemalt; mit ihm bekommt sie unten eine Kante, und
|
||
das Auge liest sie als Koerper im Raum. */
|
||
bauen('zeichen-linie', [
|
||
['0', '#ffffff', '0.98'],
|
||
['0.38', '#ffffff', '0.78'],
|
||
['0.78', 'currentColor', '0.95'],
|
||
['1', '#ffffff', '0.42'],
|
||
]);
|
||
|
||
/* Die Spiegelung, diagonal von links oben nach rechts unten. */
|
||
bauen('zeichen-glanz', [
|
||
['0', '#ffffff', '0.55'],
|
||
['0.45', '#ffffff', '0.12'],
|
||
['0.7', '#ffffff', '0'],
|
||
], '18', '0', '20');
|
||
|
||
svg.append(defs);
|
||
document.body.append(svg);
|
||
}
|
||
|
||
function zeichenBauen(name, klasse = 'kachel__svg') {
|
||
verlaufSicherstellen();
|
||
const svg = document.createElementNS(NS, 'svg');
|
||
svg.setAttribute('viewBox', '0 0 24 24');
|
||
svg.setAttribute('aria-hidden', 'true');
|
||
svg.setAttribute('class', klasse);
|
||
|
||
/* Erst die Fläche, dann die Linie -- in dieser Reihenfolge liegt
|
||
die Zeichnung oben. Ein Zeichen ohne Füllung (ältere Einträge,
|
||
die noch ein reines Feld sind) bekommt einfach keine. */
|
||
const eintrag = ZEICHEN[name] || {};
|
||
const umriss = KOERPER[name] || eintrag.fuellung || [];
|
||
const linien = Array.isArray(eintrag) ? eintrag : (eintrag.linien || []);
|
||
|
||
/* ---- Die Tiefe ----------------------------------------------------
|
||
|
||
Dieselbe Silhouette, dreimal, jedes Mal um einen halben
|
||
Rasterpunkt nach rechts unten versetzt. Von hinten nach vorn wird
|
||
sie heller. Das Auge liest die drei versetzten Kanten als EINE
|
||
schräge Seitenwand -- genau so, wie man einen Quader zeichnet.
|
||
|
||
Drei Lagen sind gemessen: bei zwei wirkt es wie ein
|
||
Druckfehler, ab fünf wie ein Schlagschatten. */
|
||
const tiefen = [
|
||
['zeichen__tiefe3', 'translate(1.5 1.5)'],
|
||
['zeichen__tiefe2', 'translate(1 1)'],
|
||
['zeichen__tiefe1', 'translate(0.5 0.5)'],
|
||
];
|
||
for (const [klasse, versatz] of tiefen) {
|
||
if (!umriss.length) break;
|
||
const g = document.createElementNS(NS, 'g');
|
||
g.setAttribute('class', klasse);
|
||
g.setAttribute('transform', versatz);
|
||
for (const d of umriss) {
|
||
const pfad = document.createElementNS(NS, 'path');
|
||
pfad.setAttribute('d', d);
|
||
g.append(pfad);
|
||
}
|
||
svg.append(g);
|
||
}
|
||
|
||
/* ---- Die Deckfläche und was darauf liegt --------------------------- */
|
||
const lagen = [
|
||
['zeichen__deck', umriss], // die Oberseite, hell
|
||
['zeichen__glanz', umriss], // die Spiegelung darauf
|
||
/* Die Details ZWEIMAL: erst ein dunkler Saum, dann die helle
|
||
Linie darauf.
|
||
|
||
Der Grund ist, dass dieselbe Linie über ZWEI Untergründen
|
||
liegt. Ein Querstrich im Kalender liegt auf der hellen
|
||
Deckfläche, die Wellen der LIVE-Analyse dagegen frei auf der
|
||
dunklen Plakette. Eine dunkle Linie verschwindet dort, eine
|
||
helle auf dem Deck -- was immer man wählt, die Hälfte ist weg.
|
||
|
||
Dunkler Saum plus helle Linie löst beides auf einmal: Auf dem
|
||
hellen Deck sieht man den Saum und liest eine eingravierte
|
||
Rille, auf der dunklen Plakette verschwindet er und die helle
|
||
Linie trägt. Ein Zeichen, zwei Untergründe, eine Lösung. */
|
||
['zeichen__saum', linien],
|
||
['zeichen__linie', linien],
|
||
];
|
||
for (const [klasse, pfade] of lagen) {
|
||
if (!pfade.length) continue;
|
||
const g = document.createElementNS(NS, 'g');
|
||
g.setAttribute('class', klasse);
|
||
for (const d of pfade) {
|
||
const pfad = document.createElementNS(NS, 'path');
|
||
pfad.setAttribute('d', d);
|
||
g.append(pfad);
|
||
}
|
||
svg.append(g);
|
||
}
|
||
return svg;
|
||
}
|
||
|
||
/* ---------- Das Merkzeichen ----------------------------------------------
|
||
|
||
Wunsch vom 01.09.2026: "wenn die Ansprechpartner was markieren, sollen
|
||
die da so ein Zeichen/Symbol haben, so dass die sehen, da ist was --
|
||
und es soll auch oben in der Kachel angezeigt werden."
|
||
|
||
Es ist bewusst das EINZIGE Zeichen der ganzen Anwendung, das eine
|
||
eigene Form hat statt der 24×24-Linienzeichen oben: eine Raute mit
|
||
Ausrufestrich. Der Grund ist nicht Geschmack, sondern Erkennbarkeit --
|
||
alle anderen Zeichen sind Rechtecke und Kreise; eine Raute ist die
|
||
einzige Form auf dem Bildschirm, die spitz nach oben zeigt, und
|
||
genau deshalb findet das Auge sie zwischen zwanzig Kacheln sofort.
|
||
|
||
Und es ist immer DIESELBE Farbe (Bernstein), egal auf welcher Kachel
|
||
es sitzt. Ein Zeichen, das seine Farbe wechselt, muss gelesen werden;
|
||
eines, das immer gleich aussieht, wird erkannt. Rot wäre falsch --
|
||
"verbessern" ist kein Fehler, sondern ein Auftrag.
|
||
|
||
anzahl > 1 schreibt die Zahl daneben, sonst steht nur das Zeichen.
|
||
Der Satz für Vorleseprogramme wird immer gesetzt: Ein Symbol ohne
|
||
Text ist für sie nicht vorhanden. */
|
||
function merkzeichenBauen(anzahl = 0, klasse = 'merk') {
|
||
const s = document.createElement('span');
|
||
s.className = klasse;
|
||
s.setAttribute('role', 'img');
|
||
s.setAttribute('aria-label', anzahl > 0
|
||
? `${anzahl} ${anzahl === 1 ? 'Punkt ist' : 'Punkte sind'} zum Verbessern markiert`
|
||
: 'Zum Verbessern markiert');
|
||
|
||
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||
svg.setAttribute('viewBox', '0 0 24 24');
|
||
svg.setAttribute('aria-hidden', 'true');
|
||
svg.setAttribute('class', klasse + '__svg');
|
||
/* Drei Pfade: die gefüllte Raute, der Strich, der Punkt. Getrennt,
|
||
damit die Fläche eine andere Deckkraft bekommen kann als die
|
||
Linie -- eine durchgehend volle Raute wäre auf dunklem Grund ein
|
||
Klecks. */
|
||
const teile = [
|
||
['M12 1.9 22.1 12 12 22.1 1.9 12z', 'flaeche'],
|
||
['M12 7.5v5.6', 'strich'],
|
||
['M12 16.9h.01', 'punkt'],
|
||
];
|
||
for (const [d, art] of teile) {
|
||
const p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||
p.setAttribute('d', d);
|
||
p.setAttribute('class', `${klasse}__${art}`);
|
||
svg.append(p);
|
||
}
|
||
s.append(svg);
|
||
if (anzahl > 1) {
|
||
const n = document.createElement('span');
|
||
n.className = klasse + '__n';
|
||
n.textContent = String(anzahl);
|
||
n.setAttribute('aria-hidden', 'true');
|
||
s.append(n);
|
||
}
|
||
return s;
|
||
}
|
||
|
||
window.Bereiche = { ZEICHEN, GRUPPEN, zuSeite, zeichenBauen, merkzeichenBauen };
|
||
})();
|