Die Zeitraeume bekommen eine Tafel -- und die Zahl, die fehlte

Filipe: "das muss viel geiler aussehen bitte. ich will dass es auch
seeeehr gut erkennbar ist, genau wie der text drueber. mach das bitte
alles so dass es mega speziell, hochwertig und lesbar ist."

DAS EIGENTLICHE PROBLEM WAR LESBARKEIT, nicht Geschmack. Im
Bildschirmfoto gemessen: Ueberschrift und Erklaersatz standen direkt
auf der Buehne -- einem Foto mit hellrotem Berg. Und die Karte griff
nach `--flaeche-tief`, einer Variablen, die es im ganzen Haus nicht
gibt; gegriffen hat der Ersatzwert mit 72 % Deckung, also kam der Berg
mit. Eine Variable, die nirgends steht, faellt nicht auf.

Jetzt sitzt alles in EINEM Koerper: vierfarbige Fassung, deckendes
Innenglas mit Messraster, die Zeitraeume als eingelassene Felder mit
dunklen Fugen. Das ist nicht neu erfunden, sondern die Rollenkachel der
Anmeldeseite -- ein Haus, eine Handschrift. Typenschild und Hauptzahl
in gebuerstetem Metall, mit vollwertigem Rueckfall.

"GUELTIGE LIVE-GEHEN-TAGE" WURDE BIS HEUTE WEGGEWORFEN. Datenbank,
Anzeigefeld und Importzeile waren da -- nur `spaltenRaten` hatte kein
Muster dafuer. Am 14.09. wurde das alte `/tag/` reparirt, das die
Spalte faelschlich zur Datumsspalte machte; die Reparatur hat den
falschen Empfaenger entfernt und keinen richtigen bestellt. Die
Pruefdatei SCHICKTE den Wert seit dem 14.09. und hat nie nachgesehen,
ob er ankommt. Jetzt steht er als Streifen da, in genau so viele
Kaestchen geteilt, wie der Zeitraum Tage hat.

ZWEI KLASSEN IM WAEHLER, mit Grund: `.spannen__schild` allein (0,1,0)
kam gegen `.inhalt .feldschild` aus start.css (0,2,0) nicht an -- im
Browser gemessen war weder `display: flex` noch die Farbe da.

UND EINE ZEITBOMBE ENTSCHAERFT: pruef-backstage-import rechnete
"morgen" mit `toISOString()` (UTC), der Server mit Ortszeit. Um 00:40
Berlin war das hier berechnete "morgen" in Wahrheit HEUTE -- die
Gegenprobe "ein Datum in der Zukunft wird abgelehnt" fiel taeglich
zwischen Mitternacht und zwei Uhr um. Alle drei Tage werden jetzt aus
einer Stelle abgeleitet.

Gemessen statt behauptet: 43 258 Bildpunkte hinter Ueberschrift und
Satz abgetastet, kein einziger rot. Gegenprobe mit weggenommenem
Innenglas: 2 857 rote -- die Messung kann Rot also sehen.

