Files
dogfather-universe/workspace/assets/css/leistung.css
T
DogFatherGitandClaude Opus 5 fc823240ab screen4: Dogi-Media — bearbeiten, entfernen, von wann bis wann
Filipe, 22.09.2026: "wenn wir in der kategorie material was hochladen
will ich dass die rechte und linke hand es auch bearbeiten und loeschen
koennen. dogfather auch fals es ein fehler gab. ... uebrigens ersetz das
wort material durch Dogi-Media. und mach kategorien welche sind benutzt
welche nicht welche sind noch offen, welche laufen von wan bis wann."

WAS JETZT GEHT
- Rechte Hand, linke Hand und DogFather bearbeiten und entfernen jedes
  Stueck, nicht nur ihr eigenes. Bearbeitet wird Text und Zeitfenster,
  nicht die Datei: Sonst zeigte dieselbe Nummer etwas anderes als das,
  was sich jemand gerade angesehen hat.
- Ein vergebenes Stueck bleibt unberuehrt (409). Wer es genommen hat,
  hat sich auf diesen Text verlassen.
- Vier Zustaende, gerechnet statt gespeichert: jetzt frei, kommt noch,
  abgelaufen, schon benutzt. Die Kategorieleiste zeigt zu jedem die
  Anzahl aus den echten Daten und filtert BEIDE Listen.
- "Material" heisst ueberall "Dogi-Media", der Dateiname bleibt.

DREI FEHLER AUS DEM EIGENEN ENTWURF, ALLE VOR DEM AUSLIEFERN GEMESSEN

1. `tagLokal()` ohne Argument gab "NaN-NaN-NaN" zurueck -- eine
   Zeichenkette, die aussieht wie ein Datum. Im Vergleich gewinnt das N
   gegen jede Ziffer, also galt JEDES Stueck mit Enddatum vom ersten Tag
   an als abgelaufen, und "Kommt noch" gab es nie. Kein Absturz, keine
   Meldung. Die drei Kopien der Funktion waren hier auseinandergelaufen;
   alle drei haben jetzt die Vorbelegung und werfen bei einer Zahl, die
   keine ist.
2. `frageNach` liefert bei einer reinen Rueckfrage `true`, nicht
   `{ ok: true }`. Der Entwurf prueft auf `erg?.ok` -- "Entfernen" waere
   ein Knopf gewesen, der nichts tut.
3. Drei erfundene Klassennamen (`knopf--leise`, `m-kat__knopf`,
   `m-karte__weg-knopf`) statt der vorhandenen des Hauses. Jetzt
   `.knopf-still`, `.knopf-still--warn` und die Filterleiste `.filter`.

EIN FUND IM BESTAND, ZWEI WOCHEN ALT

In start.css fehlten an einer Stelle die zwei Zeichen, die einen
Kommentar schliessen. CSS-Kommentare schachteln nicht: Der Block lief
bis zum naechsten Abschluss weiter und verschluckte `.kacheln {`; die
Fehlerbehebung des Browsers nahm danach auch die Regel `.kachel` mit.
In Chromium gemessen, beide Fassungen nacheinander: 738 statt 740
Regeln.

Der Entwurf, der dadurch nie gewirkt hat, ist NICHT wiederhergestellt
worden: Seine Flaeche mischte den Kachelton mit 30/11/3 Prozent ein --
pruef-kachelfarben fiel sofort von 36,5 % auf 4,1 % angekommene Farbe,
und 31 Toene sahen gleich aus. Das ist das Gegenteil dessen, was am
22.09. verlangt war. Er ist geloescht, mit dem Grund daneben. Offen
bleibt eine Frage an Filipe, keine Entscheidung von mir: zu demselben
Entwurf gehoerte ein schmaleres Kachelraster (fuenf bis sechs statt
drei pro Reihe). Das aendert das Aussehen der Startseite sichtbar und
bleibt deshalb, wie es ist.

