Auf der Startseite gab es einen Lichtfleck unter dem Zeiger. Jetzt auf
JEDER Karte im ganzen Workspace -- und mit zwei Schichten statt einer:
der FLECK ein weicher Schein unter dem Zeiger, in der Farbe des
Bereichs (--ton). Eine Aufgabenkarte leuchtet orange, eine
Kalenderkarte tuerkis.
der RAND eine helle Stelle, die auf der KANTE mitwandert.
Der Rand ist der Teil, der den Unterschied macht. Er entsteht aus einem
Farbverlauf, von dem eine Maske nur den ein Pixel breiten Saum stehen
laesst: zwei Ebenen, eine ueber die Innenflaeche, eine ueber den ganzen
Kasten, und mask-composite: exclude laesst genau die Differenz uebrig --
den Rahmen. Dadurch leuchtet wirklich die Kante an der Stelle, an der
der Zeiger steht, statt eines Rechtecks, das so tut als ob.
Beides steckt in einem eingefuegten <span class="licht">. Ein eigenes
Element statt ::before/::after am Kasten selbst, weil die bei fast
allen Karten schon belegt sind (Akzentstreifen, Wasserzeichen) -- ein
Pseudo-Element doppelt zu benutzen geht nicht, und der Fehler faellt
erst auf, wenn eines von beiden verschwindet.
Kosten: EIN Zuhoerer fuer das ganze Dokument, gedrosselt auf einen
Bildaufbau, passiv angemeldet. Das Licht-Element wird beim ersten
Ueberfahren eingesetzt, nicht beim Laden -- Karten entstehen laufend
neu, wenn Listen sich aktualisieren. Ohne feinen Zeiger (Handy) und bei
"weniger Bewegung" laeuft gar nichts und es wird auch nichts eingefuegt.
pointerout feuert auch beim Wechsel zwischen Kindern INNERHALB einer
Karte. Ohne die Pruefung auf relatedTarget haette das Licht bei jeder
Bewegung ueber ein Wort hinweg geflackert.
DIE ALTE FASSUNG IN start.js IST WEG. Sie stehen zu lassen haette zwei
Zuhoerer auf denselben Bewegungen bedeutet -- doppelte Arbeit bei jedem
Zeigerzucken, und der Fehler waere erst aufgefallen, wenn jemand die
eine geaendert haette und sich nichts tat.
GEPRUEFT AN ECHTEN BILDPUNKTEN, nicht am Quelltext: Der Zeiger wird in
die Mitte einer Kachel gesetzt, dann wird die Helligkeit der Kante
direkt darueber gegen dieselbe Kante an der fernen Ecke gemessen.
Ergebnis 50 gegen 17. Geht die Maske jemals verloren, waere die ganze
Karte eingefaerbt und der Text unlesbar -- das faellt damit sofort auf.
Co-Authored-By: Claude Opus 5 <[email protected]>
1559 lines
64 KiB
CSS
1559 lines
64 KiB
CSS
/* ===================================================================
|
|
Startseite nach dem Anmelden. Baut auf den Farben und Bausteinen von
|
|
gate.css auf, damit beides wie eine Anwendung wirkt und nicht wie zwei
|
|
verschiedene Seiten.
|
|
=================================================================== */
|
|
|
|
/* Grundschrift und Grundfarbe stehen in gate.css auf `body.gate` und
|
|
greifen hier deshalb NICHT. Ohne diese Wiederholung fällt die Seite auf
|
|
die Browservorgaben zurück: schwarze Serifenschrift auf dunklem Grund,
|
|
praktisch unlesbar. */
|
|
body.start {
|
|
display: block;
|
|
min-height: 100svh;
|
|
margin: 0;
|
|
padding: 0;
|
|
color: var(--text);
|
|
font-family: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
|
|
font-size: 16px;
|
|
line-height: 1.55;
|
|
letter-spacing: .01em;
|
|
background:
|
|
radial-gradient(120% 80% at 12% -10%, rgba(63, 189, 245, .10), transparent 58%),
|
|
radial-gradient(100% 70% at 92% 8%, rgba(138, 118, 255, .10), transparent 60%),
|
|
var(--tinte);
|
|
}
|
|
|
|
/* ---------- Die Bühne ----------------------------------------------------
|
|
|
|
HasiDog und DogFather im Studio -- das echte Marken-Bild, nicht
|
|
irgendein Husky aus dem alten Bilderordner. Über die ganze Fläche und
|
|
FEST an der Scheibe: Es scrollt nicht mit, sondern steht da wie ein
|
|
Bühnenbild, vor dem gearbeitet wird.
|
|
|
|
Warum genau dieses von den fünf: Die beiden stehen weit AUSSEN, die
|
|
Mitte ist dunkel -- und dort steht der Inhalt. Ein Bild mit Figuren in
|
|
der Mitte wäre hinter dem Text gelandet.
|
|
|
|
Aufbereitet in tools/buehne-bauen.mjs: abgedunkelt, Mitte zusätzlich
|
|
verdunkelt, weiche Kante oben. 1,9 MB PNG -> 28 KB WebP.
|
|
|
|
138 % breit und nach unten ausgerichtet: Bei 100 % ständen die beiden
|
|
bei 20 % und 78 % der Breite -- also mitten unter der Textspalte.
|
|
Vergrößert man das Bild über die Scheibe hinaus, wandern sie nach
|
|
außen (auf rund 9 % und 88 %) und der leere Hallenboden liegt dort,
|
|
wo gelesen wird. Ein Bild größer zu machen, damit WENIGER davon im
|
|
Weg ist, klingt verkehrt und ist genau richtig. */
|
|
|
|
body.start::before {
|
|
content: "";
|
|
position: fixed; inset: 0; z-index: 0;
|
|
pointer-events: none;
|
|
background-repeat: no-repeat;
|
|
/* cover statt "138% auto". Der alte Wert war der eigentliche Fehler:
|
|
Bei 138 % Fensterbreite wurde das Bild auf einem 2540 px breiten
|
|
Schirm 3500 px breit und knapp 2000 px hoch -- in einem 1300 px
|
|
hohen Fenster fehlten damit 700 px, und zwar oben. Genau deshalb
|
|
waren die Figuren riesig und ihre Koepfe abgeschnitten.
|
|
|
|
cover fuellt die Flaeche IMMER vollstaendig und skaliert dabei so
|
|
wenig wie noetig. Die Verankerung liegt auf 50 % 42 %: etwas ueber
|
|
der Mitte, weil dort in allen neun Szenen die Gesichter sitzen --
|
|
wenn etwas beschnitten werden muss, dann Fussboden und Decke. */
|
|
background-position: 50% 42%;
|
|
background-size: cover;
|
|
/* Rueckfall, falls eine Seite keine eigene Szene hat. */
|
|
background-image: url("../img/buehne-studio-breit.webp");
|
|
}
|
|
|
|
/* ---------- Neun Buehnen, nicht eine ------------------------------------
|
|
|
|
Filipe hat neun Bilder geschickt, damit es VERSCHIEDENE Hintergruende
|
|
gibt -- benutzt wurde davon lange nur das Studio. Jetzt hat jede Seite
|
|
ihre eigene Szene, ausgewaehlt ueber data-buehne am body (gesetzt von
|
|
kopf.js aus bereiche.js):
|
|
|
|
Aufgaben Werkstatt Kalender Nachtstadt Calls Sitzecke
|
|
Dateien Portal-Archiv Profil Halle Scout Wald
|
|
Dashboard grosse Buehne Content Durchgang Start Studio
|
|
|
|
Alle sind gleich abgedunkelt und tragen dieselbe Vignette -- sie sehen
|
|
verschieden aus und verhalten sich gleich. Eine Buehne, die je Seite
|
|
anders hell waere, waere Unruhe statt Vielfalt. */
|
|
body.start[data-buehne="studio"]::before { background-image: url("../img/buehne-studio-breit.webp"); }
|
|
body.start[data-buehne="showbuehne"]::before { background-image: url("../img/buehne-showbuehne-breit.webp"); }
|
|
body.start[data-buehne="garage"]::before { background-image: url("../img/buehne-garage-breit.webp"); }
|
|
body.start[data-buehne="skyline"]::before { background-image: url("../img/buehne-skyline-breit.webp"); }
|
|
body.start[data-buehne="lounge"]::before { background-image: url("../img/buehne-lounge-breit.webp"); }
|
|
body.start[data-buehne="arena"]::before { background-image: url("../img/buehne-arena-breit.webp"); }
|
|
body.start[data-buehne="halle"]::before { background-image: url("../img/buehne-halle-breit.webp"); }
|
|
body.start[data-buehne="wald"]::before { background-image: url("../img/buehne-wald-breit.webp"); }
|
|
body.start[data-buehne="portal"]::before { background-image: url("../img/buehne-portal-breit.webp"); }
|
|
|
|
|
|
/* Der Schleier. Er ist der Grund, warum Text über einem Foto unverändert
|
|
lesbar bleibt -- oben dicht für die Kopfleiste, in der Mitte dicht für
|
|
den Inhalt, an den Rändern offen, damit die beiden sichtbar bleiben.
|
|
Gemessen statt geschätzt: server/pruef-buehne.mjs rechnet den Kontrast
|
|
an echten Bildpunkten nach, an bis zu 34 Stellen je Seite. */
|
|
/* Der Schleier ist am 01.09.2026 spürbar durchlässiger geworden (Wunsch:
|
|
"den Hintergrund auch bisschen heller überall"). Er liegt jetzt bei
|
|
.86/.58/.44/.66 statt .95/.72/.60/.80 -- die Bühne kommt dadurch
|
|
deutlich durch, ohne dass sie den Text stört, weil die Inhalte auf
|
|
eigenen, kräftigeren Flächen liegen (siehe --glas in gate.css).
|
|
|
|
Ein zweiter, sehr weicher Farbschimmer in Blau-Violett legt sich
|
|
darüber. Er nimmt dem Bild das reine Schwarz und gibt der Seite
|
|
dieselbe Tiefe wie VanVans Hub -- ohne eine einzige Farbe zu
|
|
verfälschen, weil er nur 4-6 % beiträgt. */
|
|
body.start > .schleier {
|
|
position: fixed; inset: 0; z-index: 0; pointer-events: none;
|
|
background:
|
|
/* NUR NOCH DIE RAENDER. Der Schleier legte vorher .86/.58/.44
|
|
Schwarz ueber das ganze Bild -- also auch ueber die Mitte, in der
|
|
die Szene steht, und das ZUSAETZLICH zur Vignette, die dort
|
|
ebenfalls dunkel war. Zwei Schichten Dunkelheit uebereinander,
|
|
genau an der Stelle, die man sehen will.
|
|
|
|
Jetzt: oben ein Streifen (dort sitzt die Kopfleiste), unten ein
|
|
Streifen (dort laeuft die Seite aus), die Mitte fast frei. Der
|
|
Text braucht das nicht mehr -- er steht auf eigenen Flaechen. */
|
|
linear-gradient(180deg,
|
|
rgba(5, 7, 13, .82) 0%,
|
|
rgba(5, 7, 13, .34) 12%,
|
|
rgba(5, 7, 13, .12) 40%,
|
|
rgba(5, 7, 13, .12) 62%,
|
|
rgba(5, 7, 13, .52) 100%),
|
|
/* Zwei sehr weiche Farbschimmer in den gegenueberliegenden Ecken.
|
|
Sie nehmen dem Bild das reine Schwarz und geben ihm Tiefe, ohne
|
|
eine einzige Farbe zu verfaelschen -- 5 bis 7 Prozent. */
|
|
radial-gradient(75% 60% at 12% 4%, rgba(63, 189, 245, .07), transparent 70%),
|
|
radial-gradient(75% 65% at 90% 98%, rgba(138, 118, 255, .08), transparent 72%),
|
|
/* DIE LESESPUR — und der eigentliche Kniff.
|
|
|
|
In allen neun Szenen stehen HasiDog und DogFather AUSSEN, die
|
|
Mitte ist frei. Genau danach wurden die Bilder ausgesucht. Diese
|
|
Aufteilung wird jetzt benutzt, statt gegen sie zu arbeiten:
|
|
|
|
aussen das Bild bleibt hell und scharf -- dort stehen die
|
|
Figuren, und die sollen zu sehen sein
|
|
mitte gedaempft -- dort steht der Text
|
|
|
|
Vorher wurde entweder alles abgedunkelt (dann war das Bild
|
|
Nebel) oder gar nichts (dann war Schrift auf einer hellen Stelle
|
|
unlesbar, gemessene 1,08:1). Beides falsch. Der Rand bleibt in
|
|
jedem Fenster mindestens 380 px breit klar -- genug fuer die
|
|
Figuren, egal wie breit der Schirm ist. */
|
|
linear-gradient(90deg,
|
|
rgba(5, 7, 13, 0) 0,
|
|
rgba(5, 7, 13, .8) min(22%, 400px),
|
|
rgba(5, 7, 13, .86) 50%,
|
|
rgba(5, 7, 13, .8) max(78%, calc(100% - 400px)),
|
|
rgba(5, 7, 13, 0) 100%);
|
|
}
|
|
|
|
/* Alles Bedienbare liegt über der Bühne. Ohne das läge der Inhalt zwar
|
|
sichtbar darüber, aber Klicks landeten teils am falschen Ort. */
|
|
body.start > .kopfleiste,
|
|
body.start > .inhalt,
|
|
body.start > main { position: relative; z-index: 1; }
|
|
|
|
/* Auf schmalen Schirmen ein hochkant-Ausschnitt derselben Szene -- ein
|
|
auf 9:16 gequetschtes Breitbild zeigt nur noch Wand. */
|
|
@media (max-width: 760px) {
|
|
body.start::before {
|
|
background-image: url("../img/buehne-studio-schmal.webp");
|
|
background-size: cover;
|
|
background-position: 50% 38%;
|
|
}
|
|
body.start[data-buehne="studio"]::before { background-image: url("../img/buehne-studio-schmal.webp"); }
|
|
body.start[data-buehne="showbuehne"]::before { background-image: url("../img/buehne-showbuehne-schmal.webp"); }
|
|
body.start[data-buehne="garage"]::before { background-image: url("../img/buehne-garage-schmal.webp"); }
|
|
body.start[data-buehne="skyline"]::before { background-image: url("../img/buehne-skyline-schmal.webp"); }
|
|
body.start[data-buehne="lounge"]::before { background-image: url("../img/buehne-lounge-schmal.webp"); }
|
|
body.start[data-buehne="arena"]::before { background-image: url("../img/buehne-arena-schmal.webp"); }
|
|
body.start[data-buehne="halle"]::before { background-image: url("../img/buehne-halle-schmal.webp"); }
|
|
body.start[data-buehne="wald"]::before { background-image: url("../img/buehne-wald-schmal.webp"); }
|
|
body.start[data-buehne="portal"]::before { background-image: url("../img/buehne-portal-schmal.webp"); }
|
|
body.start > .schleier {
|
|
background:
|
|
linear-gradient(180deg, rgba(5, 7, 13, .86) 0%, rgba(5, 7, 13, .48) 14%,
|
|
rgba(5, 7, 13, .3) 55%, rgba(5, 7, 13, .66) 100%),
|
|
radial-gradient(90% 40% at 20% 4%, rgba(63, 189, 245, .06), transparent 70%),
|
|
radial-gradient(90% 40% at 85% 98%, rgba(138, 118, 255, .07), transparent 72%);
|
|
}
|
|
}
|
|
|
|
|
|
/* ---------- Kopfleiste ------------------------------------------------ */
|
|
|
|
.kopfleiste {
|
|
position: sticky; top: 0; z-index: 5;
|
|
display: flex; align-items: center; justify-content: space-between; gap: 16px;
|
|
padding: 14px clamp(16px, 4vw, 40px);
|
|
background: rgba(6, 9, 16, .82);
|
|
backdrop-filter: blur(18px);
|
|
-webkit-backdrop-filter: blur(18px);
|
|
border-bottom: 1px solid var(--rand);
|
|
}
|
|
|
|
/* Damit in einer Flex-Zeile ueberhaupt etwas schrumpfen KANN, braucht es
|
|
min-width: 0. Ohne diese eine Zeile behielt jedes Teil seine volle
|
|
Wunschbreite -- Zurueck (118) + Marke (141) + rechte Gruppe (297)
|
|
ergaben 556 px auf einem 390 px breiten Handy. Die Kopfleiste schob
|
|
214 px aus dem Bild und der Abmelden-Knopf war dort nicht mehr zu
|
|
erreichen. Auf JEDER Seite, seit es die Kopfleiste gibt; aufgefallen
|
|
erst beim Messen, weil man am Rechner nie danebengreift. */
|
|
.kopfleiste > * { min-width: 0; }
|
|
|
|
.kopfleiste .marke {
|
|
margin: 0; font-size: .72rem;
|
|
/* Die Marke gibt als Erstes nach: Ihr Inhalt steht direkt darunter
|
|
noch einmal als Ueberschrift, der Abmelden-Knopf dagegen nirgends. */
|
|
flex: 1 1 auto;
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
}
|
|
|
|
/* Zurück-Knopf. Steht ganz links, weil dort jeder ihn erwartet -- gleiche
|
|
Stelle wie im Browser. Auf der Startseite gibt es ihn gar nicht: Dort
|
|
ist kein "davor", und ein Knopf, der nichts tut, ist schlimmer als
|
|
keiner. Auf den übrigen Seiten entscheidet kopf.js, ob er erscheint. */
|
|
/* Entwurf "Neon-Kante": Der senkrechte Lichtstrich links ist dasselbe
|
|
Motiv wie die Kante der Anmelde-Tafel (.tafel__kante in gate.css).
|
|
Dadurch wirkt der Workspace wie ein Stück und nicht wie zusammen-
|
|
gesetzte Teile. */
|
|
.zurueck-knopf {
|
|
position: relative;
|
|
flex: 0 0 auto;
|
|
display: inline-flex; align-items: center; gap: 10px;
|
|
padding: 9px 18px 9px 17px;
|
|
border: 0;
|
|
/* Links flach, rechts rund: Die gerade Kante gehört dem Lichtstrich,
|
|
nach rechts läuft der Knopf weich aus. */
|
|
border-radius: 4px 999px 999px 4px;
|
|
background: linear-gradient(100deg,
|
|
rgba(63, 189, 245, .10), rgba(138, 118, 255, .05) 60%, transparent);
|
|
color: var(--text-leise);
|
|
font: inherit; font-size: .84rem; font-weight: 600;
|
|
cursor: pointer; white-space: nowrap;
|
|
transition: color var(--tempo), background var(--tempo);
|
|
}
|
|
|
|
/* Der Lichtstrich. Ruht etwas kürzer als der Knopf und wächst beim
|
|
Überfahren auf volle Höhe -- die Bewegung ersetzt jedes Aufblitzen. */
|
|
.zurueck-knopf::before {
|
|
content: "";
|
|
position: absolute; left: 0; top: 6px; bottom: 6px; width: 2px;
|
|
border-radius: 2px;
|
|
background: linear-gradient(180deg, var(--akzent), var(--violett));
|
|
box-shadow: 0 0 8px -1px rgba(63, 189, 245, .55);
|
|
transition: top var(--tempo), bottom var(--tempo), box-shadow var(--tempo);
|
|
}
|
|
|
|
.zurueck-knopf__pfeil {
|
|
width: 15px; height: 15px; flex: 0 0 auto;
|
|
fill: none; stroke: currentColor;
|
|
stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
|
|
transition: transform var(--tempo);
|
|
}
|
|
|
|
.zurueck-knopf:hover {
|
|
color: #fff;
|
|
background: linear-gradient(100deg,
|
|
rgba(63, 189, 245, .18), rgba(138, 118, 255, .09) 60%, transparent);
|
|
}
|
|
.zurueck-knopf:hover::before {
|
|
top: 0; bottom: 0;
|
|
box-shadow: 0 0 14px 0 rgba(63, 189, 245, .75);
|
|
}
|
|
/* Der Pfeil rückt nach links -- sagt die Richtung ohne zusätzlichen Text. */
|
|
.zurueck-knopf:hover .zurueck-knopf__pfeil { transform: translateX(-3px); }
|
|
|
|
.zurueck-knopf:active { transform: translateY(1px); }
|
|
|
|
.zurueck-knopf:focus-visible {
|
|
outline: 2px solid var(--akzent);
|
|
outline-offset: 3px;
|
|
border-radius: 4px 999px 999px 4px;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.zurueck-knopf, .zurueck-knopf::before, .zurueck-knopf__pfeil { transition: none; }
|
|
.zurueck-knopf:hover .zurueck-knopf__pfeil { transform: none; }
|
|
}
|
|
|
|
.kopfleiste__rechts { display: flex; align-items: center; gap: 12px; flex: 0 1 auto; min-width: 0; }
|
|
.kopfleiste__rechts > * { flex: 0 0 auto; }
|
|
|
|
.wer {
|
|
font-size: .86rem; color: var(--text-leise);
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 46vw;
|
|
/* Der Name darf kuerzer werden -- der Knopf daneben nicht. */
|
|
flex: 0 1 auto; min-width: 0;
|
|
}
|
|
|
|
|
|
/* ---------- Inhalt ---------------------------------------------------- */
|
|
|
|
.inhalt {
|
|
max-width: 880px;
|
|
margin: 0 auto;
|
|
padding: clamp(28px, 5vw, 56px) clamp(16px, 4vw, 40px) 64px;
|
|
}
|
|
|
|
/* Diese vier standen bis zum 31.08.2026 in aufgaben.css -- also in einer
|
|
Datei, die eine neue Seite gar nicht laden muss. Genau dadurch war das
|
|
Dashboard beim ersten Aufbau schmal und ohne Kopfzeilen-Layout: die
|
|
Klassen im HTML gab es, die Regeln dazu nicht. Derselbe Fehler ist
|
|
vorher schon zweimal passiert (.knopf-still, .schalter). Was auf
|
|
mehreren Seiten benutzt wird, gehoert hierher, wo jede Seite es hat. */
|
|
.inhalt--breit { max-width: 1240px; }
|
|
|
|
.zurueck { color: inherit; text-decoration: none; border-bottom: 1px solid transparent; }
|
|
.zurueck:hover { border-bottom-color: currentColor; }
|
|
|
|
/* ---------- Der Kopf jeder Unterseite ------------------------------------
|
|
|
|
Bis zum 01.09.2026 war das eine Zeile Text mit einem Knopf daneben --
|
|
auf allen dreizehn Seiten dieselbe, in derselben Farbe, ohne Zeichen.
|
|
Wer eine Kachel anklickte, verlor beim Übergang jede Spur davon,
|
|
woher er kam.
|
|
|
|
Jetzt trägt der Kopf Zeichen UND Farbton seiner Kachel (gesetzt von
|
|
kopf.js aus derselben Liste, aus der auch die Kachel kommt) und
|
|
bekommt dieselbe Behandlung wie sie: Plakette mit dem Zeichen, ein
|
|
leuchtender Strich über der Bereichsangabe, ein sehr schwaches
|
|
Wasserzeichen dahinter und eine auslaufende Trennlinie darunter.
|
|
|
|
Nichts davon ist Schmuck um seiner selbst willen: Es ist dieselbe
|
|
Bildsprache wie auf der Startseite, und dadurch weiß man ohne Lesen,
|
|
wo man ist. */
|
|
.kopf-zeile {
|
|
position: relative;
|
|
overflow: hidden;
|
|
display: flex; align-items: flex-end; justify-content: space-between;
|
|
gap: 20px; flex-wrap: wrap;
|
|
margin-bottom: 28px; padding: 0 0 20px;
|
|
border-bottom: 1px solid transparent;
|
|
border-image: linear-gradient(90deg,
|
|
color-mix(in srgb, var(--ton, var(--akzent)) 40%, var(--rand-hell)),
|
|
transparent 62%) 1;
|
|
}
|
|
.kopf-zeile .titel {
|
|
margin: 0;
|
|
font-size: clamp(1.5rem, 2.6vw, 2.1rem);
|
|
letter-spacing: -.02em;
|
|
color: #f2f7fd;
|
|
text-shadow: 0 2px 22px color-mix(in srgb, var(--ton, var(--akzent)) 22%, transparent);
|
|
}
|
|
.kopf-zeile .unterzeile { margin-bottom: 0; }
|
|
|
|
/* Zeichen und Text nebeneinander. Der Block darf schrumpfen (min-width),
|
|
sonst drückt er den Knopf rechts aus dem Bild -- derselbe Fehler wie
|
|
im August in der Kopfleiste. */
|
|
.kopf-zeile__marke {
|
|
display: flex; align-items: center; gap: 16px;
|
|
min-width: 0; flex: 1 1 auto;
|
|
position: relative; z-index: 1;
|
|
}
|
|
.kopf-zeichen {
|
|
flex: none;
|
|
display: grid; place-items: center;
|
|
width: 52px; height: 52px; border-radius: 15px;
|
|
border: 1px solid color-mix(in srgb, var(--ton, var(--akzent)) 34%, transparent);
|
|
background:
|
|
radial-gradient(120% 120% at 30% 18%,
|
|
color-mix(in srgb, var(--ton, var(--akzent)) 26%, transparent), transparent 72%),
|
|
rgba(255, 255, 255, .04);
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255, 255, 255, .09),
|
|
0 12px 28px -14px color-mix(in srgb, var(--ton, var(--akzent)) 70%, transparent);
|
|
}
|
|
.kopf-zeichen__svg {
|
|
width: 26px; height: 26px;
|
|
fill: none; stroke: var(--ton, var(--akzent)); stroke-width: 1.6;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
}
|
|
|
|
/* Der Bereichsname über dem Titel bekommt denselben leuchtenden Strich
|
|
wie die Abschnitte auf der Startseite -- so gehört sichtbar zusammen,
|
|
was zusammengehört. */
|
|
.kopf-zeile .marke {
|
|
display: flex; align-items: center; gap: 9px;
|
|
margin-bottom: 7px;
|
|
color: color-mix(in srgb, var(--ton, var(--akzent)) 62%, #cfe0f0);
|
|
}
|
|
.kopf-zeile .marke::before {
|
|
content: "";
|
|
width: 22px; height: 2px; border-radius: 2px;
|
|
background: linear-gradient(90deg, var(--ton, var(--akzent)), transparent);
|
|
}
|
|
|
|
/* Dasselbe Zeichen noch einmal, riesig und fast unsichtbar. Es liegt im
|
|
Kopf (overflow: hidden schneidet es sauber ab) und macht jede Seite
|
|
auf den ersten Blick unverwechselbar, ohne dass man es bewusst
|
|
wahrnimmt. */
|
|
.kopf-wasserzeichen {
|
|
position: absolute; right: -18px; top: 50%;
|
|
transform: translateY(-50%) rotate(-8deg);
|
|
pointer-events: none;
|
|
opacity: .06;
|
|
z-index: 0;
|
|
}
|
|
.kopf-wasserzeichen__svg {
|
|
width: 190px; height: 190px;
|
|
fill: none; stroke: var(--ton, var(--akzent)); stroke-width: 1;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
}
|
|
/* Auf schmalen Bildschirmen läge das Wasserzeichen unter dem Text und
|
|
würde ihn unruhig machen -- dort bleibt es weg. */
|
|
@media (max-width: 720px) {
|
|
.kopf-wasserzeichen { display: none; }
|
|
.kopf-zeichen { width: 42px; height: 42px; border-radius: 12px; }
|
|
.kopf-zeichen__svg { width: 21px; height: 21px; }
|
|
.kopf-zeile__marke { gap: 12px; }
|
|
}
|
|
@media (forced-colors: active) {
|
|
.kopf-wasserzeichen { display: none; }
|
|
.kopf-zeichen__svg { stroke: CanvasText; }
|
|
}
|
|
|
|
.leise { color: var(--text-still); font-weight: 400; }
|
|
|
|
/* ---------- Wenn nichts da ist -------------------------------------------
|
|
|
|
Diese Regel stand in NEUN Dateien -- neunmal fast dasselbe, mit
|
|
Abständen von 22, 26 und 30 px, weil beim Kopieren jedes Mal etwas
|
|
anders wurde. Genau davor warnt der Kommentar weiter oben. Jetzt
|
|
einmal hier, und jede Seite hat sie.
|
|
|
|
Wichtiger als das Aufräumen ist aber, WIE der leere Zustand aussieht.
|
|
Vorher: ein gestrichelter Kasten mit einem grauen Satz. Gestrichelte
|
|
Ränder sagen "hier fehlt etwas", und grau auf grau sagt "unwichtig" --
|
|
zusammen also: eine kaputt wirkende Seite, obwohl gar nichts kaputt
|
|
ist. Eine leere Liste ist ein normaler Zustand, oft sogar ein guter.
|
|
|
|
Jetzt: eine ruhige, geschlossene Fläche im Farbton der Seite (der
|
|
kommt aus data-ton am body, gesetzt von kopf.js), mit einem
|
|
leuchtenden Ring darüber. Sie sieht aus wie ein fertiges Bauteil und
|
|
nicht wie ein Loch. */
|
|
.leer-hinweis {
|
|
position: relative; overflow: hidden;
|
|
padding: 34px 26px 32px;
|
|
text-align: center;
|
|
color: var(--text-leise); font-size: .92rem; line-height: 1.6;
|
|
border: 1px solid color-mix(in srgb, var(--ton, var(--akzent)) 20%, var(--rand));
|
|
border-radius: var(--radius);
|
|
background:
|
|
radial-gradient(120% 90% at 50% -10%,
|
|
color-mix(in srgb, var(--ton, var(--akzent)) 9%, transparent), transparent 68%),
|
|
var(--flaeche);
|
|
}
|
|
/* Der Ring: ein Kreis in der Seitenfarbe, hohl, weich leuchtend. Ein
|
|
Zeichen wäre hier zu laut -- es geht ja gerade darum, dass NICHTS da
|
|
ist. Der Ring markiert die Stelle, ohne etwas zu behaupten. */
|
|
.leer-hinweis::before {
|
|
content: "";
|
|
display: block;
|
|
width: 34px; height: 34px;
|
|
margin: 0 auto 14px;
|
|
border-radius: 50%;
|
|
border: 1.5px solid color-mix(in srgb, var(--ton, var(--akzent)) 40%, transparent);
|
|
background: radial-gradient(circle,
|
|
color-mix(in srgb, var(--ton, var(--akzent)) 22%, transparent), transparent 70%);
|
|
box-shadow: 0 0 22px -6px color-mix(in srgb, var(--ton, var(--akzent)) 60%, transparent);
|
|
}
|
|
/* Ein zweiter Satz darin ist der Tipp, was man jetzt tun kann. Wenn
|
|
schon nichts dasteht, soll wenigstens dastehen, wie etwas hinkommt. */
|
|
.leer-hinweis__tipp {
|
|
display: block; margin-top: 7px;
|
|
font-size: .82rem; color: var(--text-still);
|
|
}
|
|
@media (forced-colors: active) {
|
|
.leer-hinweis::before { border-color: CanvasText; background: none; }
|
|
}
|
|
|
|
/* ---------- Auf- und Zuklappen ------------------------------------------
|
|
Lange Listen (Protokoll, Verlauf) stehen zugeklappt da und zeigen nur
|
|
die neuesten Zeilen. Der Pfeil dreht sich beim Aufklappen -- er zeigt
|
|
die Richtung, der Text daneben sagt, was der Knopf TUT.
|
|
|
|
Steht hier und nicht in einer Seiten-Datei: Er wird an mehreren
|
|
Stellen gebraucht, und genau so sind schon dreimal Regeln dort
|
|
gelandet, wo eine Seite sie gar nicht laedt. */
|
|
|
|
.klapp-kopf {
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
gap: 12px; flex-wrap: wrap; margin-bottom: 8px;
|
|
}
|
|
.klapp-kopf > .feldschild, .klapp-kopf > .block__titel { margin: 0; }
|
|
|
|
.klapp-pfeil {
|
|
width: 14px; height: 14px; flex: 0 0 auto;
|
|
fill: none; stroke: currentColor;
|
|
stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
|
|
transition: transform var(--tempo);
|
|
}
|
|
[aria-expanded="true"] > .klapp-pfeil { transform: rotate(180deg); }
|
|
|
|
/* Zugeklappt bleiben die vier neuesten Zeilen stehen. Bewusst ueber CSS
|
|
statt ueber das Entfernen von Zeilen: Das Aufklappen braucht dann
|
|
weder einen neuen Aufbau noch eine zweite Abfrage. */
|
|
[data-klapp="zu"] > *:nth-child(n+5) { display: none; }
|
|
|
|
.willkommen { margin-bottom: 38px; }
|
|
.willkommen .titel { margin-bottom: 6px; }
|
|
|
|
/* ---------- Zahlen ---------------------------------------------------- */
|
|
|
|
.zahlen-block { margin-bottom: 34px; }
|
|
|
|
.zahlen {
|
|
list-style: none; margin: 0; padding: 0;
|
|
display: grid; gap: 10px;
|
|
grid-template-columns: repeat(auto-fit, minmax(122px, 1fr));
|
|
}
|
|
|
|
.zahl {
|
|
padding: 14px 16px;
|
|
background: var(--flaeche);
|
|
border: 1px solid var(--rand);
|
|
border-radius: var(--radius-klein);
|
|
}
|
|
.zahl__wert { display: block; font-size: 1.7rem; font-weight: 700; line-height: 1.1; }
|
|
.zahl__name { display: block; margin-top: 2px; font-size: .78rem; color: var(--text-still); }
|
|
|
|
/* Nur wenn wirklich etwas überfällig ist, wird die Kachel hervorgehoben --
|
|
sonst stumpft die Farbe ab und man übersieht sie im Ernstfall. */
|
|
.zahl[data-warn="ja"] { border-color: rgba(255, 154, 162, .42); background: rgba(255, 154, 162, .07); }
|
|
.zahl[data-warn="ja"] .zahl__wert { color: var(--warn); }
|
|
|
|
/* ---------- Bereiche: Gruppen und Kacheln --------------------------------
|
|
|
|
Vorher: siebzehn gleiche Rechtecke mit "ÖFFNEN" darauf. Wenn alles
|
|
gleich aussieht, ist alles gleich wichtig -- also nichts.
|
|
|
|
Drei Dinge tragen jetzt die Gestaltung:
|
|
|
|
1. Die Kachel ist ruhig, bis man sie ansieht. Der Farbton sitzt im
|
|
Zeichen und in einer schmalen Kante -- nicht als Fläche. Siebzehn
|
|
farbige Flächen wären ein Bonbonglas, kein Werkzeug.
|
|
|
|
2. Beim Überfahren geht ein sehr weicher Schimmer aus der oberen
|
|
linken Ecke an. Kein Blitzen, kein Springen: Alphawerte unter 0.25,
|
|
Bewegung unter einem Pixel.
|
|
|
|
3. Der Einlauf ist gestaffelt -- genau EINE Bewegung beim Aufbau,
|
|
danach Ruhe. Bei "weniger Bewegung" fällt sie ersatzlos weg.
|
|
|
|
Die acht Farbtöne sind gegen genau diesen Hintergrund gerechnet:
|
|
Helligkeitsband, Farbstärke, Abstand bei Farbfehlsichtigkeit
|
|
(schlechtestes Paar dE 8.4), Normalsicht-Abstand (19.3) und Kontrast
|
|
-- alle Prüfungen bestanden. Warum acht und nicht siebzehn: Siebzehn
|
|
unterscheidbare Farben gibt es nicht; ein Versuch mit einer eigenen
|
|
Farbe je Kachel ergab Paare mit Abstand 1.4, also praktisch dieselbe
|
|
Farbe. Sie stützen nur -- WAS eine Kachel ist, sagen Zeichen und Name.
|
|
------------------------------------------------------------------------- */
|
|
|
|
.gruppe { margin-bottom: 34px; }
|
|
.gruppe:last-child { margin-bottom: 0; }
|
|
|
|
.gruppe__kopf {
|
|
position: relative;
|
|
display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
|
|
margin-bottom: 14px; padding-bottom: 10px;
|
|
/* Die Trennlinie läuft nach rechts aus, statt hart abzubrechen --
|
|
eine durchgezogene Linie über die ganze Breite zerschneidet die
|
|
Seite, eine auslaufende gliedert sie nur. */
|
|
border-bottom: 1px solid transparent;
|
|
border-image: linear-gradient(90deg, var(--rand-hell), transparent 70%) 1;
|
|
}
|
|
.gruppe__name {
|
|
margin: 0; font-size: .76rem; font-weight: 700;
|
|
letter-spacing: .1em; text-transform: uppercase; color: var(--text-leise);
|
|
}
|
|
.gruppe__unter { font-size: .78rem; color: var(--text-still); }
|
|
|
|
.kacheln {
|
|
list-style: none; margin: 0; padding: 0;
|
|
display: grid; gap: 12px;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
}
|
|
|
|
/* 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.
|
|
|
|
Die Töne hängen bewusst NICHT an .kachel, sondern nur am Merkmal
|
|
data-ton: Dieselbe Nummer färbt die Kachel und die Hinweiszeile, die
|
|
dorthin führt. Eine Farbe gehört hier zu einem Bereich, nicht zu einem
|
|
Bauteil. */
|
|
[data-ton="1"] { --ton: #3e95e7; } /* 250° */
|
|
[data-ton="2"] { --ton: #7089ea; } /* 271° */
|
|
[data-ton="3"] { --ton: #947de2; } /* 292° */
|
|
[data-ton="4"] { --ton: #b173d0; } /* 314° */
|
|
[data-ton="5"] { --ton: #c66ab5; } /* 335° */
|
|
[data-ton="6"] { --ton: #d56694; } /* 356° */
|
|
[data-ton="7"] { --ton: #dc666f; } /* 17° */
|
|
[data-ton="8"] { --ton: #db6c48; } /* 38° */
|
|
[data-ton="9"] { --ton: #d17717; } /* 59° */
|
|
[data-ton="10"] { --ton: #ba8610; } /* 81° */
|
|
[data-ton="11"] { --ton: #a29205; } /* 102° */
|
|
[data-ton="12"] { --ton: #809e23; } /* 123° */
|
|
[data-ton="13"] { --ton: #50a752; } /* 144° */
|
|
[data-ton="14"] { --ton: #07aa7c; } /* 165° */
|
|
[data-ton="15"] { --ton: #12a69b; } /* 186° */
|
|
[data-ton="16"] { --ton: #04a3b4; } /* 208° */
|
|
[data-ton="17"] { --ton: #059ece; } /* 229° */
|
|
|
|
/* Rückfallwert für alles, was einen Ton braucht, aber keine Nummer hat.
|
|
Steht bewusst in :where() -- damit zählt die Zeile beim Wettstreit der
|
|
Regeln als NICHT vorhanden und die Nummer oben gewinnt immer. Ohne
|
|
das Kniff hätte diese Zeile (eine Klasse, weiter unten in der Datei)
|
|
alle siebzehn Töne überstimmt und jede Kachel wäre blau gewesen. */
|
|
:where(.kachel, .dran__punkt) { --ton: var(--akzent); }
|
|
|
|
.kachel {
|
|
/* Wo der Zeiger steht. Wird von start.js gesetzt; die Mitte ist der
|
|
Rückfallwert, damit ohne Zeiger nichts springt. */
|
|
--mx: 50%;
|
|
--my: 0%;
|
|
position: relative;
|
|
border-radius: 18px;
|
|
background:
|
|
linear-gradient(155deg,
|
|
color-mix(in srgb, var(--ton) 26%, var(--flaeche)),
|
|
var(--flaeche) 62%);
|
|
border: 1px solid var(--rand);
|
|
/* Die feine helle Linie an der Oberkante. Ein Pixel, kaum sichtbar --
|
|
aber die Kachel wirkt dadurch von oben beleuchtet statt aufgeklebt.
|
|
Das ist der Unterschied zwischen "Kasten" und "Objekt". */
|
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .055);
|
|
overflow: hidden;
|
|
transition: border-color var(--tempo), transform var(--tempo), box-shadow var(--tempo);
|
|
}
|
|
.kachel[data-gross="ja"] { grid-column: span 2; }
|
|
|
|
/* Die farbige Kante links. Sie ist das Einzige, was den Ton kräftig
|
|
zeigt -- drei Pixel reichen, um eine Kachel wiederzuerkennen. */
|
|
.kachel::before {
|
|
content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
|
|
background: linear-gradient(180deg, var(--ton), transparent 92%);
|
|
opacity: .55;
|
|
transition: opacity var(--tempo), width var(--tempo);
|
|
}
|
|
|
|
/* Das Licht. Es liegt schwach auf der Kachel und FOLGT beim Überfahren
|
|
dem Zeiger -- das ist die Kleinigkeit, die man nicht sieht, sondern
|
|
erst beim Benutzen merkt. Kein Blinken, keine Bewegung des Inhalts:
|
|
Es wird nur an einer anderen Stelle heller.
|
|
|
|
Ruhend sitzt es in der oberen linken Ecke (--my: 0%), damit die
|
|
Kacheln auch ohne Zeiger von einer Seite beleuchtet wirken. */
|
|
.kachel::after {
|
|
content: ""; position: absolute; inset: 0; pointer-events: none;
|
|
background: radial-gradient(130% 150% at var(--mx) var(--my),
|
|
color-mix(in srgb, var(--ton) 20%, transparent), transparent 60%);
|
|
opacity: .38;
|
|
transition: opacity var(--tempo);
|
|
}
|
|
|
|
.kachel:hover {
|
|
border-color: color-mix(in srgb, var(--ton) 45%, var(--rand));
|
|
transform: translateY(-2px);
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255, 255, 255, .09),
|
|
0 10px 26px -14px color-mix(in srgb, var(--ton) 55%, transparent);
|
|
}
|
|
.kachel:hover::before { opacity: 1; width: 4px; }
|
|
.kachel:hover::after { opacity: 1; }
|
|
.kachel:has(:focus-visible) { border-color: var(--ton); }
|
|
|
|
.kachel__link {
|
|
position: relative; z-index: 1;
|
|
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;
|
|
}
|
|
|
|
/* Das Zeichen sitzt in einem eigenen Feld -- dadurch bekommt der Ton
|
|
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: 52px; height: 52px; border-radius: 15px;
|
|
background:
|
|
linear-gradient(160deg,
|
|
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) 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: 62px; height: 62px; border-radius: 18px; }
|
|
|
|
.kachel__svg {
|
|
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: 31px; height: 31px; }
|
|
|
|
.kachel__text { position: relative; z-index: 1; display: grid; gap: 3px; min-width: 0; }
|
|
.kachel__name {
|
|
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.24rem; }
|
|
.kachel__unter {
|
|
font-size: .78rem; color: var(--text-still); line-height: 1.3;
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
}
|
|
.kachel[data-gross="ja"] .kachel__unter { font-size: .83rem; }
|
|
|
|
/* Die Zahl auf der Kachel. Sie ersetzt den Pfeil, wenn dort Arbeit
|
|
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;
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--ton);
|
|
background: color-mix(in srgb, var(--ton) 15%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--ton) 36%, transparent);
|
|
box-shadow: inset 0 1px 0 color-mix(in srgb, var(--ton) 26%, transparent);
|
|
border-radius: 999px;
|
|
transition: background var(--tempo), border-color var(--tempo);
|
|
}
|
|
.kachel:hover .kachel__zahl {
|
|
background: color-mix(in srgb, var(--ton) 24%, transparent);
|
|
border-color: color-mix(in srgb, var(--ton) 55%, transparent);
|
|
}
|
|
.kachel__zahl[data-warn="ja"] {
|
|
color: var(--warn);
|
|
background: rgba(255, 154, 162, .13);
|
|
border-color: rgba(255, 154, 162, .44);
|
|
box-shadow: inset 0 1px 0 rgba(255, 154, 162, .28);
|
|
}
|
|
.kachel:hover .kachel__zahl[data-warn="ja"] {
|
|
background: rgba(255, 154, 162, .2); border-color: rgba(255, 154, 162, .62);
|
|
}
|
|
|
|
.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);
|
|
}
|
|
.kachel:hover .kachel__pfeil { color: var(--ton); transform: translateX(4px); }
|
|
|
|
/* Gestaffelter Einlauf. Die Verzögerung kommt aus --nr, das start.js je
|
|
Kachel setzt. Steht in einer no-preference-Abfrage, damit bei
|
|
"weniger Bewegung" gar keine Animation entsteht -- nicht nur eine
|
|
ohne Dauer. */
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
.kachel {
|
|
animation: kachel-ein .38s cubic-bezier(.32, 0, .2, 1) backwards;
|
|
animation-delay: calc(var(--nr, 0) * 26ms);
|
|
}
|
|
@keyframes kachel-ein {
|
|
from { opacity: 0; transform: translateY(6px); }
|
|
to { opacity: 1; transform: none; }
|
|
}
|
|
}
|
|
|
|
/* Der leere Zustand ist kein Fehler, sondern das Ziel -- deshalb ein
|
|
ruhiges Gruen statt gestrichelter Leere. Gedeckt gehalten, kein
|
|
Signalgruen: Es soll freuen, nicht blenden. */
|
|
.zahlen-leer {
|
|
display: flex; align-items: center; gap: 13px;
|
|
margin: 0; padding: 14px 17px;
|
|
font-size: .9rem; color: var(--text);
|
|
border: 1px solid rgba(80, 167, 130, .28);
|
|
border-radius: var(--radius-klein);
|
|
background: linear-gradient(90deg, rgba(80, 167, 130, .1), transparent 60%);
|
|
}
|
|
.zahlen-leer__haken {
|
|
flex: none; display: grid; place-items: center;
|
|
width: 30px; height: 30px; border-radius: 50%;
|
|
border: 1px solid rgba(80, 167, 130, .38);
|
|
background: rgba(80, 167, 130, .14);
|
|
}
|
|
.zahlen-leer__haken svg {
|
|
width: 16px; height: 16px;
|
|
fill: none; stroke: #6fbd95; stroke-width: 2;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
}
|
|
/* Pflicht, sobald hier ein display steht: Das display der Klasse ist
|
|
staerker als das hidden des Browsers -- ohne diese Zeile stuende der
|
|
Satz IMMER da, auch wenn Aufgaben offen sind. */
|
|
.zahlen-leer[hidden] { display: none; }
|
|
.zahlen-leer__still { color: var(--text-leise); }
|
|
.zahlen-leer strong { font-weight: 650; }
|
|
.zahlen-leer strong::after { content: " "; }
|
|
|
|
@media (max-width: 900px) {
|
|
.kacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
.kachel[data-gross="ja"] { grid-column: span 2; }
|
|
}
|
|
@media (max-width: 560px) {
|
|
.kacheln { grid-template-columns: 1fr; }
|
|
.kachel[data-gross="ja"] { grid-column: span 1; }
|
|
.gruppe__kopf { gap: 4px; }
|
|
.gruppe__unter { flex-basis: 100%; }
|
|
}
|
|
|
|
.inhalt .fuss { margin-top: 40px; text-align: left; }
|
|
|
|
@media (max-width: 520px) {
|
|
.kopfleiste { padding: 12px 16px; gap: 10px; }
|
|
/* Die Marke wich zwar zurueck, nahm aber immer noch so viel Platz,
|
|
dass vom Namen nur noch drei Pixel uebrig blieben. Auf dem Handy
|
|
verschwindet sie deshalb -- genau derselbe Text steht zwei Zeilen
|
|
tiefer als Ueberschrift, der Name des Angemeldeten dagegen
|
|
nirgends sonst.
|
|
|
|
Aber nur dort, wo der Zurueck-Knopf sichtbar ist: Auf der
|
|
Startseite gibt es ihn nicht, dort waere die linke Haelfte sonst
|
|
leer und die Leiste saehe kaputt aus. */
|
|
.kopfleiste:has(.zurueck-knopf:not([hidden])) .marke { display: none; }
|
|
.kopfleiste__rechts { margin-left: auto; }
|
|
.wer { max-width: none; }
|
|
/* Der Pfeil allein sagt "zurueck" -- das Wort daneben kostet auf dem
|
|
Handy 65 px, die dem Abmelden-Knopf fehlen. Vorlesende Programme
|
|
verlieren nichts: Der Text bleibt im Dokument und wird nur
|
|
unsichtbar gerechnet. */
|
|
.zurueck-knopf { padding: 9px 12px 9px 11px; }
|
|
.zurueck-knopf__text {
|
|
position: absolute; width: 1px; height: 1px;
|
|
margin: -1px; padding: 0; overflow: hidden;
|
|
clip-path: inset(50%); white-space: nowrap;
|
|
}
|
|
.zurueck-knopf { gap: 0; }
|
|
}
|
|
|
|
/* Zurueckhaltender Zweitknopf. Gehoert bewusst hierher und nicht in eine
|
|
einzelne Seite: Er wird ueberall gebraucht, und als Seiten-CSS fehlte er
|
|
prompt dort, wo die Datei nicht geladen war -- dann standen nackte
|
|
Systemknoepfe in der Oberflaeche. */
|
|
|
|
/* ---------- Was ist dran ------------------------------------------------
|
|
Steht vor den Zahlen. Zahlen sagen, WIE VIEL anliegt -- diese Liste
|
|
sagt, WAS zu tun ist. Nur drei Stufen, und nur die oberste ist farbig:
|
|
Waere alles hervorgehoben, waere nichts hervorgehoben. */
|
|
/* Die Seite ist breit, damit die Kacheln Platz haben. Eine Zeile Text
|
|
ueber 1240 px zu ziehen macht sie aber nicht lesbarer, sondern
|
|
anstrengender -- Hinweise und Begruessung behalten deshalb ihr Mass. */
|
|
.willkommen, .dran__liste, .inhalt .fuss { max-width: 940px; }
|
|
|
|
.dran { margin-bottom: 30px; }
|
|
.dran__liste { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
|
|
|
|
/* Jede Zeile traegt Zeichen und Farbe ihrer Kachel (data-ton kommt aus
|
|
start.js). Ohne Zuordnung bleibt der Hausakzent -- eine Zeile ohne
|
|
Farbe gibt es nicht. */
|
|
.dran__punkt {
|
|
/* --ton kommt aus data-ton bzw. dem Rückfallwert in :where() oben. */
|
|
position: relative;
|
|
overflow: hidden;
|
|
border: 1px solid var(--rand);
|
|
border-radius: var(--radius-klein);
|
|
background:
|
|
linear-gradient(90deg, color-mix(in srgb, var(--ton) 9%, transparent), transparent 46%),
|
|
var(--flaeche);
|
|
transition: border-color .18s ease, background .18s ease, transform .18s ease;
|
|
}
|
|
/* Der Streifen links ist die Farbe der Kachel, zu der es geht -- oben
|
|
kraeftig, unten auslaufend, damit er nicht wie ein Balken wirkt. */
|
|
.dran__punkt::before {
|
|
content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
|
|
background: linear-gradient(180deg,
|
|
var(--ton),
|
|
color-mix(in srgb, var(--ton) 35%, transparent));
|
|
}
|
|
|
|
/* Ueberfaellig schlaegt Bereichsfarbe: Wenn etwas brennt, zaehlt zuerst
|
|
DASS es brennt. Das Zeichen sagt weiterhin, wo. */
|
|
.dran__punkt[data-stufe="warnung"] {
|
|
--ton: var(--warn);
|
|
border-color: rgba(255, 154, 162, .3);
|
|
}
|
|
.dran__punkt[data-stufe="ruhig"] { opacity: .8; }
|
|
.dran__punkt:hover {
|
|
border-color: color-mix(in srgb, var(--ton) 42%, var(--rand));
|
|
background:
|
|
linear-gradient(90deg, color-mix(in srgb, var(--ton) 15%, transparent), transparent 52%),
|
|
rgba(255, 255, 255, .05);
|
|
}
|
|
.dran__punkt[data-stufe="ruhig"]:hover { opacity: 1; }
|
|
|
|
.dran__link {
|
|
display: grid;
|
|
grid-template-columns: auto auto 1fr auto;
|
|
align-items: center; gap: 13px;
|
|
padding: 11px 15px 11px 17px;
|
|
color: var(--text); text-decoration: none; font-size: .9rem;
|
|
}
|
|
.dran__zeichen {
|
|
display: grid; place-items: center;
|
|
width: 30px; height: 30px; border-radius: 9px;
|
|
border: 1px solid color-mix(in srgb, var(--ton) 30%, transparent);
|
|
background: color-mix(in srgb, var(--ton) 13%, transparent);
|
|
transition: transform .18s ease, background .18s ease;
|
|
}
|
|
.dran__svg {
|
|
width: 16px; height: 16px;
|
|
fill: none; stroke: var(--ton); stroke-width: 1.7;
|
|
stroke-linecap: round; stroke-linejoin: round;
|
|
}
|
|
.dran__link:hover .dran__zeichen {
|
|
transform: scale(1.07);
|
|
background: color-mix(in srgb, var(--ton) 20%, transparent);
|
|
}
|
|
/* Die Zahl steht vorn und in gleicher Zeichenbreite: Beim Ueberfliegen
|
|
von sieben Zeilen liest man sie zuerst, und sie sollen untereinander
|
|
stehen, nicht huepfen. */
|
|
.dran__zahl {
|
|
font-size: 1.15rem; font-weight: 700; line-height: 1;
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--ton);
|
|
min-width: 1.6ch; text-align: right;
|
|
}
|
|
.dran__text { color: var(--text-leise); }
|
|
.dran__punkt[data-stufe="warnung"] .dran__text { color: var(--text); font-weight: 600; }
|
|
.dran__pfeil {
|
|
color: var(--text-still); font-size: .95rem;
|
|
transition: transform .18s ease, color .18s ease;
|
|
}
|
|
.dran__link:hover .dran__pfeil { color: var(--ton); transform: translateX(3px); }
|
|
|
|
/* Auf dem Handy ist Platz das knappste Gut: Zeichen und Pfeil weichen,
|
|
Zahl und Satz bleiben -- die tragen die Aussage. */
|
|
@media (max-width: 460px) {
|
|
.dran__link { grid-template-columns: auto 1fr; gap: 10px; padding: 11px 13px 11px 15px; }
|
|
.dran__zeichen, .dran__pfeil { display: none; }
|
|
}
|
|
|
|
@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, .dran__zeichen { transition: none; }
|
|
.dran__link:hover .dran__pfeil { transform: none; }
|
|
.dran__link:hover .dran__zeichen { transform: none; }
|
|
}
|
|
|
|
/* Ohne Farbverlaeufe (Kontrastmodus, Druck) bleibt der Streifen als
|
|
einfarbige Kante -- sonst waere die Zuordnung dort ganz weg. */
|
|
@media (forced-colors: active) {
|
|
.dran__punkt::before { background: CanvasText; }
|
|
.dran__svg { stroke: CanvasText; }
|
|
.dran__zahl { color: CanvasText; }
|
|
}
|
|
|
|
/* =====================================================================
|
|
Kopfleiste, Begrüßung, Hinweise -- der Feinschliff vom 01.09.2026.
|
|
|
|
Vorher waren das vier Stellen mit reinem Systemtext: eine Marke in
|
|
Großbuchstaben, eine Überschrift, ein Name, eine Liste. Alles
|
|
funktionierte, nichts sagte etwas über den Ort, an dem man ist.
|
|
===================================================================== */
|
|
|
|
/* ---------- Die Marke oben links ----------------------------------------
|
|
|
|
Der DogFather-Kopf davor. Als MASKE, nicht als Bild: Die Form wird im
|
|
Stil eingefärbt (siehe tools/buehne-bauen.mjs). Ein fertig
|
|
eingefärbtes Bild müsste man für jede Farbe neu bauen -- und beim
|
|
Überfahren wechselt die Farbe. */
|
|
.kopfleiste .marke {
|
|
display: flex; align-items: center; gap: 9px;
|
|
letter-spacing: .14em;
|
|
/* min-width: 0 muss auch INNEN gelten. Die Marke ist jetzt selbst eine
|
|
Flex-Zeile (Zeichen + Text); ohne diese Angabe behaelt ihr Text seine
|
|
volle Wunschbreite und die Marke schrumpft nicht mehr -- der
|
|
Abmelden-Knopf stand dadurch auf dem Handy 9 px aus dem Bild.
|
|
Derselbe Fehler wie im August, eine Ebene tiefer. */
|
|
min-width: 0;
|
|
}
|
|
/* flex: 0 1 auto, NICHT 1 1 auto. Mit flex-grow: 1 zog sich der
|
|
Schriftzug ueber die ganze Leiste -- unsichtbar, solange er nur Text
|
|
war, aber seit er einen Rahmen traegt (die Pille), lief der Rahmen
|
|
quer durch das ganze Bild, obwohl der Text kurz ist. Schrumpfen darf
|
|
er weiterhin (das braucht die Kuerzung auf dem Handy), wachsen nicht. */
|
|
.kopfleiste .marke__text { min-width: 0; flex: 0 1 auto; }
|
|
.kopfleiste .marke::before {
|
|
content: "";
|
|
flex: none; width: 22px; height: 22px;
|
|
background: linear-gradient(150deg, var(--akzent), var(--violett));
|
|
-webkit-mask: url("../img/marke-husky.webp") center / contain no-repeat;
|
|
mask: url("../img/marke-husky.webp") center / contain no-repeat;
|
|
transition: filter var(--tempo);
|
|
}
|
|
.kopfleiste:hover .marke::before { filter: brightness(1.25); }
|
|
|
|
/* KEIN Farbverlauf IM Text.
|
|
|
|
Ich hatte das zuerst gebaut (background-clip: text mit durchsichtiger
|
|
Schrift) -- es sah gut aus, und der eigene Kontrasttest schlug sofort
|
|
Alarm: 1,05:1. Zu Recht. Durchsichtige Schrift ist auf eine einzige
|
|
Technik angewiesen; faellt sie aus (Kontrastmodus des Betriebssystems,
|
|
Druck, aeltere Browser), ist der Text UNSICHTBAR statt nur anders
|
|
gefaerbt. Das ist kein Schoenheitsfehler, das ist ein Ausfall.
|
|
|
|
Stattdessen: feste Farbe, ein Hauch Leuchten. Sieht fast gleich aus
|
|
und kann nicht verschwinden. */
|
|
.kopfleiste .marke__text {
|
|
color: #a8dbfb;
|
|
text-shadow: 0 0 14px rgba(63, 189, 245, .28);
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
display: flex; align-items: center; gap: 9px;
|
|
}
|
|
|
|
/* Der Rang im Schriftzug (aufgeteilt von kopf.js).
|
|
|
|
Vorher war alles gleich laut. Jetzt trägt der vordere Teil den Namen
|
|
und steht kräftig; was dahinter kommt, sagt nur, wo man gerade ist,
|
|
und tritt zurück. Beide bleiben eigenständig lesbar -- der leise Teil
|
|
liegt bei 5,2:1 und damit deutlich über der Norm. */
|
|
.kopfleiste .marke__haupt {
|
|
color: #dcecfb;
|
|
font-weight: 700;
|
|
text-shadow: 0 0 16px rgba(63, 189, 245, .34);
|
|
}
|
|
.kopfleiste .marke__leise {
|
|
color: #86b4d6;
|
|
font-weight: 500;
|
|
text-shadow: none;
|
|
}
|
|
.kopfleiste a.marke__haupt { text-decoration: none; }
|
|
.kopfleiste a.marke__haupt:hover { color: #fff; }
|
|
|
|
/* Der Trenner ist kein Satzzeichen mehr, sondern eine kleine, auf die
|
|
Spitze gestellte Raute in der Hausfarbe -- dieselbe Form wie die
|
|
Ecken der Bühne. Ein Punkt zwischen zwei Wörtern liest sich wie ein
|
|
Tippfehler; eine Raute liest sich als Gestaltung. */
|
|
.kopfleiste .marke__raute {
|
|
flex: none;
|
|
width: 5px; height: 5px;
|
|
transform: rotate(45deg);
|
|
border-radius: 1px;
|
|
background: var(--akzent);
|
|
box-shadow: 0 0 9px rgba(63, 189, 245, .65);
|
|
opacity: .85;
|
|
}
|
|
|
|
/* Das Zeichen davor bekommt einen eigenen Träger: runder Rahmen, ein
|
|
Hauch Fläche, weicher Schein. Aus einer aufgeklebten Form wird damit
|
|
ein Wappen. */
|
|
.kopfleiste .marke::before {
|
|
padding: 0;
|
|
filter: drop-shadow(0 0 7px rgba(63, 189, 245, .45));
|
|
}
|
|
.kopfleiste .marke {
|
|
/* Nur so breit wie ihr Inhalt -- sonst waere die Pille eine Leiste. */
|
|
flex: 0 1 auto;
|
|
padding: 4px 13px 4px 5px;
|
|
border-radius: 999px;
|
|
border: 1px solid transparent;
|
|
transition: border-color var(--tempo), background var(--tempo);
|
|
}
|
|
.kopfleiste .marke:hover {
|
|
border-color: color-mix(in srgb, var(--akzent) 26%, transparent);
|
|
background: rgba(255, 255, 255, .035);
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.kopfleiste .marke { transition: none; }
|
|
}
|
|
/* Im Kontrastmodus gibt es keine Farbverläufe und keine Schatten -- dort
|
|
muss der Rang über die Schriftstärke allein tragen. */
|
|
@media (forced-colors: active) {
|
|
.kopfleiste .marke__raute { background: CanvasText; }
|
|
.kopfleiste .marke__haupt, .kopfleiste .marke__leise { color: CanvasText; }
|
|
}
|
|
|
|
/* ---------- Wer angemeldet ist ------------------------------------------
|
|
|
|
Vorher stand da "Dogfather · DogFather" -- Name und Rolle lasen sich
|
|
gleich und es sah nach einem Fehler aus. Jetzt: ein Zeichen mit dem
|
|
Anfangsbuchstaben, der Name, und die Rolle als eigene Marke in ihrer
|
|
Farbe. Drei verschiedene Dinge sehen jetzt auch verschieden aus. */
|
|
.wer {
|
|
display: flex; align-items: center; gap: 9px;
|
|
max-width: none; overflow: visible;
|
|
}
|
|
.wer__zeichen {
|
|
flex: none;
|
|
display: grid; place-items: center;
|
|
width: 28px; height: 28px; border-radius: 9px;
|
|
font-size: .8rem; font-weight: 700; color: #eaf3ff;
|
|
background: linear-gradient(150deg,
|
|
color-mix(in srgb, var(--rollen-ton) 62%, transparent),
|
|
color-mix(in srgb, var(--rollen-ton) 24%, transparent));
|
|
border: 1px solid color-mix(in srgb, var(--rollen-ton) 55%, transparent);
|
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16);
|
|
}
|
|
.wer__name {
|
|
font-size: .88rem; font-weight: 600; color: var(--text);
|
|
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
min-width: 0;
|
|
}
|
|
.wer__rolle {
|
|
flex: none;
|
|
padding: 2px 9px; border-radius: 999px;
|
|
font-size: .66rem; font-weight: 700;
|
|
letter-spacing: .08em; text-transform: uppercase;
|
|
color: color-mix(in srgb, var(--rollen-ton) 75%, #ffffff);
|
|
background: color-mix(in srgb, var(--rollen-ton) 15%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--rollen-ton) 38%, transparent);
|
|
}
|
|
/* Eine Farbe je Rolle -- dieselbe Sprache wie in der Personenliste. */
|
|
.wer[data-rolle="admin"] { --rollen-ton: #e8c07d; }
|
|
.wer[data-rolle="manager"] { --rollen-ton: #9085e9; }
|
|
.wer[data-rolle="scout"] { --rollen-ton: #4fc38f; }
|
|
.wer[data-rolle="creator"] { --rollen-ton: #3fbdf5; }
|
|
|
|
/* Auf dem Handy faellt die Rollen-Marke weg und der Name darf schrumpfen.
|
|
Ohne das schob die neue Kennung die Kopfleiste um 8 px aus dem Bild --
|
|
gemessen, nicht vermutet: Der Pruefflauf zaehlt den waagerechten
|
|
Ueberstand auf jeder Seite mit.
|
|
|
|
Die Rolle wegzulassen kostet hier nichts: Wer angemeldet ist, weiss,
|
|
welche Rolle er hat -- und auf der Startseite steht sie zwei Zeilen
|
|
tiefer noch einmal ausgeschrieben. */
|
|
@media (max-width: 620px) {
|
|
.wer__rolle { display: none; }
|
|
.wer { min-width: 0; gap: 7px; }
|
|
.wer__name { max-width: 34vw; }
|
|
|
|
/* Auf dem Handy bleibt vom Markenzug nur der Kopf stehen. Gemessen:
|
|
Marke 209 px + rechte Gruppe 139 px + Polsterung passten nicht in
|
|
390 px, der Abmelden-Knopf stand 9 px aus dem Bild. Schrumpfen
|
|
allein reichte nicht.
|
|
|
|
Der Text kostet hier nichts: Er steht auf jeder Seite zwei Zeilen
|
|
tiefer noch einmal als Ueberschrift. Der Kopf dagegen sagt in 22 px,
|
|
wo man ist -- und bleibt.
|
|
|
|
Vorlesende Programme verlieren nichts: Der Text bleibt im Dokument
|
|
und wird nur unsichtbar gerechnet. */
|
|
.kopfleiste .marke__text {
|
|
position: absolute; width: 1px; height: 1px;
|
|
margin: -1px; padding: 0; overflow: hidden;
|
|
clip-path: inset(50%); white-space: nowrap;
|
|
}
|
|
.kopfleiste .marke { flex: none; }
|
|
}
|
|
|
|
/* ---------- Die Begrüßung ------------------------------------------------
|
|
|
|
Aus drei gestapelten Zeilen wird ein Kopf: ein leuchtender Strich, die
|
|
Zeile "ANGEMELDET" daneben, darunter der Gruß mit einem sehr sanften
|
|
Verlauf. Kein zusätzliches Element -- der Strich ist ein
|
|
Pseudo-Element der Marke. */
|
|
.willkommen .marke {
|
|
display: flex; align-items: center; gap: 10px;
|
|
margin-bottom: 10px;
|
|
}
|
|
.willkommen .marke::before {
|
|
content: "";
|
|
width: 26px; height: 2px; border-radius: 2px;
|
|
background: linear-gradient(90deg, var(--akzent), transparent);
|
|
}
|
|
.willkommen .titel {
|
|
font-size: clamp(1.9rem, 3.4vw, 2.6rem);
|
|
letter-spacing: -.025em;
|
|
/* Auch hier bewusst eine feste Farbe statt eines Verlaufs im Text --
|
|
siehe die Begruendung bei .marke__text. Die Wirkung kommt aus
|
|
Groesse, engerem Satz und dem Leuchten, nicht aus einem Kniff, der
|
|
im Kontrastmodus zu unsichtbarer Schrift wird. */
|
|
color: #f2f7fd;
|
|
text-shadow: 0 2px 26px rgba(63, 189, 245, .18);
|
|
}
|
|
.willkommen .unterzeile { margin-bottom: 0; }
|
|
|
|
/* Datumszeile: Tag, Datum und Kalenderwoche. Die Ziffern in gleicher
|
|
Zeichenbreite, damit die Zeile über die Tage hinweg ruhig bleibt. */
|
|
.willkommen__datum { font-variant-numeric: tabular-nums; }
|
|
|
|
/* Das kleine Wort zum Tag ("Neue Woche", "Endspurt", "Wochenende").
|
|
Steht nur an Tagen, die wirklich einen Charakter haben -- ein Wort,
|
|
das jeden Tag dasteht, liest nach drei Tagen niemand mehr. */
|
|
.willkommen__marker {
|
|
margin-left: 10px; padding: 3px 9px;
|
|
border: 1px solid color-mix(in srgb, var(--akzent) 32%, transparent);
|
|
border-radius: 999px;
|
|
background: color-mix(in srgb, var(--akzent) 12%, transparent);
|
|
color: var(--akzent);
|
|
font-size: .68rem; letter-spacing: .1em;
|
|
}
|
|
.willkommen__marker[hidden] { display: none; }
|
|
|
|
/* Der Gruß in zwei Stimmen: das Grußwort leiser, der Name kräftig.
|
|
Man liest den eigenen Namen, nicht die Höflichkeitsfloskel. */
|
|
.gruss__wort { color: #c3d2e4; font-weight: 600; }
|
|
.gruss__name { color: #f2f7fd; }
|
|
|
|
/* Plakette und Text nebeneinander. Die Plakette ist der einzige runde
|
|
Körper auf der Seite -- dadurch ist sofort klar, dass sie zu einer
|
|
PERSON gehört und nicht zu einem Bereich. */
|
|
.willkommen__reihe { display: flex; align-items: center; gap: 18px; }
|
|
.willkommen__text { min-width: 0; }
|
|
|
|
.willkommen__plakette {
|
|
--rolle-ton: var(--akzent);
|
|
flex: none;
|
|
display: grid; place-items: center;
|
|
width: 58px; height: 58px; border-radius: 50%;
|
|
font-size: 1.6rem; font-weight: 700; line-height: 1;
|
|
color: #f2f7fd;
|
|
border: 1px solid color-mix(in srgb, var(--rolle-ton) 42%, transparent);
|
|
background:
|
|
radial-gradient(120% 120% at 30% 20%,
|
|
color-mix(in srgb, var(--rolle-ton) 34%, transparent), transparent 70%),
|
|
rgba(255, 255, 255, .045);
|
|
box-shadow:
|
|
inset 0 1px 0 rgba(255, 255, 255, .1),
|
|
0 10px 26px -12px color-mix(in srgb, var(--rolle-ton) 60%, transparent);
|
|
}
|
|
/* Dieselben vier Rollentöne wie im Kopf der Seite und auf der
|
|
Zugangsseite -- eine Rolle hat überall dieselbe Farbe. */
|
|
.willkommen__plakette[data-rolle="admin"] { --rolle-ton: #d8a13a; }
|
|
.willkommen__plakette[data-rolle="manager"] { --rolle-ton: #8a76ff; }
|
|
.willkommen__plakette[data-rolle="scout"] { --rolle-ton: #12a69b; }
|
|
.willkommen__plakette[data-rolle="creator"] { --rolle-ton: #3fbdf5; }
|
|
|
|
/* Die Lage in einem Satz, abgesetzt hinter der Rolle. Auf dem Handy
|
|
rutscht sie in die zweite Zeile, statt den Text zu quetschen. */
|
|
.willkommen .unterzeile { display: flex; flex-wrap: wrap; gap: 6px 12px; }
|
|
.willkommen__lage { position: relative; padding-left: 14px; color: var(--text-leise); }
|
|
.willkommen__lage::before {
|
|
content: ""; position: absolute; left: 0; top: 50%;
|
|
width: 5px; height: 5px; margin-top: -2.5px; border-radius: 50%;
|
|
background: currentColor; opacity: .55;
|
|
}
|
|
.willkommen__lage[data-stufe="warnung"] { color: var(--warn); }
|
|
.willkommen__lage[hidden] { display: none; }
|
|
|
|
@media (max-width: 560px) {
|
|
.willkommen__plakette { width: 46px; height: 46px; font-size: 1.25rem; }
|
|
.willkommen__reihe { gap: 13px; }
|
|
}
|
|
|
|
/* Die Trennlinie unter der Begrüßung. Läuft nach rechts aus, statt hart
|
|
abzubrechen -- eine durchgezogene Linie zerschneidet die Seite. */
|
|
.willkommen {
|
|
padding-bottom: 22px; margin-bottom: 30px;
|
|
border-bottom: 1px solid transparent;
|
|
border-image: linear-gradient(90deg, var(--rand-hell), transparent 62%) 1;
|
|
}
|
|
|
|
/* ---------- Abschnittsschilder ------------------------------------------
|
|
"WAS IST DRAN" und "DEINE AUFGABEN" bekommen denselben leuchtenden
|
|
Strich wie die Begrüßung -- so gehört sichtbar zusammen, was
|
|
zusammengehört. */
|
|
.dran .feldschild,
|
|
.zahlen-block .feldschild {
|
|
display: flex; align-items: center; gap: 9px;
|
|
}
|
|
.dran .feldschild::before,
|
|
.zahlen-block .feldschild::before {
|
|
content: "";
|
|
width: 18px; height: 2px; border-radius: 2px;
|
|
background: linear-gradient(90deg, var(--akzent), transparent);
|
|
opacity: .8;
|
|
}
|
|
|
|
/* =====================================================================
|
|
LESEZONEN — Text auf einem hellen Bild
|
|
|
|
Seit die Buehnen wirklich hell sind, reicht "dunkler Text auf dunklem
|
|
Grund" nicht mehr: Wo kein Kasten liegt, steht Schrift direkt auf dem
|
|
Bild. Die Kontrastmessung an echten Bildpunkten hat das sofort
|
|
gemeldet -- 1,08:1 an einer hellen Stelle. Unlesbar.
|
|
|
|
Die billige Loesung waere, das Bild wieder abzudunkeln. Damit waere
|
|
man aber wieder da, wo man angefangen hat.
|
|
|
|
Die richtige: Der Untergrund wird NUR DORT abgedunkelt, wo Text
|
|
steht -- und zwar mit backdrop-filter. Der Hintergrund bleibt in
|
|
Farbe und Form sichtbar, wird an dieser Stelle aber weichgezeichnet
|
|
und gedimmt. Das ist dieselbe Technik, die hochwertige Oberflaechen
|
|
fuer ihre Leisten benutzen: Man sieht, dass da etwas ist, aber es
|
|
stoert nicht mehr.
|
|
|
|
Faellt backdrop-filter aus (aeltere Browser), traegt der Verlauf
|
|
darunter die Lesbarkeit allein -- deshalb steht er da und ist nicht
|
|
nur Beiwerk.
|
|
===================================================================== */
|
|
|
|
body.start .willkommen,
|
|
body.start .kopf-zeile,
|
|
body.start .k-kopf {
|
|
padding: 20px 24px;
|
|
border-radius: var(--radius);
|
|
background: linear-gradient(180deg, rgba(6, 9, 16, .74), rgba(6, 9, 16, .58));
|
|
backdrop-filter: blur(14px) saturate(.9);
|
|
-webkit-backdrop-filter: blur(14px) saturate(.9);
|
|
}
|
|
/* Die Trennlinie darunter war fuer eine Zeile ohne Flaeche gedacht.
|
|
Auf einer eigenen Flaeche waere sie eine Kante zu viel. */
|
|
body.start .willkommen { border-bottom: 0; margin-bottom: 26px; }
|
|
body.start .kopf-zeile,
|
|
body.start .k-kopf { border-bottom: 0; }
|
|
|
|
/* Die Gruppenueberschriften auf der Startseite stehen frei zwischen den
|
|
Kacheln. Sie bekommen keinen Kasten (das waeren drei weitere Kaesten),
|
|
sondern nur einen schmalen, weich auslaufenden Traeger. */
|
|
body.start .gruppe__kopf {
|
|
position: relative;
|
|
padding: 7px 14px;
|
|
margin-left: -14px;
|
|
border-radius: 999px;
|
|
width: fit-content; max-width: 100%;
|
|
background: linear-gradient(90deg, rgba(6, 9, 16, .72), rgba(6, 9, 16, .3) 82%, transparent);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
}
|
|
|
|
/* Der Fusstext und freistehende Hinweise brauchen dasselbe. */
|
|
body.start .inhalt .fuss,
|
|
body.start .leer-hinweis,
|
|
body.start .protokoll-block,
|
|
body.start .zahlen-block,
|
|
body.start .dran {
|
|
position: relative;
|
|
}
|
|
body.start .inhalt .fuss {
|
|
padding: 14px 16px;
|
|
border-radius: var(--radius-klein);
|
|
background: rgba(6, 9, 16, .6);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
}
|
|
|
|
/* Listen und Bloecke, die bisher gar keine Flaeche hatten (Protokolle,
|
|
Verlaeufe, Tabellenzeilen) -- sie liegen jetzt auf --flaeche wie
|
|
alles andere. */
|
|
body.start #protokoll,
|
|
body.start #liste > .leise,
|
|
body.start .verlauf {
|
|
border-radius: var(--radius-klein);
|
|
}
|
|
|
|
@media (max-width: 620px) {
|
|
body.start .willkommen,
|
|
body.start .kopf-zeile,
|
|
body.start .k-kopf { padding: 16px 15px; }
|
|
body.start .gruppe__kopf { margin-left: -10px; padding: 6px 11px; }
|
|
}
|
|
|
|
/* Ohne backdrop-filter (Kontrastmodus, aeltere Browser) muss der
|
|
Verlauf allein tragen -- deshalb wird er dort deckend. */
|
|
@media (forced-colors: active) {
|
|
body.start .willkommen,
|
|
body.start .kopf-zeile,
|
|
body.start .k-kopf,
|
|
body.start .gruppe__kopf { background: Canvas; }
|
|
}
|
|
|
|
/* Die letzten drei freistehenden Textstellen, die die Kontrastmessung
|
|
nach dem Aufhellen noch gefunden hat. Alle drei sind Beschriftungen
|
|
ohne eigene Flaeche -- sie bekommen dieselbe schmale Lesezone wie die
|
|
Gruppenueberschriften. */
|
|
body.start .dran .feldschild,
|
|
body.start .zahlen-block .feldschild,
|
|
body.start .protokoll-block .feldschild,
|
|
body.start .k-leiste .feldschild {
|
|
padding: 6px 13px 6px 11px;
|
|
margin-left: -11px;
|
|
border-radius: 999px;
|
|
width: fit-content; max-width: 100%;
|
|
background: linear-gradient(90deg, rgba(6, 9, 16, .74), rgba(6, 9, 16, .32) 84%, transparent);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
}
|
|
|
|
/* Das Ereignisprotokoll auf der Personenseite stand als einziges ganz
|
|
ohne Traeger da -- IP-Adressen und Zeitstempel direkt auf dem Bild. */
|
|
body.start #protokoll {
|
|
padding: 4px 14px;
|
|
border-radius: var(--radius-klein);
|
|
background: rgba(6, 9, 16, .66);
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
}
|
|
|
|
/* Auf dem Handy gibt es keinen Platz fuer Figuren neben dem Text --
|
|
dort darf die Lesespur ueber die ganze Breite gehen. Das Bild bleibt
|
|
oben und unten sichtbar, wo der Inhalt nicht steht. */
|
|
@media (max-width: 760px) {
|
|
body.start > .schleier {
|
|
background:
|
|
linear-gradient(180deg, rgba(5, 7, 13, .88) 0%, rgba(5, 7, 13, .6) 12%,
|
|
rgba(5, 7, 13, .5) 55%, rgba(5, 7, 13, .72) 100%),
|
|
radial-gradient(90% 40% at 20% 4%, rgba(63, 189, 245, .06), transparent 70%),
|
|
radial-gradient(90% 40% at 85% 98%, rgba(138, 118, 255, .07), transparent 72%);
|
|
}
|
|
}
|
|
|
|
/* =====================================================================
|
|
DAS LICHT FOLGT DEM ZEIGER — auf jeder Karte, im ganzen Workspace
|
|
|
|
Zwei Schichten in einem eingefuegten <span class="licht"> (siehe
|
|
kopf.js, dort steht auch, warum ein eigenes Element und nicht
|
|
::before am Kasten selbst):
|
|
|
|
::before der FLECK — ein weicher Schein unter dem Zeiger
|
|
::after der RAND — eine helle Stelle, die auf der KANTE
|
|
mitwandert
|
|
|
|
Der Rand ist der Teil, der es besonders macht. Er entsteht aus einem
|
|
Farbverlauf, von dem eine Maske nur den ein Pixel breiten Saum stehen
|
|
laesst: zwei Ebenen, eine ueber die Innenflaeche, eine ueber den
|
|
ganzen Kasten, und "exclude" laesst genau die Differenz uebrig — den
|
|
Rahmen. Dadurch leuchtet wirklich die Kante an der Stelle, an der der
|
|
Zeiger ist, statt eines Rechtecks, das so tut als ob.
|
|
|
|
Die Farbe kommt aus --ton, also aus der Kachelfarbe des Bereichs.
|
|
Eine Aufgabenkarte leuchtet orange, eine Kalenderkarte tuerkis.
|
|
===================================================================== */
|
|
|
|
.licht {
|
|
position: absolute; inset: 0;
|
|
border-radius: inherit;
|
|
pointer-events: none;
|
|
z-index: 0;
|
|
opacity: 0;
|
|
transition: opacity .28s ease;
|
|
}
|
|
[data-licht="an"] > .licht { opacity: 1; }
|
|
|
|
/* Der Fleck. Bewusst gross und sehr weich — ein kleiner harter Kreis
|
|
sieht nach Taschenlampe aus, ein grosser weicher nach Beleuchtung. */
|
|
.licht::before {
|
|
content: "";
|
|
position: absolute; inset: 0;
|
|
border-radius: inherit;
|
|
background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 0%),
|
|
color-mix(in srgb, var(--ton, var(--akzent)) 20%, transparent),
|
|
transparent 68%);
|
|
}
|
|
|
|
/* Der Rand. Etwas kleiner im Radius als der Fleck, dafuer kraeftiger --
|
|
so wirkt er wie eine Reflexion auf einer Kante, nicht wie ein zweiter
|
|
Schein. */
|
|
.licht::after {
|
|
content: "";
|
|
position: absolute; inset: 0;
|
|
border-radius: inherit;
|
|
padding: 1px;
|
|
background: radial-gradient(170px circle at var(--mx, 50%) var(--my, 0%),
|
|
color-mix(in srgb, var(--ton, var(--akzent)) 85%, #ffffff 15%),
|
|
color-mix(in srgb, var(--ton, var(--akzent)) 30%, transparent) 45%,
|
|
transparent 72%);
|
|
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
|
-webkit-mask-composite: xor;
|
|
mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
|
|
mask-composite: exclude;
|
|
}
|
|
|
|
/* Alles, was Licht bekommen soll, braucht einen eigenen Bezugspunkt --
|
|
sonst legt sich der Schein ueber die halbe Seite statt ueber die
|
|
Karte. Die meisten haben ihn schon; diese Zeile ist die Versicherung
|
|
fuer die uebrigen. */
|
|
.kachel, .karte, .spalte, .k-anlasskarte, .k-tag, .k-wochentag,
|
|
.dran__punkt, .zahl, .datei, .person, .eintrag, .thema,
|
|
.k-listentag, .steckbrief, .leer-hinweis, .block {
|
|
position: relative;
|
|
}
|
|
|
|
/* Inhalt ueber das Licht. Die Karten setzen ihre Kinder meist nicht
|
|
ausdruecklich; bei gleichem Stapelwert gewinnt das spaetere Element,
|
|
und .licht wird als erstes Kind eingefuegt. Fuer die Faelle, in denen
|
|
ein Kind selbst positioniert ist, hier die Zusicherung. */
|
|
.kachel__link, .kachel__text, .karte__titel, .spalte__kopf,
|
|
.k-anlasskarte__txt, .dran__link, .steckbrief__kopf { position: relative; z-index: 1; }
|
|
|
|
/* Ohne feinen Zeiger oder bei "weniger Bewegung" wird gar kein
|
|
Licht-Element eingefuegt (kopf.js). Diese Regel ist die zweite
|
|
Sicherung, falls doch eines im Dokument steht. */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.licht { display: none; }
|
|
}
|
|
@media (hover: none), (pointer: coarse) {
|
|
.licht { display: none; }
|
|
}
|
|
/* Im Kontrastmodus gibt es keine Farbverlaeufe -- ein Licht, das dort
|
|
als Flaeche erscheint, wuerde den Text verdecken. */
|
|
@media (forced-colors: active) {
|
|
.licht { display: none; }
|
|
}
|