pruef-backstage-import 133 (war 127), pruef-xlsx 75 (war 67),
pruef-css-klassen, pruef-leistung-optik 59, pruef-leistung: alle gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-16 00:59:51 +02:00
co-authored by Claude Opus 5
parent 04f87603f6
commit 984f0dd7a9
35 changed files with 929 additions and 424 deletions
+310 -50
View File
@@ -432,56 +432,218 @@
.dialog--breit .neu { max-height: min(86vh, 900px); overflow-y: auto; }
/* =====================================================================
ZEITRÄUME AUS BACKSTAGE — zweite Fassung (14.09.2026)
ZEITRÄUME AUS BACKSTAGE — dritte Fassung (16.09.2026)
Filipe zur ersten: "das muss viel geiler aussehen und viel klarer."
Filipe: "das muss viel geiler aussehen bitte. ich will dass es auch
seeeehr gut erkennbar ist, genau wie der text drüber. mach das bitte
alles so dass es mega speziell, hochwertig und lesbar ist. mach was
richtig krass geiles."
Er hatte recht. Die erste Fassung war eine Liste kleiner Werte ohne
Rangfolge: Spanne, Diamanten, LIVE, Follower -- alles gleich groß,
nichts sprang heraus. Wer draufschaut, will ZWEI Dinge in einer
halben Sekunde wissen: WELCHER Zeitraum und WIE VIELE Diamanten.
Genau die sind jetzt groß, alles andere ordnet sich darunter.
---------------------------------------------------------------------
WAS WIRKLICH NICHT STIMMTE — im Bildschirmfoto gemessen, nicht geraten
DER RAHMEN IST BEWUSST ANDERS ALS BEI DEN WOCHENKARTEN. Wer einen
Zeitraum für einen Tageswert hält, rechnet mit ihm weiter -- die
Karte muss auf den ersten Blick sagen, dass sie etwas anderes ist.
Deshalb: eigene Farbe an der Kante, die Spanne als Überschrift, die
Zahl der Tage als Marke daneben.
Die zweite Fassung hatte eine ordentliche Rangfolge. Ihr Fehler lag
woanders, und er war ein LESBARKEITSFEHLER:
1. ÜBERSCHRIFT UND SATZ STANDEN AUF DEM FOTO. Hinter dem Inhalt
dieser Seite liegt die Bühne — ein Bild mit einem hellroten
Berg. "ZEITRÄUME AUS BACKSTAGE" stand in `--text-still`
(#7f8fa6) mitten darin, der Erklärsatz daneben. Genau davon
redet er mit "seeeehr gut erkennbar".
2. DIE KARTE WAR DURCHSICHTIG. Sie griff nach `--flaeche-tief` —
eine Variable, die es IM GANZEN HAUS NICHT GIBT. Gegriffen hat
also der Ersatzwert `rgba(10,16,24,.72)`, und durch die
fehlenden 28 % kam der Berg mit. Eine Variable, die nirgends
steht, fällt nicht auf: Sie wird still durch etwas Schlechteres
ersetzt.
3. SIE STAND ALLEIN IN EINER REIHE FÜR VIER. `auto-fill` hält
leere Spalten offen; neben der einen Karte lagen 800 px blankes
Foto.
---------------------------------------------------------------------
DIE ANTWORT IST KEINE NEUE FARBE, SONDERN EIN KÖRPER
Überschrift, Satz und Zeiträume sitzen ab jetzt IN EINER TAFEL:
Fassung außen, deckendes Innenglas darin, die Zeiträume als
eingelassene Felder. Damit steht jede Zeile auf einem bekannten
Grund — der Kontrast ist eine feste Zahl statt einer Frage an das
Hintergrundbild.
DIE BAUART IST NICHT NEU ERFUNDEN. Es ist die Rollenkachel der
Anmeldeseite (`.rollen` in gate.css): vierfarbige Fassung in den
Hausfarben, Innenglas mit dem feinen Messraster, dunkle Fugen
zwischen den Feldern. Ein Haus, eine Handschrift.
WARUM NICHT DIE MODULLISTE AUS module.css? Die gibt jeder Karte EINE
abgeschnittene Ecke und ein Kantenlicht. Bei fünf Zeiträumen wären
das fünf Silhouetten nebeneinander — wieder eine Liste. Hier ist es
EINE Sache mit mehreren Einträgen, also EIN Körper. Dieselbe
Entscheidung wie damals bei den fünf Rollen.
AUGENSCHONEND BLEIBT ES: Die Fassung ist 2 px breit, das Raster
liegt bei 5 % Deckkraft, die hellste Fläche im Glas ist #0b111c.
Nichts leuchtet, nichts blinkt, nichts bewegt sich.
===================================================================== */
.leistung-spannen { margin: 26px 0 0; }
.spannen__satz {
margin: 4px 0 14px;
font-size: .82rem; line-height: 1.6;
color: var(--text-still);
max-width: 64ch;
.leistung-spannen { margin: 26px 0 30px; }
.spannen-tafel {
/* Die Form steht EINMAL als Variable da und wird von Fassung und
Innenglas benutzt. Zwei Abschriften desselben Polygons wären zwei
Gelegenheiten, dass die Fase auseinanderläuft. */
--sp-fase: 16px;
--sp-rand: 2px;
--sp-form: polygon(
var(--sp-fase) 0, calc(100% - var(--sp-fase)) 0,
100% var(--sp-fase), 100% calc(100% - var(--sp-fase)),
calc(100% - var(--sp-fase)) 100%, var(--sp-fase) 100%,
0 calc(100% - var(--sp-fase)), 0 var(--sp-fase));
position: relative;
padding: var(--sp-rand);
clip-path: var(--sp-form);
/* DIE FASSUNG: links Rot, rechts Babyblau, Silber als Treffpunkt,
Schwarz als Fuge — dieselben vier Farben wie am Rand der Zentrale
und an der Rollenkachel. */
background: linear-gradient(96deg,
#20060b 0%, #c8323f 6%, #ff5f6d 14%, #ffd9dd 20%,
#b3242f 30%, #0a0c12 40%, #f4faff 50%, #0a0c12 60%,
#4f95bd 70%, #8fd8ff 78%, #dff2ff 84%, #3f7fa3 92%, #06080f 100%);
box-shadow: 0 14px 30px -18px rgba(0, 0, 0, .9);
}
/* DAS INNENGLAS — und es ist DECKEND. Das ist der eigentliche
Unterschied zur zweiten Fassung: Die letzte Ebene ist ein
undurchsichtiger Verlauf, kein rgba(). Kein einziger Bildpunkt des
Fotos kommt hier durch. */
.spannen-tafel::before {
content: ""; position: absolute; inset: var(--sp-rand);
z-index: 0; pointer-events: none;
clip-path: var(--sp-form);
background:
linear-gradient(180deg, rgba(255, 255, 255, .05), transparent 34%),
repeating-linear-gradient(0deg, rgba(150, 186, 220, .05) 0 1px, transparent 1px 22px),
repeating-linear-gradient(90deg, rgba(150, 186, 220, .05) 0 1px, transparent 1px 22px),
radial-gradient(120% 80% at 12% 100%, rgba(255, 74, 92, .10), transparent 62%),
radial-gradient(110% 75% at 88% 0%, rgba(126, 200, 242, .09), transparent 60%),
linear-gradient(180deg, #0b111c, #070b13);
}
.spannen-tafel > * { position: relative; z-index: 1; }
/* ---------- Der Kopf der Tafel ---------------------------------------- */
/* Überschrift und Erklärsatz sitzen IN der Tafel, nicht darüber —
sonst wäre die Tafel eine Liste ohne Titel und der Titel ein Satz
ohne Bezug. Dieselbe Überlegung wie bei der Rollenkachel. */
.spannen-tafel__kopf {
padding: 14px 18px 14px;
border-bottom: 1px solid #05070c;
box-shadow: 0 1px 0 rgba(255, 255, 255, .045);
}
/* DAS TYPENSCHILD IN GEBÜRSTETEM METALL.
"genau wie der text drüber" — der Text drüber soll nicht nur
mithalten, er soll der Anker sein. Oben hell, in der Mitte dunkler,
unten wieder hell: erst der WECHSEL liest sich als Material, ein
Verlauf von hell nach dunkel wäre bloß eine Färbung.
DER RÜCKFALL IST VOLLWERTIG: `color` steht fest auf #e6eef8 und wird
erst in einem `@supports` durch den Verlauf ersetzt. Fällt
`background-clip: text` aus, steht dort heller Text — nicht
unsichtbarer. Der dunkelste Punkt des Verlaufs (#93a8bf) liegt auf
dem Glas (#0b111c) bei 8,8:1; gerechnet, nicht geschätzt.
ZWEI KLASSEN IM WAEHLER, UND ZWAR MIT ABSICHT (16.09.2026).
Der erste Anlauf schrieb `.spannen__schild` -- eine Klasse, Gewicht
(0,1,0). Im Browser gemessen kam davon NICHTS an: `display` stand
auf `block`, die Farbe auf `--text-leise`, das Metall war nicht da.
Schuld war `.inhalt .feldschild` in start.css, Gewicht (0,2,0) --
zwei Klassen schlagen eine, egal wer spaeter geladen wird.
Mit `.spannen-tafel .spannen__schild` sind es auch (0,2,0), und
DANN entscheidet der Ladeweg: leistung.css kommt nach start.css.
Genau davor warnt start.css an anderer Stelle selbst ("Wer eine
Flaeche neu baut, muss zuerst nachsehen, wer sie vorher beschrieben
hat -- und mit welchem Gewicht"). Der Hinweis stand da; gefunden hat
es trotzdem erst die Messung. */
.spannen-tafel .spannen__schild {
position: relative;
display: flex; align-items: center; gap: 11px;
margin: 0 0 7px;
/* Groesser als ein gewoehnliches Feldschild (.74rem): Es ist hier
nicht die Beschriftung eines Feldes, sondern der Titel der Tafel --
und Filipe will ihn "seeeehr gut erkennbar". */
font-size: .82rem;
color: #e6eef8;
letter-spacing: .1em;
}
/* Der Anschlag links: drei Kerben, oben rot, unten babyblau — dieselbe
Richtung wie die Fassung ringsum. */
.spannen-tafel .spannen__schild::before {
content: "";
width: 13px; height: 13px; flex: none;
background-image:
linear-gradient(180deg, transparent 0 46%, rgba(143, 216, 255, .95) 46%),
repeating-linear-gradient(180deg, #ff5f6d 0 2px, transparent 2px 5px);
background-blend-mode: multiply, normal;
-webkit-mask: linear-gradient(180deg, #000 0 45%, rgba(0, 0, 0, .55) 100%);
mask: linear-gradient(180deg, #000 0 45%, rgba(0, 0, 0, .55) 100%);
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
.spannen-tafel .spannen__schild {
background: linear-gradient(178deg,
#f4f9ff 0%, #dfeaf6 32%, #93a8bf 60%, #d7e6f5 86%, #f4f9ff 100%) text;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
/* Der Anschlag ist ein ::before und würde vom `background-clip: text`
der Elternregel mit ausgeschnitten — er hat keinen Text, also
bliebe nichts übrig. Er bekommt deshalb seine eigene Ansage. */
.spannen-tafel .spannen__schild::before {
-webkit-background-clip: border-box; background-clip: border-box;
}
}
/* Der Erklärsatz. Er stand in `--text-still` (#7f8fa6) auf einem Foto.
Jetzt in `--text-leise` auf dem deckenden Glas. */
.spannen__satz {
margin: 0;
font-size: .82rem; line-height: 1.6;
color: var(--text-leise);
max-width: 72ch;
}
/* ---------- Die Zeiträume als eingelassene Felder --------------------- */
/* DIE FUGE MACHT DIE TAFEL. Nicht der Rand außen — der ist Fassung —,
sondern die dunkle Linie ZWISCHEN den Feldern. Ein Spalt, durch den
der Untergrund scheint, trennt; eine dunkle Fuge verbindet, weil sie
zum selben Körper gehört. Deshalb `#05070c` und nicht `transparent`.
`auto-fit` STATT `auto-fill` (16.09.2026): Bei EINEM Zeitraum hielt
`auto-fill` drei leere Spalten offen, und daneben lag blankes Foto.
`auto-fit` lässt die leeren Spuren zusammenfallen — ein Zeitraum
füllt die Breite, vier teilen sie sich. */
.spannen {
display: grid; gap: 12px;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
display: grid; gap: 1px;
background: #05070c;
grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}
.spanne {
position: relative; overflow: hidden;
border: 1px solid var(--rand); border-radius: 16px;
padding: 14px 16px 15px;
position: relative;
padding: 15px 18px 16px;
background:
linear-gradient(180deg, rgba(255, 255, 255, .045), rgba(255, 255, 255, .012)),
var(--flaeche-tief, rgba(10, 16, 24, .72));
}
/* Die Kante links: ein Streifen in der Hausfarbe. Er sagt "andere
Sorte Zahl", ohne dass ein einziges Wort dafür nötig wäre. */
.spanne::before {
content: ""; position: absolute; inset: 0 auto 0 0;
width: 3px;
background: linear-gradient(180deg,
color-mix(in srgb, var(--akzent) 75%, transparent),
color-mix(in srgb, var(--akzent) 15%, transparent));
linear-gradient(180deg, rgba(255, 255, 255, .028), transparent 42%),
#0a1018;
}
.spanne__kopf {
display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
padding-bottom: 10px; margin-bottom: 11px;
border-bottom: 1px solid var(--rand);
padding-bottom: 10px; margin-bottom: 12px;
border-bottom: 1px solid rgba(150, 186, 220, .13);
}
.spanne__spanne {
display: inline-flex; align-items: baseline; gap: 5px;
@@ -490,28 +652,39 @@
}
.spanne__strich { color: var(--text-still); font-weight: 400; }
.spanne__tage {
font-size: .73rem; color: var(--text-leise);
border: 1px solid color-mix(in srgb, var(--akzent) 30%, var(--rand));
background: color-mix(in srgb, var(--akzent) 10%, transparent);
font-size: .73rem; color: #cfe4f4;
border: 1px solid color-mix(in srgb, var(--akzent) 42%, transparent);
background: color-mix(in srgb, var(--akzent) 14%, transparent);
border-radius: 999px;
padding: 2px 9px 3px;
white-space: nowrap;
}
/* Die Hauptzahl. Groß, aber nicht grell -- sie soll die erste sein,
die man liest, nicht die einzige, die man sieht. */
/* Die Hauptzahl. Groß, aber nicht grell — sie soll die erste sein, die
man liest, nicht die einzige, die man sieht. Dasselbe gebürstete
Metall wie das Typenschild: Die Tafel hat damit ZWEI Anker, oben und
in der Mitte, und beide sprechen dieselbe Sprache. */
.spanne__haupt {
display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 9px;
margin-bottom: 12px;
}
.spanne__haupt-zahl {
font-size: 1.85rem; font-weight: 700; line-height: 1.05;
font-size: 2.05rem; font-weight: 700; line-height: 1.05;
color: var(--text);
font-variant-numeric: tabular-nums;
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
.spanne__haupt-zahl {
background: linear-gradient(176deg,
#f4f9ff 0%, #dbe7f4 38%, #9fb3c9 72%, #e4eef9 100%) text;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
}
.spanne__haupt-name {
font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
color: var(--text-still);
color: var(--text-leise);
}
/* Der Durchschnitt steht in derselben Zeile und deutlich kleiner:
Er ist eine Einordnung, kein zweiter Messwert. */
@@ -521,23 +694,110 @@
font-variant-numeric: tabular-nums;
}
.spanne__werte {
display: grid; gap: 8px 14px;
grid-template-columns: repeat(auto-fit, minmax(92px, 1fr));
padding-top: 11px;
border-top: 1px solid var(--rand);
/* ---------- "11 von 13 Tagen live" ------------------------------------ */
/* KEINE DEKORATION, SONDERN DIE ZAHL, DIE BACKSTAGE MITLIEFERT und die
bis heute weggeworfen wurde: `spaltenRaten` kannte kein Muster für
"Gültige LIVE-Gehen-Tage", die Spalte lief also ins Leere. Jetzt
steht sie da — und ein Streifen zeigt sie, statt sie nur zu nennen.
ER FÜLLT SICH NICHT WIE EIN LADEBALKEN. Das wäre "Fortschritt" und
damit gelogen: Elf von dreizehn Tagen ist kein halb fertiger
Vorgang, sondern ein fertiges Ergebnis. */
.spanne__lauf { margin: 0 0 12px; }
.spanne__lauf-bahn {
position: relative;
height: 8px; border-radius: 3px; overflow: hidden;
background: rgba(150, 186, 220, .14);
}
/* IN TAGE GETEILT, NICHT IN PROZENT.
Ein durchgehender Balken sagt "85 %". Das ist richtig gerechnet und
trotzdem die schlechtere Auskunft: Gezaehlt wurden TAGE, und dreizehn
Kaestchen, von denen elf leuchten, liest man ohne eine einzige Zahl.
Auf 1050 px Breite taeuscht ein glatter Balken ausserdem eine
Genauigkeit vor, die es nicht gibt -- ein Bildpunkt waere ein
Zehntelprozent, die kleinste echte Einheit ist ein ganzer Tag.
EINE MASKE, KEINE DREIZEHN ELEMENTE. Sie schneidet Fugen in den
fertigen Streifen und wirkt dadurch auf Bahn UND Fuellung zugleich --
die beiden koennen also gar nicht auseinanderlaufen.
AB 32 TAGEN WIRD NICHT MEHR GETEILT (`data-teilen` kommt aus dem
Skript): Bei einem Zeitraum ueber ein Quartal waere jede Zelle
schmaler als ihre eigene Fuge -- der Streifen verschwaende sich
selbst. Dann traegt wieder die glatte Bahn. */
.spanne__lauf-bahn[data-teilen="ja"] {
--zelle: calc(100% / var(--tage, 1));
border-radius: 0;
-webkit-mask: repeating-linear-gradient(90deg,
#000 0 calc(var(--zelle) - 2px), transparent calc(var(--zelle) - 2px) var(--zelle));
mask: repeating-linear-gradient(90deg,
#000 0 calc(var(--zelle) - 2px), transparent calc(var(--zelle) - 2px) var(--zelle));
}
.spanne__lauf-teil {
position: absolute; inset: 0 auto 0 0;
border-radius: 3px;
/* Gedeckt, nicht grell: Der Streifen ist der einzige farbige Fleck
der Karte und soll ihn nicht zum Leuchtkasten machen. */
background: linear-gradient(90deg,
color-mix(in srgb, var(--akzent) 72%, transparent),
color-mix(in srgb, var(--akzent) 40%, transparent));
}
.spanne__lauf-text {
display: block; margin-top: 5px;
font-size: .73rem; color: var(--text-leise);
font-variant-numeric: tabular-nums;
}
/* FLIESSEND STATT IM RASTER (16.09.2026).
Als Gitter mit `1fr`-Spuren zog ein einzelner Zeitraum ueber die
ganze Tafelbreite zwei Werte auf 1050 px auseinander -- "LIVE-ZEIT"
ganz links, "NEUE FOLLOWER" in der Mitte, dazwischen nichts. Das
liest sich als Tabelle mit fehlenden Spalten.
Fliessend gesetzt stehen sie beieinander und brechen erst um, wenn
der Platz wirklich endet. Dieselbe Ueberlegung wie bei der
Kopfleiste: eine REGEL, die misst, statt einer Zahl, die rechnet. */
.spanne__werte {
display: flex; flex-wrap: wrap; gap: 9px 26px;
padding-top: 11px;
border-top: 1px solid rgba(150, 186, 220, .13);
}
.spanne__wert {
display: flex; flex-direction: column; gap: 2px;
flex: 0 1 auto; min-width: 92px;
}
.spanne__wert { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.spanne__name {
font-size: .72rem; letter-spacing: .05em; text-transform: uppercase;
color: var(--text-still);
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.spanne__zahl {
font-size: .95rem; color: var(--text-leise);
font-size: .95rem; color: var(--text);
font-variant-numeric: tabular-nums;
}
@media (max-width: 620px) {
.spannen-tafel { --sp-fase: 12px; }
.spannen-tafel__kopf { padding: 12px 14px; }
.spanne { padding: 13px 14px 14px; }
}
@media (forced-colors: active) {
/* Im Kontrastmodus trägt allein die Kante. Fassung, Innenglas und
Metallschrift wären dort graue Flecken — und eine Schrift, die
ihre Farbe aus einem Verlauf holt, wäre unsichtbar. */
.spannen-tafel { background: none; border: 1px solid CanvasText; box-shadow: none; }
.spannen-tafel::before { display: none; }
.spannen { gap: 0; background: none; }
.spanne { border-top: 1px solid CanvasText; background: none; }
.spannen-tafel .spannen__schild, .spanne__haupt-zahl {
background: none; -webkit-text-fill-color: CanvasText; color: CanvasText;
}
.spannen-tafel .spannen__schild::before { display: none; }
}
/* =====================================================================
EINE WOCHE OHNE EINEN EINZIGEN TAG (14.09.2026)