Drei Ringe, klappbare Gruppen -- und die Calls-Seite endlich wirklich umgebaut

DU HATTEST RECHT (Bildschirmfoto 3). Beim letzten Mal habe ich an der
Calls-Seite nur das MATERIAL der Karten getauscht und die Aufstellung
gelassen. Drei Gruppen untereinander, und weil "Steht an" 27 Eintraege
hat, lagen die beiden anderen ausserhalb des Bildes -- man SAH die
Aenderung gar nicht, weil man nie so weit kam. Das war Lackieren, kein
Umbauen.

JETZT EIN BRETT AUS ZWEI SPALTEN. Die Gruppen sind eigenstaendige Tafeln
in einem Raster; "Protokoll fehlt" (kurz, dringend) und "Festgehalten"
(Archiv) liegen NEBEN der langen Liste statt darunter. `align-items:
start` ist dabei der Punkt: Ohne ihn waeren alle Tafeln so hoch wie die
hoechste, und neben der langen Liste stuenden zwei fast leere Kaesten.
Welche Tafel wo landet, entscheidet die Breite und nicht das Skript --
eine festgeschriebene Spalte waere eine Zahl, die beim naechsten Fenster
falsch ist.

Jede Tafel klappt zu, und der Zustand wird gemerkt. Vorgabe: "Festgehalten"
ist zu -- es ist das Archiv; wer die Seite oeffnet, will wissen, was
ansteht.

DIE GRUPPEN AUF DER STARTSEITE genauso. Der Kopf IST der Schalter, nicht
ein Dreieck daneben: Die ganze Zeile ist ein Ziel von 40 Pixeln statt
eines von vierzehn. <button> statt <div>, damit Tastaturbedienung und
Ansage nicht mit tabindex und role nachgebaut werden muessen. Gemerkt
wird je Gruppe UND je angesehener Rolle -- DogFather, der sich einen
Creator ansieht, hat dort eine andere Aufteilung im Kopf.

DIE UHR: drei Ringe statt zwei. Aussen die Stunde in Schwarzsilber, in
der Mitte die Minute in Blau, innen die Sekunde in Rot -- von aussen nach
innen immer schneller, so liest man eine Uhr ohne nachzudenken.

UND SIE IST SCHARF. Kein blur(), kein drop-shadow mehr auf den Boegen --
an der alten lag beides drauf, und der Vorwurf stimmte. Der Glanz kommt
jetzt aus dem VERLAUF: Echtes Metall glaenzt nicht, weil es leuchtet,
sondern weil es das Licht abwechselnd hell und dunkel zurueckwirft. Fuenf
Stopps statt zwei -- ein zweifarbiger Verlauf waere ein Farbverlauf,
erst der Wechsel ist Metall. Dazu `shape-rendering="geometricPrecision"`
(sonst rastert der Browser duenne Boegen grober) und Kappen auf `butt`
statt `round`: Eine runde Kappe steht ueber das Ende hinaus, bei null
Sekunden saehe man trotzdem einen Punkt.

Minute und Stunde laufen WEICH mit: die Minute bekommt die Sekunden
anteilig, die Stunde die Minuten. Ein Minutenring, der einmal pro Minute
springt, sieht aus wie eine haengende Anzeige.

Gruen: css-klassen (15), call-kategorien (17), start-ansicht (136),
handy (59), breiten (23), buehne (38), struktur (32).