GEMEINSAME BAUSTEINE AUS DEN SEITENDATEIEN GEHOLT
`.filter` stand Zeichen fuer Zeichen doppelt in dateien.css und
bereich.css, `.feld-hinweis` in aufgaben.css und leistung.css (und die
zwei waren schon auseinandergelaufen). Dogi-Media war jeweils die
dritte Seite, die sie braucht, und laedt keine davon. Derselbe Fehler
wie damals bei .knopf-still und beim Schalter -- jetzt in gate.css
bzw. start.css.

GEPRUEFT
pruef-material 155/0 (von 126, neu: Zeitfenster, Bearbeiten, Entfernen,
Rechte in der Liste und ein Abschnitt am echten Bildschirm mit Browser).
pruef-css-klassen um eine Pruefung erweitert, die genau den
start.css-Fehler findet -- mit sieben Gegenproben, darunter der echte
Fall. pruef-kachelfarben 22/0, pruef-start-ansicht, pruef-struktur,
pruef-meldungen, pruef-zeitraum, pruef-content, pruef-serien 69/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 13:59:55 +02:00

884 lines
34 KiB
CSS

/* ===================================================================
Zahlen. Baut auf gate.css, start.css und aufgaben.css auf.
DER GESTALTERISCHE GRUNDSATZ dieser Seite ist ein anderer als auf den
uebrigen: Hier steht nicht die Flaeche im Vordergrund, sondern die
ZAHL. Alles andere -- Rahmen, Beschriftung, Vergleich, Linie --
ordnet sich ihr unter und wird leiser, je weiter es von ihr weg ist.
Deshalb:
* Die Zahl in Tabellenziffern (font-variant-numeric), damit
untereinanderstehende Werte auf derselben Stelle sitzen. Ohne das
tanzen 1.240 und 987 gegeneinander, und man vergleicht schlechter.
* Der Vergleich in GEDECKTEM Gruen/Rot, nicht in Signalfarbe. Ein
Minus ist eine Auskunft, kein Alarm -- und die Seite soll
augenschonend bleiben (Dauerregel).
* Die Verlaufslinie ohne Achsen, Gitter und Beschriftung. Sie
beantwortet genau eine Frage ("geht es hoch oder runter?"), und
jede weitere Linie darin macht diese Antwort langsamer.
=================================================================== */
/* ---------- Kopf ------------------------------------------------------- */
.leistung__wahl { display: grid; gap: 6px; min-width: 220px; }
/* Wie vollstaendig die Woche erfasst ist. Steht neben der Ueberschrift
und nicht darunter: Wer die Zahlen liest, muss diesen Satz VORHER
gesehen haben -- eine Woche aus zwei Tagen ist etwas anderes als eine
aus sieben. */
.leistung__erfassung {
margin: 0; font-size: 13px; color: var(--text-still);
}
.leistung__erfassung[data-knapp="ja"] { color: #d9a441; }
.leistung__leer {
margin: 0; padding: 18px; text-align: center;
color: var(--text-leise); font-size: 14px; line-height: 1.6;
}
.leistung-woche, .leistung-ziele, .leistung-tage { margin: 0 0 30px; }
/* ---------- Die Wochenkarten -------------------------------------------- */
.zahlkarten {
display: grid; gap: 14px;
grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}
.zahlkarte {
position: relative; overflow: hidden;
padding: 16px 16px 12px;
background: var(--flaeche);
border: 1px solid var(--rand);
border-radius: var(--radius-klein);
display: grid; gap: 4px;
/* Alle Karten gleich hoch, auch die ohne Verlaufslinie. Sonst
entsteht eine Treppe, und eine Treppe liest man als Bedeutung
("die kurze Karte ist weniger wichtig"), obwohl sie nur ein
Nebeneffekt ist. */
align-content: start; min-height: 132px;
}
/* DIE LEITZAHL. Die Verweildauer ist seit 2026 die Groesse, an der der
Algorithmus alles aufhaengt -- sie darf nicht eine von sieben
gleichaussehenden Karten sein. Ein feiner Rand und ein Hauch Farbe
reichen; ein Kasten in Signalfarbe waere Laerm. */
.zahlkarte[data-leit="ja"] {
border-color: color-mix(in srgb, var(--akzent) 34%, transparent);
background:
radial-gradient(120% 100% at 0% 0%,
color-mix(in srgb, var(--akzent) 9%, transparent), transparent 70%),
var(--flaeche);
}
.zahlkarte__name {
margin: 0; font-size: 12px; letter-spacing: .07em; text-transform: uppercase;
color: var(--text-still);
}
.zahlkarte__wert {
margin: 0; font-size: 30px; line-height: 1.1; font-weight: 650;
color: var(--text);
/* Tabellenziffern: gleiche Breite je Ziffer. Damit stehen die Werte
mehrerer Karten auf derselben senkrechten Linie. */
font-variant-numeric: tabular-nums;
}
.zahlkarte__wandel {
margin: 2px 0 0; font-size: 12.5px; line-height: 1.45;
}
/* Gedeckt, nicht grell. Gruen und Rot sind hier Auskunft, nicht Ampel --
und beide bleiben ueber 4,5:1 gegen die Kachelflaeche. */
.zahlkarte__wandel[data-richtung="hoch"] { color: #6fc38a; }
.zahlkarte__wandel[data-richtung="runter"] { color: #e08c93; }
.zahlkarte__wandel[data-richtung="gleich"] { color: var(--text-still); }
/* Die kleine Verlaufslinie. Sie sitzt unten in der Karte und laeuft
ueber die ganze Breite -- als Untergrund, nicht als eigenes Bild. */
.zahlkarte__linie {
width: 100%; height: 30px; margin-top: 8px; display: block;
overflow: visible;
}
.zahlkarte__linie polyline {
fill: none; stroke: var(--akzent); stroke-width: 1.6;
stroke-linejoin: round; stroke-linecap: round;
/* Nicht mitskalieren: preserveAspectRatio="none" streckt das Bild in
die Breite und wuerde die Linie sonst hauchduenn ziehen. */
vector-effect: non-scaling-stroke;
opacity: .8;
}
.zahlkarte__linie circle {
fill: var(--akzent); stroke: none;
/* Der letzte Punkt ist das Jetzt. Er wird durch die Streckung zum
Ei -- deshalb bleibt er klein genug, dass es nicht auffaellt. */
}
.zahlkarte[data-leit="ja"] .zahlkarte__linie polyline { opacity: 1; }
/* ---------- Ziele -------------------------------------------------------- */
.zielbalken { display: grid; gap: 16px; }
.zielbalken__zeile {
padding: 14px 16px;
background: var(--flaeche);
border: 1px solid var(--rand);
border-radius: var(--radius-klein);
}
.zielbalken__kopf {
display: flex; justify-content: space-between; align-items: baseline;
gap: 12px; margin-bottom: 10px; flex-wrap: wrap;
}
.zielbalken__name { font-size: 14px; color: var(--text); }
.zielbalken__zahl {
font-size: 14px; color: var(--text-leise); font-variant-numeric: tabular-nums;
}
.zielbalken__spur {
height: 10px; border-radius: 999px; overflow: hidden;
background: rgba(150, 186, 220, 0.12);
}
.zielbalken__fuell {
height: 100%; border-radius: 999px;
background: linear-gradient(90deg, var(--akzent-tief), var(--akzent));
transition: width var(--tempo);
}
/* Ein erreichtes Ziel wechselt die Farbe, nicht die Groesse. Ein
springender Balken waere Bewegung ohne Aussage. */
.zielbalken__fuell[data-voll="ja"] {
background: linear-gradient(90deg, #2f8f5b, #55c184);
}
.zielbalken__anteil {
margin: 8px 0 0; font-size: 12.5px; color: var(--text-still);
}
@media (prefers-reduced-motion: reduce) {
.zielbalken__fuell { transition: none; }
}
/* ---------- Die Tageszeilen ---------------------------------------------- */
.tagetabelle {
display: grid; gap: 8px;
}
.tagzeile {
display: grid; align-items: center; gap: 6px 16px;
grid-template-columns: 74px 1fr auto;
padding: 12px 16px;
background: var(--flaeche);
border: 1px solid var(--rand);
border-radius: var(--radius-klein);
}
/* EIN TAG OHNE EINTRAG BLEIBT SICHTBAR -- er ist selbst die Auskunft.
Er wird nur leiser, damit die erfassten Tage vorn stehen. */
.tagzeile[data-leer="ja"] {
background: transparent;
border-style: dashed;
border-color: rgba(150, 186, 220, 0.13);
}
/* Woher die Zeile kommt. Ein schmaler Streifen links, kein Etikett:
Man muss es wissen KOENNEN, nicht bei jedem Blick lesen. */
.tagzeile[data-quelle="import"] {
border-left: 3px solid color-mix(in srgb, var(--violett) 55%, transparent);
}
.tagzeile__datum { display: grid; gap: 1px; }
.tagzeile__wochentag {
font-size: 12px; letter-spacing: .08em; text-transform: uppercase;
color: var(--text-still);
}
.tagzeile__zahl {
font-size: 15px; color: var(--text); font-variant-numeric: tabular-nums;
}
.tagzeile__werte {
display: flex; flex-wrap: wrap; gap: 6px 22px; min-width: 0;
}
.tagzeile__wert { display: grid; gap: 1px; min-width: 0; }
.tagzeile__wertname {
font-size: 12px; letter-spacing: .05em; color: var(--text-still);
}
.tagzeile__wertzahl {
font-size: 15px; color: var(--text); font-variant-numeric: tabular-nums;
}
.tagzeile__leer { font-size: 13.5px; color: var(--text-still); }
/* Die Notiz laeuft ueber die ganze Zeilenbreite unter den Werten --
sie ist der Kontext, ohne den eine eingebrochene Zahl in die Irre
fuehrt ("krank", "Technik ausgefallen"). */
.tagzeile__notiz {
grid-column: 2 / -1;
margin: 2px 0 0; font-size: 13px; line-height: 1.5;
color: var(--text-leise);
}
.tagzeile__knopf {
grid-row: 1; grid-column: 3;
padding: 8px 14px; min-height: 38px;
font: inherit; font-size: 13px;
color: var(--text-leise); cursor: pointer;
background: transparent;
border: 1px solid var(--rand); border-radius: 999px;
transition: color var(--tempo), border-color var(--tempo);
}
.tagzeile__knopf:hover, .tagzeile__knopf:focus-visible {
color: var(--text); border-color: var(--rand-hell);
}
.import-vorschau {
margin: 4px 0 14px; padding: 16px;
background: rgba(150, 186, 220, 0.05);
border: 1px solid var(--rand);
border-radius: var(--radius-klein);
}
.import-zahlen { display: flex; flex-wrap: wrap; gap: 12px 28px; }
.import-zahl { display: grid; gap: 2px; }
.import-zahl__wert {
font-size: 26px; font-weight: 650; line-height: 1.1;
color: var(--text); font-variant-numeric: tabular-nums;
}
.import-zahl__name { font-size: 12px; color: var(--text-still); }
.import-zahl[data-warn="ja"] .import-zahl__wert { color: #d9a441; }
.import-spalten {
margin: 14px 0 0; font-size: 13px; line-height: 1.6;
color: var(--text-leise);
}
.import-probleme {
margin: 10px 0 0; padding-left: 20px;
font-size: 12.5px; line-height: 1.7; color: #d9a441;
}
/* ---------- Handy --------------------------------------------------------- */
@media (max-width: 640px) {
/* Die Wochenkarten werden EINSPALTIG, nicht enger. Zwei Karten
nebeneinander auf 360 px lassen fuer die Zahl 150 px uebrig -- ein
vierstelliger Wert bricht dann um, und eine umgebrochene Zahl ist
keine Zahl mehr. */
.zahlkarten { grid-template-columns: 1fr; }
.zahlkarte { min-height: 0; }
.zahlkarte__wert { font-size: 27px; }
.leistung__wahl { min-width: 0; width: 100%; }
/* Die Tageszeile wird zweizeilig: Datum und Knopf oben, die Werte
darunter. Drei Spalten nebeneinander quetschen den Knopf sonst auf
unter 44 px -- und darunter trifft man ihn mit dem Daumen nicht
mehr zuverlaessig. */
.tagzeile {
grid-template-columns: 1fr auto;
gap: 10px 12px;
}
.tagzeile__datum { grid-row: 1; grid-column: 1; }
.tagzeile__knopf { grid-row: 1; grid-column: 2; }
.tagzeile__werte { grid-row: 2; grid-column: 1 / -1; gap: 8px 18px; }
.tagzeile__notiz { grid-row: 3; grid-column: 1 / -1; }
.import-zahl__wert { font-size: 23px; }
}
/* =====================================================================
DIE BACKSTAGE-TABELLE (11.09.2026)
Ein Textfeld, in das eine ganze Tabelle passt -- und eine Vorschau,
die nicht nur zählt, sondern NAMEN nennt. Wer eine Zeile übersieht,
hat stillschweigend jemanden ausgelassen; das ist die Sorte Fehler,
die erst Wochen später auffällt.
===================================================================== */
.netz__feld {
width: 100%;
min-height: 120px;
font-family: ui-monospace, "Cascadia Code", "Consolas", monospace;
font-size: .82rem; line-height: 1.5;
/* Umbrechen AUS: Eine Tabellenzeile soll eine Zeile bleiben, sonst
sieht man nicht, ob die Spalten sauber getrennt wurden. */
white-space: pre; overflow-x: auto;
}
.import-vorschau__zeile {
margin: 0 0 4px;
font-size: .84rem; line-height: 1.5;
color: var(--text-leise);
}
.import-vorschau__zeile[data-art="gut"] {
color: color-mix(in srgb, var(--k-gut, #5fc99a) 45%, #ffffff);
font-weight: 600;
}
.import-vorschau__zeile[data-art="warn"] {
color: color-mix(in srgb, var(--k-warn, #e0736b) 42%, #ffffff);
font-weight: 600;
}
.import-vorschau__zeile[data-art="still"] {
color: var(--text-still); font-size: .8rem;
}
/* =====================================================================
DIE ANLEITUNGEN (11.09.2026)
Filipe: "ich brauch auch eine erklärung immer dabei wo die scouts und
manager das finden. also eine perfekte beschreibung bitte."
Zwei Ebenen, weil zwei Fragen dahinterstecken:
1. WAS IST DAS? -- zwei Sätze, immer sichtbar unter den Knöpfen.
Wer davorsitzt und beide Knöpfe zum ersten Mal sieht, weiß sonst
nicht, welcher für ihn gemeint ist.
2. WIE GEHT DAS? -- die Schritte, im Fenster, wo man sie braucht.
Dort stören sie niemanden, der es längst weiß.
Eine Anleitung, die immer und vollständig auf der Seite steht, liest
nach dem dritten Mal niemand mehr -- und dann steht sie nur im Weg.
===================================================================== */
.quellen-hinweis {
display: flex; flex-wrap: wrap; gap: 6px 22px;
margin: 10px 0 0;
font-size: .8rem; line-height: 1.5;
color: var(--text-still);
}
.quellen-hinweis > span { flex: 1 1 320px; min-width: 0; }
.quellen-hinweis strong { color: var(--text-leise); }
/* Die Schritte im Fenster. Nummern in der Hausfarbe, damit man sie als
Reihenfolge liest und nicht als Aufzählung -- bei einer Anleitung ist
die Reihenfolge die halbe Auskunft. */
.anleitung {
margin: 10px 0 12px; padding: 0 0 0 1.5em;
font-size: .83rem; line-height: 1.55;
color: var(--text-still);
}
.anleitung li { margin: 0 0 6px; }
.anleitung li::marker { color: var(--akzent); font-weight: 700; }
.anleitung strong { color: var(--text-leise); }
/* ---- EINGEKLAPPTE HILFE (11.09.2026) ------------------------------
Filipe zum Backstage-Fenster: "die sieht so scheisse aus."
Der Grund war nicht die Farbe, sondern die Reihenfolge: Fuenf lange
Schritte standen VOR dem Feld, in das man einfuegt. Wer das Fenster
oft benutzt, scrollte jedes Mal an einer Anleitung vorbei, die er
laengst kennt.
Jetzt liegt sie unter einer Zeile, die man aufklappen KANN. Kein
Kasten, kein Rahmen -- nur ein Pfeil und eine stille Zeile, damit
sie im geschlossenen Zustand fast nichts vom Fenster wegnimmt. */
.hilfe {
margin: 14px 0 4px;
border-top: 1px solid var(--rand);
padding-top: 10px;
}
.hilfe > summary {
display: flex; align-items: center; gap: 7px;
list-style: none; cursor: pointer;
font-size: .82rem; color: var(--text-still);
padding: 3px 0;
transition: color var(--tempo);
}
.hilfe > summary::-webkit-details-marker { display: none; }
/* Der Pfeil wird gedreht statt ausgetauscht -- ein Zeichen, zwei
Zustaende, und die Drehung sagt von selbst, was passiert. */
.hilfe > summary::before {
content: ""; flex: none;
width: 7px; height: 7px;
border-right: 1.6px solid currentColor;
border-bottom: 1.6px solid currentColor;
transform: rotate(-45deg);
transition: transform var(--tempo);
}
.hilfe[open] > summary::before { transform: rotate(45deg); }
.hilfe > summary:hover { color: var(--text-leise); }
.hilfe > summary:focus-visible { outline: 2px solid var(--akzent); outline-offset: 3px; }
.hilfe__satz {
margin: 0 0 8px; font-size: .8rem; line-height: 1.55;
color: var(--text-still);
}
.hilfe__satz strong { color: var(--text-leise); }
/* Der Tag steht neben seinem Hinweis, nicht in der Beschriftung. Vorher
hing der ganze Erklaersatz in der Ueberschrift des Feldes und machte
sie zweizeilig -- eine Beschriftung, die man lesen muss, ist keine
mehr. */
/* `font: inherit` ist hier kein Schoenheitsfehler-Fix, sondern
Notwendigkeit: Ohne Angabe rendert der Browser ein Datumsfeld in
SEINER Schrift -- neben dem uebrigen Fenster sieht das aus wie ein
Rest, den jemand vergessen hat. Die Breite deckelt es auf die
Laenge, die ein Datum wirklich braucht; volle Breite laesst ein
fast leeres Feld quer durch den Dialog laufen. */
.neu__zeile--tag input[type="date"] {
max-width: 190px;
font: inherit; font-size: .88rem;
}
/* `.feld-hinweis` steht seit 22.09.2026 in start.css. Die Fassung hier
hatte kein `line-height` und war damit schon einen Hauch anders als
die in aufgaben.css -- zwei Kopien laufen auseinander, auch wenn sie
am Anfang gleich aussahen. */
/* "… oder direkt die Datei": steht UNTER dem Einfuegefeld und gehoert
sichtbar dazu, ohne ihm den Rang abzulaufen. Das Dateifeld selbst
bleibt klein -- es ist der zweite Weg, nicht der erste. */
.feld-hinweis--oder {
display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
margin-top: 8px;
}
.feld-datei { flex: 1 1 220px; min-width: 0; font-size: .76rem; }
/* =====================================================================
ZEITRÄUME AUS BACKSTAGE — dritte Fassung (16.09.2026)
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."
---------------------------------------------------------------------
WAS WIRKLICH NICHT STIMMTE — im Bildschirmfoto gemessen, nicht geraten
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 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: 1px;
background: #05070c;
grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}
.spanne {
position: relative;
padding: 15px 18px 16px;
background:
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: 12px;
border-bottom: 1px solid rgba(150, 186, 220, .13);
}
.spanne__spanne {
display: inline-flex; align-items: baseline; gap: 5px;
font-size: 1.06rem; font-weight: 650; color: var(--text);
font-variant-numeric: tabular-nums;
}
.spanne__strich { color: var(--text-still); font-weight: 400; }
.spanne__tage {
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. 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: 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-leise);
}
/* Der Durchschnitt steht in derselben Zeile und deutlich kleiner:
Er ist eine Einordnung, kein zweiter Messwert. */
.spanne__schnitt {
flex-basis: 100%;
font-size: .76rem; color: var(--text-still);
font-variant-numeric: tabular-nums;
}
/* ---------- "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__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);
font-variant-numeric: tabular-nums;
}
/* ---------- Alles, was in der Datei stand ------------------------------ */
/* Filipe: "wenn ich dir runter lade soll alles notiert und angezeigt
werden." Achtunddreissig Werte je Zeitraum -- offen waeren sie eine
Wand, weg waeren sie eine Luecke. Also ein Deckel, der die ZAHL
nennt: Man sieht ohne Oeffnen, dass nichts fehlt.
ZWEI SPALTEN, NICHT ZWEI ZEILEN. Name links, Wert rechts, mit einer
gepunkteten Fuehrung dazwischen -- so liest man 38 Paare von oben
nach unten, ohne die Zeile zu verlieren. Untereinander waeren es 76
Zeilen. */
.spanne__alles {
margin-top: 12px;
border-top: 1px solid rgba(150, 186, 220, .13);
padding-top: 10px;
}
.spanne__alles-kopf {
cursor: pointer;
list-style: none;
display: flex; align-items: center; gap: 7px;
font-size: .76rem; letter-spacing: .04em;
color: var(--text-leise);
}
.spanne__alles-kopf::-webkit-details-marker { display: none; }
/* Ein eigener Pfeil statt des Standarddreiecks -- das sieht auf jedem
Gerät anders aus, und hier soll alles gleich aussehen. */
.spanne__alles-kopf::before {
content: "";
width: 7px; height: 7px; flex: none;
border-right: 1.5px solid currentColor;
border-bottom: 1.5px solid currentColor;
transform: rotate(-45deg);
transition: transform var(--tempo, .2s);
}
.spanne__alles[open] > .spanne__alles-kopf::before { transform: rotate(45deg); }
.spanne__alles-kopf:hover { color: var(--text); }
.spanne__alles-liste {
margin: 10px 0 0;
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 0 12px;
align-items: baseline;
}
.spanne__alles-name {
margin: 0; padding: 4px 0;
font-size: .74rem; color: var(--text-still);
min-width: 0;
/* Die gepunktete Fuehrung liegt auf dem NAMEN, nicht als eigenes
Element: ein Unterrand, der genau so breit ist wie der Text. */
border-bottom: 1px dotted rgba(150, 186, 220, .16);
}
.spanne__alles-wert {
margin: 0; padding: 4px 0;
font-size: .78rem; color: var(--text);
text-align: right; white-space: nowrap;
font-variant-numeric: tabular-nums;
border-bottom: 1px dotted rgba(150, 186, 220, .16);
}
@media (prefers-reduced-motion: reduce) {
.spanne__alles-kopf::before { transition: none; }
}
@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)
Filipe: "wieso werden die zahlen oben nicht ausgefüllt von der excel
datei?" Sieben Karten mit "0" und "wie in der Vorwoche" sehen aus
wie ein Fehler. Stattdessen steht dort jetzt die Antwort -- und der
Weg, wie man es ändert.
===================================================================== */
.woche-leer {
border: 1px dashed color-mix(in srgb, var(--akzent) 34%, var(--rand));
border-radius: 14px;
padding: 14px 16px 15px;
background: color-mix(in srgb, var(--akzent) 5%, transparent);
max-width: 72ch;
}
.woche-leer__satz {
margin: 0 0 6px;
font-size: .96rem; font-weight: 600; color: var(--text);
}
.woche-leer__grund {
margin: 0; font-size: .84rem; line-height: 1.6; color: var(--text-leise);
}
.woche-leer__weg {
margin: 9px 0 0; padding-top: 9px;
border-top: 1px solid var(--rand);
font-size: .82rem; line-height: 1.6; color: var(--text-still);
}