NOCH OFFEN: der neue Kachelstil fuer die ganze Website und die Rolle
"Spicy Media".

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-07 04:39:32 +02:00
co-authored by Claude Opus 5
parent 49bd4a7cec
commit 4bb5afc942
23 changed files with 642 additions and 251 deletions
+129
View File
@@ -344,3 +344,132 @@
@media (forced-colors: active) {
.call { background: Canvas; box-shadow: none; border: 1px solid CanvasText; }
}
/* =====================================================================
DAS BRETT — zwei Spalten statt einer Liste (07.09.2026)
Filipe: "immer noch gleich aufgestellt, man kann sogar bestimmt zwei
kategorien neben einander legen ... wenn ich sage komplett aendern
dan komplett aendern."
Er hatte recht. Beim letzten Mal habe ich nur das Material der Karten
getauscht -- die Aufstellung blieb eine Spalte, in der drei Gruppen
untereinander standen. Und weil "Steht an" siebenundzwanzig Eintraege
hat, lagen die beiden anderen ausserhalb des Bildes: Man SAH die
Aenderung gar nicht, weil man nie so weit kam.
Jetzt sind die Gruppen eigenstaendige Tafeln in einem Raster. Die
kurze, dringende ("Protokoll fehlt") und das Archiv ("Festgehalten")
liegen NEBEN der langen Liste statt darunter.
`align-items: start` ist dabei der entscheidende Punkt: Ohne ihn
waeren alle Tafeln so hoch wie die hoechste, und neben der langen
Liste stuenden zwei fast leere Kaesten. So endet jede Tafel dort, wo
ihr Inhalt endet.
KEINE feste Spaltenzuweisung im Skript. Welche Tafel wo landet,
entscheidet die Breite -- eine im Skript festgeschriebene Spalte waere
eine Zahl, die beim naechsten Fenster falsch ist.
===================================================================== */
.call-brett {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
gap: 16px;
align-items: start;
}
/* Die lange Liste bekommt die erste Spalte und behaelt sie. Ohne diese
Zeile wandert sie je nach Anzahl mal links, mal rechts -- und eine
Oberflaeche, deren Aufbau sich mit dem Inhalt aendert, lernt man nie. */
.call-brett .gruppe[data-gruppe="anstehend"] { grid-row: span 2; }
.call-brett .gruppe {
margin: 0;
padding: 4px 14px 14px;
border: 1px solid rgba(150, 186, 220, .12);
border-radius: 4px 18px 18px 4px;
background:
linear-gradient(90deg,
color-mix(in srgb, var(--tafel-ton, var(--akzent)) 16%, transparent) 0%,
color-mix(in srgb, var(--tafel-ton, var(--akzent)) 5%, transparent) 12%,
transparent 34%),
linear-gradient(163deg,
rgba(21, 28, 41, .95) 0%,
rgba(11, 15, 24, .95) 62%,
rgba(8, 11, 18, .95) 100%);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, .075),
inset 0 -1px 0 rgba(0, 0, 0, .45),
0 2px 4px -2px rgba(0, 0, 0, .5),
0 14px 30px -20px rgba(0, 0, 0, .88);
overflow: hidden;
position: relative;
}
/* Jede Tafel traegt die Farbe ihres Zustands in einer Schiene links --
dieselbe Sprache wie ueberall: Bernstein wartet, Blau steht an, Gruen
ist erledigt. */
.call-brett .gruppe[data-gruppe="offen"] { --tafel-ton: #f0c48a; }
.call-brett .gruppe[data-gruppe="anstehend"] { --tafel-ton: var(--akzent); }
.call-brett .gruppe[data-gruppe="erledigt"] { --tafel-ton: #79d1a2; }
.call-brett .gruppe::before {
content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
background: linear-gradient(180deg,
color-mix(in srgb, var(--tafel-ton) 85%, transparent) 0%,
color-mix(in srgb, var(--tafel-ton) 35%, transparent) 100%);
}
/* Der Kopf ist der Schalter -- <button>, also muessen die Vorgaben des
Browsers zurueck (eigene Schrift, Rand, zentrierter Text). */
.call-brett .stufe__kopf {
appearance: none; -webkit-appearance: none;
width: 100%;
font: inherit; color: inherit; text-align: left;
border: 0; background: none; cursor: pointer;
display: flex; align-items: center; gap: 10px;
padding: 12px 2px;
border-radius: 10px;
transition: background var(--tempo);
}
.call-brett .stufe__kopf:hover { background: rgba(255, 255, 255, .04); }
.call-brett .stufe__kopf:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
.call-brett .stufe__titel { margin: 0; }
.call-brett .stufe__zahl { margin-left: auto; }
.call-brett .gruppe__pfeil {
width: 16px; height: 16px; flex: none;
color: var(--text-still);
transition: transform var(--tempo);
}
.call-brett .gruppe[data-zu="ja"] .gruppe__pfeil { transform: rotate(-90deg); }
.call-brett .gruppe[data-zu="ja"] { padding-bottom: 4px; }
.call-brett .gruppe__karten { margin-top: 0; }
/* Die Karten stehen jetzt IN einer Tafel -- sie brauchen keine zweite
schwere Flaeche, sonst liegt Kasten in Kasten. Leichter Grund, gleiche
Schiene. */
.call-brett .call {
background:
linear-gradient(90deg,
color-mix(in srgb, var(--c) 14%, transparent) 0%,
transparent 38%),
rgba(255, 255, 255, .028);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
}
.call-brett .call:hover {
transform: none;
background:
linear-gradient(90deg,
color-mix(in srgb, var(--c) 20%, transparent) 0%,
transparent 42%),
rgba(255, 255, 255, .05);
}
@media (prefers-reduced-motion: reduce) {
.call-brett .stufe__kopf, .call-brett .gruppe__pfeil { transition: none; }
}
@media (max-width: 900px) {
/* Eine Spalte -- und die Reihenspanne muss weg, sonst reisst sie in
der einspaltigen Ansicht eine leere Zeile auf. */
.call-brett .gruppe[data-gruppe="anstehend"] { grid-row: auto; }
}
@media (forced-colors: active) {
.call-brett .gruppe { background: Canvas; box-shadow: none; border: 1px solid CanvasText; }
}
+130 -39
View File
@@ -174,7 +174,7 @@
-------------------------------------------------------------------- */
.uhr {
position: relative;
width: 112px; height: 112px; flex: none;
width: 124px; height: 124px; flex: none;
display: grid; place-items: center;
border-radius: 50%;
/* SCHICHT 1: der Metallrand. Ein Verlauf von hell (oben links, wo das
@@ -213,17 +213,21 @@
sechzig Elementen mehr im Baum. Jeder fuenfte Strich ist kraeftiger
-- das ist der Unterschied zwischen "Punkte im Kreis" und "Skala". */
.uhr__skala {
position: absolute; inset: 9px; border-radius: 50%;
/* Die Skala liegt GANZ AUSSEN, jenseits des Stundenrings -- zwischen
den Ringen waere sie ein vierter Kreis und der Grund, warum das
Zifferblatt unruhig wirkt. Zwoelf kraeftige Striche fuer die
Stunden, sechzig feine dazwischen. */
position: absolute; inset: 1px; border-radius: 50%;
background:
repeating-conic-gradient(from 0deg,
rgba(255, 145, 155, .55) 0deg 1deg,
transparent 1deg 30deg),
rgba(226, 234, 244, .70) 0deg 0.8deg,
transparent 0.8deg 30deg),
repeating-conic-gradient(from 0deg,
rgba(150, 186, 220, .26) 0deg 0.5deg,
transparent 0.5deg 6deg);
-webkit-mask: radial-gradient(circle, transparent 0 74%, #000 74% 86%, transparent 86%);
mask: radial-gradient(circle, transparent 0 74%, #000 74% 86%, transparent 86%);
opacity: .65;
rgba(150, 186, 220, .22) 0deg 0.4deg,
transparent 0.4deg 6deg);
-webkit-mask: radial-gradient(circle, transparent 0 92%, #000 92% 99%, transparent 99%);
mask: radial-gradient(circle, transparent 0 92%, #000 92% 99%, transparent 99%);
opacity: .8;
pointer-events: none; z-index: 1;
}
/* SCHICHT 3: das Glas. Eine Spiegelung von oben links ueber die Kuppe,
@@ -246,38 +250,57 @@
z-index: 2;
overflow: visible;
}
.uhr__bahn, .uhr__minute, .uhr__zeiger {
fill: none; stroke-linecap: round;
stroke-dasharray: 276.46;
/* DREI RINGE, ALLE SCHARF (07.09.2026).
Filipe: "die minuten blau, [die stunden] schwarzsilber glaenzend und
die sekunden rot ... soll null unscharf sein, sehr schoen praezise."
KEIN blur(), KEIN drop-shadow auf den Boegen. Ein Weichzeichner auf
einer Linie macht sie nicht edler, sondern unscharf -- genau das war
der Vorwurf, und er stimmte: An der alten Uhr lag ein blur(1.2px) auf
dem Schein und ein drop-shadow auf dem Sekundenbogen.
Der GLANZ entsteht stattdessen aus dem Verlauf selbst. Echtes Metall
glaenzt nicht, weil es leuchtet, sondern weil es das Licht an
verschiedenen Stellen verschieden zurueckwirft: hell, dunkel, hell,
dunkel. Genau das machen die fuenf Stopps des Silberverlaufs im SVG.
Ein zweifarbiger Verlauf waere ein Farbverlauf; erst der Wechsel ist
Metall.
Die Kappen sind BUTT und nicht rund. Eine runde Kappe steht ueber das
Ende hinaus -- bei "null Sekunden" saehe man dann trotzdem einen
Punkt, und die Anzeige waere um zwei Grad falsch. Praezise heisst
auch: nichts anzeigen, wo nichts ist. */
.uhr__bahn, .uhr__stunde, .uhr__minute, .uhr__sekunde {
fill: none;
stroke-linecap: butt;
}
.uhr__bahn { stroke: rgba(150, 186, 220, .10); stroke-width: 4; }
/* Der Stundenstand: breit und gedeckt, im Verlauf Rot -> Babyblau. Er
aendert sich einmal pro Minute und darf nicht um Aufmerksamkeit
bitten -- deshalb kein Leuchten. */
.uhr__bahn { stroke: rgba(150, 186, 220, .09); stroke-width: 3; }
/* AUSSEN: die Stunde in Schwarzsilber. Am breitesten und am ruhigsten --
sie bewegt sich in fuenf Minuten um ein halbes Grad. */
.uhr__stunde {
stroke: url(#uhr-silber);
stroke-width: 3.4;
stroke-dasharray: 285.88;
stroke-dashoffset: 285.88;
}
/* MITTE: die Minute in Blau. */
.uhr__minute {
stroke: url(#uhr-lauf);
stroke-width: 4;
stroke-dashoffset: 276.46;
opacity: .72;
stroke: url(#uhr-blau);
stroke-width: 3;
stroke-dasharray: 241.90;
stroke-dashoffset: 241.90;
}
/* Die Sekunde: schmaler, heller, gegenlaeufig gefaerbt und mit einem
Hauch Leuchten. */
.uhr__zeiger {
stroke: url(#uhr-sekunde); stroke-width: 2;
stroke-dashoffset: 276.46;
filter: drop-shadow(0 0 3px rgba(168, 228, 255, .75));
}
/* Der Kopf am Ende des Sekundenbogens -- ein Punkt, der mitlaeuft.
Das ist die eine Stelle, an der sich sichtbar etwas BEWEGT, und
deshalb die, an der das Auge merkt, dass die Seite lebt. */
.uhr__kopf-schein {
fill: rgba(168, 228, 255, .28);
filter: blur(1.2px);
}
.uhr__kopf-kern {
fill: #eaf7ff;
filter: drop-shadow(0 0 4px rgba(168, 228, 255, .95));
/* INNEN: die Sekunde in Rot. Am duennsten -- sie laeuft am schnellsten,
und eine schnelle dicke Linie wird unruhig. */
.uhr__sekunde {
stroke: url(#uhr-rot);
stroke-width: 2.4;
stroke-dasharray: 197.92;
stroke-dashoffset: 197.92;
}
.uhr__mitte {
position: relative; z-index: 4;
display: grid; justify-items: center; gap: 2px; line-height: 1;
@@ -331,7 +354,7 @@
keine Zeile mehr übrig. */
.willkommen { padding: 18px 16px; }
.willkommen__rechts { margin-left: 0; width: 100%; justify-content: flex-start; }
.uhr { width: 88px; height: 88px; }
.uhr { width: 96px; height: 96px; }
.uhr__zeit { font-size: 1.18rem; }
}
@@ -339,9 +362,77 @@
/* Die Uhr springt ohnehin -- hier gibt es nichts abzuschalten. Die
Zeile steht trotzdem da, damit der nächste, der einen weichen
Zeiger einbaut, sie findet. */
.uhr__zeiger, .uhr__minute { transition: none; }
.uhr__stunde, .uhr__minute, .uhr__sekunde { transition: none; }
}
@media (forced-colors: active) {
.uhr { background: Canvas; box-shadow: none; border: 1px solid CanvasText; }
.uhr__skala, .uhr__glas { display: none; }
}
/* =====================================================================
GRUPPEN LASSEN SICH ZUKLAPPEN (07.09.2026)
Wunsch Filipe: "diese kategorien soll man auch zu und aufmachen
koennen so wie es einem lieb ist gerade."
DIE UEBERSCHRIFT IST DER SCHALTER. Ein kleines Dreieck daneben waere
ein Ziel von 14 Pixeln; die ganze Zeile ist eines von 40. Deshalb ist
der Kopf ein <button> und nicht ein <div> mit einem Knopf darin --
damit kommt auch die Tastaturbedienung geschenkt.
Ein Knopf bringt allerdings die Vorgaben des Browsers mit (eigene
Schrift, eigener Rand, zentrierter Text). Die muessen alle
zurueckgesetzt werden, sonst sieht die Ueberschrift wie eine
Schaltflaeche aus -- und genau das soll sie NICHT: Sie soll aussehen
wie vorher und sich nur anders anfuehlen.
===================================================================== */
.gruppe__kopf {
/* Alles, was ein <button> mitbringt, wieder aus. */
appearance: none; -webkit-appearance: none;
width: 100%;
font: inherit; color: inherit; text-align: left;
border: 0; background: none;
cursor: pointer;
/* Und der Aufbau von vorher. */
position: relative;
display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
margin-bottom: 14px; padding: 6px 4px 10px;
border-radius: 10px;
transition: background var(--tempo);
}
.gruppe__kopf:hover { background: rgba(255, 255, 255, .035); }
.gruppe__kopf:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
/* Die Zahl sagt, was hinter einer zugeklappten Gruppe steckt. Sie steht
ganz rechts, direkt vor dem Pfeil -- dort sucht man sie. */
.gruppe__zahl {
margin-left: auto;
min-width: 22px; padding: 1px 8px;
border-radius: 999px;
background: rgba(255, 255, 255, .06);
color: var(--text-still);
font-size: .74rem; font-weight: 700;
font-variant-numeric: tabular-nums;
text-align: center;
}
.gruppe__pfeil {
width: 16px; height: 16px; flex: none;
color: var(--text-still);
transition: transform var(--tempo), color var(--tempo);
}
.gruppe__kopf:hover .gruppe__pfeil { color: var(--text); }
/* Zugeklappt zeigt der Pfeil nach rechts -- die Richtung, in die es
geht, wenn man drueckt. */
.gruppe[data-zu="ja"] .gruppe__pfeil { transform: rotate(-90deg); }
/* Eine zugeklappte Gruppe rueckt zusammen: Der Abstand, den die Kacheln
gebraucht haben, gehoert ihnen und nicht der Ueberschrift. */
.gruppe[data-zu="ja"] { margin-bottom: 10px; }
.gruppe[data-zu="ja"] .gruppe__kopf { margin-bottom: 0; }
@media (prefers-reduced-motion: reduce) {
.gruppe__kopf, .gruppe__pfeil { transition: none; }
}
@media (forced-colors: active) {
.gruppe__kopf { border: 1px solid CanvasText; }
}