Files
dogfather-universe/assets/css/webdesign.css
T
DogFatherGitandClaude Opus 5 469a6c195f Portal: Aufgabenliste und Postfach fuer den Kunden
Schritt 4 von 4 -- damit sind beide Wuensche vom 22.08.2026 vollstaendig:
"wenn sie drauf druecken sollen sie auch sehen was ich schon gemacht habe
von dem was im plan war" und "die kunden sollen mir auch nachrichten
hinterlassen koennen".

AUFGABENLISTE IM PROJEKT

Bisher sah der Kunde nur die Phase ("Design . 3/7") -- eine Zahl ohne
Inhalt. Sie beantwortet die eigentliche Frage nicht: WAS ist denn fertig?

Die Liste steht GANZ OBEN, direkt nach dem Projektkopf, noch vor
Zahlungen und Dateien. Die sind wichtig, aber sie sind nicht der Grund
fuer den Klick.

Zwei Entscheidungen praegen die Ansicht:

1. Offene Kundenpunkte stehen in einem EIGENEN Kasten ganz oben ("Das
   brauche ich noch von dir"), nicht nur farblich markiert irgendwo
   mittendrin. Wer eine lange Liste sieht, liest sie als Bericht ueber
   fremde Arbeit und ueberliest seinen eigenen Teil -- genau daraus
   entstehen die meisten Verzoegerungen. Ist nichts offen, steht das
   auch da: "Von dir wird gerade nichts gebraucht." Eine gute Nachricht
   darf ausgesprochen werden.

2. Der Kunde hakt seine eigenen Punkte selbst ab. Nur diese haben einen
   Knopf; bei fremden Punkten ist das Zeichen reine Anzeige. Ein Knopf,
   der nichts tut, laesst die Seite kaputt wirken. Geprueft: 4 Knoepfe
   bei 2 offenen eigenen Punkten (sie erscheinen zweimal), 5 feste.

Grosse Zahl statt Prozent: "2 von 6 erledigt" ist greifbar, "33 %" ist
eine Rechnung, die niemand fuehlt. Der Balken traegt die vier
Prozessfarben -- dieselben wie auf der Ablaufseite und in der Verwaltung.

Der Ton ist bewusst gewaehlt. Der Kunde liest die Liste, wenn er unsicher
ist -- also im Zweifel schon angespannt. "Wir warten auf dich" waere
Druck, "Das brauche ich noch von dir" ist eine Bitte.

POSTFACH AUF DER UEBERSICHT

Bewusst auf der Uebersicht, nicht im Projekt: Wer kein Projekt hat -- oder
eine Frage, die zu keinem gehoert -- konnte vorher gar nicht schreiben und
musste zur E-Mail greifen. Damit war der Verlauf weg, sobald man ihn
brauchte.

Niedrigschwellig: kein Betreff, kein Pflichtfeld, der Projektbezug ist
freiwillig. Wer glaubt, eine Nachricht muesse eine "richtige" Anfrage
sein, schreibt gar nicht erst -- und genau die kurzen Fragen sollen hier
landen. Wird nachgeladen, damit die Uebersicht sofort dasteht.

Projekt- und Aufgabendaten werden gleichzeitig angefordert statt
nacheinander -- sonst waere die Wartezeit die Summe beider Anfragen. Die
Aufgabenliste darf dabei fehlschlagen, ohne die Seite mitzureissen: Wer
wegen einer leeren Liste seine Zahlungen nicht mehr saehe, waere
schlechter dran als vorher.

EIN SICHTBARER FEHLER GEFUNDEN

Auf dem Screenshot stand "Ideen & Aenderungswuensche". Ursache ist
eine Falle mit zwei Wegen: Texte ueber data-i18n landen als HTML in der
Seite, dort ist "&" richtig. Derselbe Text im JavaScript laeuft aber
durch die Absicherung und wird ein zweites Mal kodiert. Derselbe Baustein
ist also je nach Verwendungsort richtig oder falsch.

Das kann man nicht im Kopf behalten -- deshalb neu pruef-texte.mjs mit
ZWEI Pruefungen:

  Anzeige:   alle 11 Seiten x 5 Sprachen = 55 Kombinationen, sichtbarer
             Text darf keine Kodierungsreste enthalten.
  Quelltext: welcher Baustein mit "&" wird irgendwo abgesichert
             eingesetzt?

Beide sind noetig. Gegengeprueft: Die Anzeigepruefung allein haette den
Fehler NICHT gefunden, weil die Ideen-Karte erst nach einer Anmeldung
erscheint. Die Quelltextpruefung findet ihn ohne Anzeige.

Auch die Quelltextpruefung selbst wurde zweimal gegengeprueft: Zuerst
meldete sie zusaetzlich po_senden ("Senden", voellig harmlos) -- ihre
Blockerkennung lief bis zum naechsten Schluessel und schluckte dabei
einen Kommentar mit "&". Jetzt zaehlt sie geschweifte Klammern. Ein
Fehlalarm im Pruefwerkzeug ist fast so schaedlich wie ein uebersehener
Fehler: Man gewoehnt sich daran, ihn wegzusehen.

GEPRUEFT

32 Pruefungen im Portal (Computer und Handy), alle bestanden. Darunter:
114 Texte in allen fuenf Sprachen vollstaendig, Kundenpunkte stehen vor
der langen Liste, Aufgaben vor den Zahlungen, Abhaken meldet den
richtigen Punkt, alle Kaestchen mindestens 24 px, keine Fehler im
Protokoll. Dazu 55 Seiten-Sprach-Kombinationen ohne Kodierungsreste.

Ein Fehler im Test selbst gefunden und behoben: Die Adressabfrage prueft
jetzt den PFAD statt der ganzen Adresse. Der API-Server heisst
"postfach.dogfather-universe.com" -- ein includes("/postfach") traf den
HOSTNAMEN und damit jede Anfrage, auch die Uebersicht.

Versionsstempel und Cache-Name auf v5.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 10:46:09 +02:00

1545 lines
72 KiB
CSS

/* =====================================================================
DOGFATHER WEBDESIGN — webdesign.css
Eigenes Designsystem für den Bereich /webdesign, umgesetzt nach dem
"Website Masterplan" (Seite 6, VISUELLE DNA).
Warum eine EIGENE Datei statt main.css zu erweitern:
- main.css trägt drei Welten (Dogfather/HasiDog/SpicyMedia) über
theme-*.css. Der Webdesign-Bereich ist eine vierte, eigenständige
Marke mit eigener Farblogik (Gold ist hier z.B. AUSSCHLIESSLICH für
Hinweise/Zahlung reserviert, im Universe ist es allgemeine Deko).
Eine Vermischung würde beide Systeme unscharf machen.
- Der Bereich ist bis zur Freigabe nicht öffentlich. Solange darf er
am laufenden Universe nichts kaputt machen können — getrennte Datei
heißt: null Risiko für die Live-Seite.
Die Grundtokens (--radius, Schriftfamilien) kommen weiterhin aus
main.css, das hier zusätzlich geladen wird. Alles Eigene trägt bewusst
das Präfix --wd- / .wd-, damit es sich nie mit main.css beißt.
AUGENSCHONEND ist Dauervorgabe (nicht projektspezifisch):
gedeckte Flächen statt greller Neon-Optik, Leuchten nur als weicher
Schimmer, keine Flacker-/Strobe-Effekte, jede Animation respektiert
prefers-reduced-motion, Textkontraste durchgehend über WCAG-AA.
===================================================================== */
/* ---------------------------------------------------------------------
1. FARBWELT & TOKENS
Kontraste gegen die dunkelste Fläche (#05070b) nachgerechnet:
--wd-text #eef4fb -> 17.4:1 (AAA)
--wd-text-mid #b3c2d4 -> 10.2:1 (AAA)
--wd-text-soft #8f9fb4 -> 6.6:1 (AA, auch für kleine Schrift)
--wd-blau #7fd0e8 -> 10.6:1 (AAA)
--wd-lila #b79dff -> 8.1:1 (AAA)
--wd-gold #e8c877 -> 11.0:1 (AAA)
Bewusst KEIN reines #00e5ff / #ff00ff — solche vollgesättigten Neons
blenden auf dunklem Grund und sind genau das, was vermieden werden soll.
--------------------------------------------------------------------- */
:root {
--wd-schwarz: #05070b; /* Tiefschwarz — Grundfläche */
--wd-dunkelblau: #0a1220; /* Dunkelblau — zweite Grundfläche */
--wd-dunkelblau-2: #0e1826; /* leicht angehoben, für Abschnittswechsel */
--wd-flaeche: #101a29; /* Kartengrund (deckend, für Formularfelder) */
--wd-blau: #7fd0e8; /* Babyblau — Hauptaktionen, Linien, Leuchten */
--wd-blau-hell: #a9e2f2; /* Eisblau — Lesbarkeit auf dunklem Grund */
--wd-blau-tief: #3d9dbd; /* für Ränder/Verläufe, nicht für Text */
--wd-lila: #b79dff; /* sekundäre Bereiche, Kontrast */
--wd-lila-tief: #7c5cd6;
--wd-gold: #e8c877; /* NUR Hinweise & Zahlungsinformationen */
--wd-gold-tief: #a8873a;
--wd-text: #eef4fb;
--wd-text-mid: #b3c2d4;
--wd-text-soft: #8f9fb4;
--wd-rand: rgba(127, 208, 232, .16);
--wd-rand-stark: rgba(127, 208, 232, .34);
--wd-glas: rgba(16, 26, 41, .62);
--wd-glas-tief: rgba(10, 18, 32, .82);
--wd-ok: #6fd6a3;
--wd-fehler: #ff9d9d;
--wd-warnung: var(--wd-gold);
--wd-r: 16px; /* Standardradius */
--wd-r-gross: 22px;
--wd-schatten: 0 24px 60px -28px rgba(0, 0, 0, .9);
--wd-schatten-tief: 0 40px 90px -34px rgba(0, 0, 0, .95);
/* Bewegung an EINER Stelle steuerbar — die Reduktions-Regel ganz unten
setzt diese Variablen auf 0s, damit auch neu hinzukommende Animationen
automatisch mit abgeschaltet sind und nicht einzeln nachgepflegt
werden müssen. */
--wd-zeit-schnell: .16s;
--wd-zeit: .28s;
--wd-zeit-lang: .6s;
}
/* ---------------------------------------------------------------------
1b. BILDLAUFLEISTE
Rückmeldung 22.08.2026: "die leiste rechts zum hoch und runter, kannst
du die mal geil aussehen lassen anstatt einfach so kake weiß."
Zu Recht. Auf einer durchgehend dunklen Seite ist eine helle
Bildlaufleiste der einzige grelle Streifen im Bild — sie zieht den
Blick genau dorthin, wo nichts Wichtiges steht, und ist bei einer
dunklen Umgebung schlicht blendend. Das widerspricht der Dauervorgabe
"augenschonend".
Zwei Wege sind nötig, weil kein Browser beide versteht:
* color-scheme: dark -- Firefox und Safari. Ein einziges Wort, das
dem Browser sagt: das hier ist eine dunkle Oberfläche, nimm deine
dunklen Bedienelemente. Wirkt auch auf Auswahlfelder und
Datumsauswahl, die sonst weiß aufblitzen.
* ::-webkit-scrollbar -- Chrome, Edge, Opera. Feiner steuerbar,
aber ausschließlich dort verfügbar.
scrollbar-width/-color (die neue Norm) NICHT verwendet: Sobald es
gesetzt ist, ignoriert Chrome die ::-webkit-Regeln und man bekommt
überall die grobe Fassung. Zwei getrennte Wege ergeben in beiden
Browserfamilien das bessere Ergebnis.
Die Leiste ist bewusst zurückhaltend: gedeckt, erst beim Zeigen etwas
heller. Sie soll auffindbar sein, nicht leuchten.
--------------------------------------------------------------------- */
body.wd,
.wd input, .wd select, .wd textarea {
/* Wirkt zusätzlich auf Formularfelder — sonst bleibt die Datumsauswahl
in Firefox ein weißes Rechteck mitten in der dunklen Seite. */
color-scheme: dark;
}
/* ACHTUNG bei den Selektoren: "body.wd::-webkit-scrollbar" (ohne
Leerzeichen) und ".wd ::-webkit-scrollbar" (mit Leerzeichen) sind
zwei VERSCHIEDENE Dinge, und man braucht beide.
ohne Leerzeichen -> die Leiste des body selbst, also die grosse
rechts am Fensterrand. GENAU die war gemeint.
mit Leerzeichen -> die Leisten von Elementen INNERHALB der Seite,
z.B. im Detailfenster der Verwaltung.
Beim ersten Versuch stand hier nur die zweite Fassung. Alle Messungen
sahen gut aus — an der einzigen Leiste, ueber die sich jemand
beschwert hatte, aenderte sich dadurch nichts. */
body.wd::-webkit-scrollbar,
.wd ::-webkit-scrollbar { width: 12px; height: 12px; }
body.wd::-webkit-scrollbar-track,
.wd ::-webkit-scrollbar-track {
background: rgba(8, 14, 24, .6);
border-radius: 999px;
}
body.wd::-webkit-scrollbar-thumb,
.wd ::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, rgba(127,208,232,.44), rgba(183,157,255,.36));
border-radius: 999px;
/* Der durchsichtige Rand lässt die Spur seitlich durchscheinen — der
Griff wirkt dadurch schmaler als die Trefferfläche. Bedienbar bleibt
die volle Breite, sichtbar ist nur ein feiner Strich. */
border: 3px solid transparent;
background-clip: content-box;
}
body.wd::-webkit-scrollbar-thumb:hover,
.wd ::-webkit-scrollbar-thumb:hover {
background: linear-gradient(180deg, rgba(127,208,232,.6), rgba(183,157,255,.5));
background-clip: content-box;
}
body.wd::-webkit-scrollbar-thumb:active,
.wd ::-webkit-scrollbar-thumb:active {
background: linear-gradient(180deg, rgba(127,208,232,.8), rgba(183,157,255,.7));
background-clip: content-box;
}
/* Die Ecke zwischen waagerechter und senkrechter Leiste — ohne diese
Zeile bleibt genau dort ein weißes Quadrat stehen. */
body.wd::-webkit-scrollbar-corner,
.wd ::-webkit-scrollbar-corner { background: transparent; }
/* ---------------------------------------------------------------------
2. GRUNDLAGEN
--------------------------------------------------------------------- */
body.wd {
background: var(--wd-schwarz);
color: var(--wd-text);
font-family: var(--font-body);
line-height: 1.7;
overflow-x: hidden;
}
/* Cinematische Tiefe: zwei sehr weiche, weit auseinanderliegende
Lichtquellen statt eines flächigen Verlaufs. Fest positioniert, damit
beim Scrollen echte Tiefe entsteht, ohne eine einzige Animation zu
kosten (Masterplan S.6 "Cinematische Tiefe, Licht, Nebel" — S.15 aber
auch "Animationen leistungsbewusst"). */
body.wd::before {
content: "";
position: fixed;
inset: 0;
z-index: -2;
pointer-events: none;
background:
radial-gradient(1100px 720px at 18% -8%, rgba(61, 157, 189, .20), transparent 68%),
radial-gradient(900px 640px at 92% 8%, rgba(124, 92, 214, .16), transparent 66%),
linear-gradient(180deg, #070b12 0%, var(--wd-schwarz) 46%, #04060a 100%);
}
/* Feine Rasterlinien — gibt der Fläche Struktur (Premium statt Baukasten),
bleibt mit 3 % Deckkraft klar unter der Wahrnehmungsschwelle für
"unruhig". mask blendet das Raster nach unten aus, damit es nicht
teppichartig über die ganze Seite liegt. */
body.wd::after {
content: "";
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
opacity: .5;
background-image:
linear-gradient(rgba(127, 208, 232, .03) 1px, transparent 1px),
linear-gradient(90deg, rgba(127, 208, 232, .03) 1px, transparent 1px);
background-size: 64px 64px;
-webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 62%);
mask-image: linear-gradient(180deg, #000 0%, transparent 62%);
}
.wd-container { width: min(1180px, 92vw); margin: 0 auto; }
.wd-container--schmal { width: min(860px, 92vw); }
/* Abstand zwischen den Abschnitten.
Vorher clamp(3.4rem, 7vw, 6.5rem) = 100,8px oben UND unten, also gut
200px Leerraum zwischen zwei Abschnitten. Rueckmeldung 22.08.2026:
"ich will nicht soooo viel abstand". Jetzt rund die Haelfte -- immer
noch klar getrennt, aber ohne dass man an leeren Flaechen
vorbeiscrollt. */
.wd-abschnitt { padding: clamp(2.2rem, 4vw, 3.6rem) 0; position: relative; }
.wd-abschnitt--eng { padding: clamp(1.4rem, 2.6vw, 2.2rem) 0; }
/* Abwechselnde Grundfläche statt Trennlinien — ruhiger und trotzdem klar. */
.wd-abschnitt--gehoben { background: linear-gradient(180deg, transparent, var(--wd-dunkelblau) 14%, var(--wd-dunkelblau) 86%, transparent); }
/* ---------- Typografie (Masterplan S.6) ----------
Dynamische Größen mit clamp(); Fließtext bewusst ruhiger und kleiner als
im Universe (dort 1.32rem), weil hier deutlich mehr Sachtext steht —
Preise, Bedingungen und Abläufe müssen lesbar sein, nicht laut. */
.wd h1, .wd h2, .wd h3, .wd h4 {
font-family: var(--font-head);
line-height: 1.15;
letter-spacing: -.015em;
margin: 0 0 .5em;
color: var(--wd-text);
/* Lange deutsche Komposita ("Buchhaltungsverwaltungsseiten") duerfen auf
dem Handy nicht aus dem Kasten laufen — dafuer reicht
overflow-wrap: break-word. Es greift NUR im Notfall, wenn ein Wort
sonst wirklich ueberlaufen wuerde.
"hyphens: auto" stand hier zusaetzlich und ist wieder raus: der
Browser trennt damit nach Silben, auch wenn gar kein Platzproblem
besteht. Auf dem Handy stand dadurch "Alles, was vorher ge-klaert
sein sollte" in der Ueberschrift. In Fliesstext ist Silbentrennung
ein Gewinn, in grossen Ueberschriften sieht sie schlicht billig aus —
und genau die sind das Erste, was jemand von der Seite sieht. */
overflow-wrap: break-word;
hyphens: manual;
}
.wd h1 { font-size: clamp(2.15rem, 5.6vw, 3.9rem); font-weight: 800; }
.wd h2 { font-size: clamp(1.75rem, 4.2vw, 2.75rem); font-weight: 800; }
.wd h3 { font-size: clamp(1.2rem, 2.4vw, 1.5rem); font-weight: 700; }
.wd h4 { font-size: 1.05rem; font-weight: 700; }
.wd p { margin: 0 0 1em; color: var(--wd-text-mid); font-size: clamp(1rem, 1.5vw, 1.12rem); }
.wd .wd-lead { font-size: clamp(1.08rem, 2vw, 1.32rem); color: var(--wd-text); line-height: 1.65; }
.wd .wd-klein { font-size: .92rem; }
.wd .wd-leise { color: var(--wd-text-soft); }
/* :not(.wd-btn) ist hier PFLICHT, kein Feinschliff.
Ohne das gewinnt ".wd a" (Klasse + Element = spezifischer als die reine
Knopf-Klasse ".wd-btn--haupt") und faerbt die Schrift auf dem hellblauen
Hauptknopf ebenfalls hellblau -- blau auf blau, praktisch unlesbar.
Genau so live gemeldet am 22.08.2026 per Bildschirmfoto. */
.wd a:not(.wd-btn) { color: var(--wd-blau); text-decoration: none; }
.wd a:not(.wd-btn):hover { color: var(--wd-blau-hell); }
.wd a.wd-btn { text-decoration: none; }
.wd strong { color: var(--wd-text); font-weight: 700; }
.wd-eyebrow {
display: inline-block;
font-size: .74rem;
letter-spacing: .18em;
text-transform: uppercase;
font-weight: 800;
color: var(--wd-blau);
margin-bottom: .9em;
}
.wd-eyebrow--lila { color: var(--wd-lila); }
/* Sichtbarer Fokus ÜBERALL (Masterplan S.15 Barrierearmut). :focus-visible
statt :focus, damit Mausklicks keinen Rahmen hinterlassen, Tastatur aber
immer einen — und zwar auch auf Elementen, die erst später dazukommen. */
.wd :focus-visible {
outline: 3px solid var(--wd-blau);
outline-offset: 3px;
border-radius: 6px;
}
/* Sprungmarke für Tastatur-/Screenreader-Nutzung. */
.wd-skip {
position: absolute; left: -9999px; top: 0; z-index: 200;
background: var(--wd-blau); color: #04060a; font-weight: 800;
padding: .8rem 1.2rem; border-radius: 0 0 10px 0;
}
.wd-skip:focus { left: 0; }
/* ---------------------------------------------------------------------
[hidden] MUSS gewinnen.
Das hidden-Attribut wird vom Browser nur mit "display: none" aus dem
Standard-Stylesheet umgesetzt — jede eigene display-Angabe schlaegt es.
Und genau die haben hier viele Elemente: Knoepfe sind inline-flex,
Karten sind flex, Raster sind grid.
Folge ohne diese Regel: el.hidden = true im JavaScript hat schlicht
keine Wirkung, und das Element bleibt sichtbar. Genau so aufgefallen im
Anfrageformular (22.08.2026) -- der "Zurueck"-Knopf stand auch auf dem
ersten Schritt da, obwohl es dorthin nichts zurueckzugehen gibt.
Das !important ist hier ausnahmsweise richtig: "versteckt" ist eine
Aussage ueber den Zustand, nicht ueber die Gestaltung, und darf von
keiner Gestaltungsregel ueberstimmt werden.
--------------------------------------------------------------------- */
.wd [hidden] { display: none !important; }
.wd-visuell-versteckt {
position: absolute; width: 1px; height: 1px; overflow: hidden;
clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
/* ---------------------------------------------------------------------
BILDVERHAELTNIS — diese Regel verhindert einen Fehler, der schon
passiert ist und sonst wieder passiert.
Bilder tragen im HTML bewusst width/height als Attribute: der Browser
reserviert damit vor dem Laden den richtigen Platz und die Seite
springt beim Nachladen nicht. Diese Attribute wirken aber wie eine
CSS-Hoehe -- und schlagen damit jedes spaetere "aspect-ratio".
Live gemeldet am 22.08.2026 ("die sollen alle gleich aussehen"): die
beiden Projektbilder standen mit 750px bzw. 696px Hoehe bei nur 576px
Breite da, also hochkant gestreckt und ungleich hoch, obwohl im CSY
sauber 16:10 stand.
"height: auto" gibt die Hoehe an aspect-ratio zurueck. Es steht hier
einmal zentral fuer alle Bilder mit Seitenverhaeltnis, statt in jeder
einzelnen Regel -- so kann es bei einem neuen Bild nicht vergessen
werden.
--------------------------------------------------------------------- */
.wd img[width][height] { height: auto; }
/* ---------------------------------------------------------------------
3. KARTEN — "glasartig mit feinen Neonrändern" (Masterplan S.6)
Der Rand ist bewusst ein Verlauf über border-box statt einer flachen
Farbe: dadurch wirkt er wie eine Lichtkante, nicht wie ein Strich.
--------------------------------------------------------------------- */
.wd-karte {
position: relative;
border-radius: var(--wd-r-gross);
padding: clamp(1.3rem, 2.6vw, 1.9rem);
background:
linear-gradient(180deg, rgba(20, 32, 50, .72), rgba(9, 15, 26, .86)) padding-box,
linear-gradient(140deg, rgba(127, 208, 232, .40), rgba(127, 208, 232, .07) 45%, rgba(183, 157, 255, .30)) border-box;
border: 1px solid transparent;
box-shadow: var(--wd-schatten);
backdrop-filter: blur(10px);
transition: transform var(--wd-zeit) ease, box-shadow var(--wd-zeit) ease;
}
/* Sekundäre Bereiche tragen Lila (Masterplan S.6). */
.wd-karte--lila {
background:
linear-gradient(180deg, rgba(26, 22, 48, .72), rgba(12, 10, 24, .88)) padding-box,
linear-gradient(140deg, rgba(183, 157, 255, .42), rgba(183, 157, 255, .07) 45%, rgba(127, 208, 232, .26)) border-box;
}
/* Nur für Karten, die wirklich klickbar sind — eine Karte, die sich hebt,
ohne dass man sie anklicken kann, verspricht eine Aktion, die es nicht
gibt. */
a.wd-karte:hover, .wd-karte--klickbar:hover {
transform: translateY(-4px);
box-shadow: var(--wd-schatten-tief), 0 0 44px -20px rgba(127, 208, 232, .55);
}
/* Farbige Kappe oben — übernimmt die Optik der Masterplan-PDF, in der jede
Karte einen blauen bzw. lila Balken trägt. */
.wd-karte--kappe { padding-top: clamp(1.6rem, 3vw, 2.2rem); overflow: hidden; }
.wd-karte--kappe::before {
content: "";
position: absolute; top: 0; left: 0; right: 0; height: 5px;
background: linear-gradient(90deg, var(--wd-blau-tief), var(--wd-blau));
}
.wd-karte--lila.wd-karte--kappe::before { background: linear-gradient(90deg, var(--wd-lila-tief), var(--wd-lila)); }
.wd-karte h3 { margin-bottom: .55em; }
.wd-karte > :last-child { margin-bottom: 0; }
/* Aufzählung in Karten — Punkt als eigenes Element statt list-style, damit
die Farbe steuerbar ist und mehrzeilige Punkte sauber einrücken. */
.wd-liste { margin: 0; padding: 0; list-style: none; }
.wd-liste li {
position: relative;
padding-left: 1.35rem;
margin-bottom: .55rem;
color: var(--wd-text-mid);
font-size: clamp(.98rem, 1.4vw, 1.05rem);
}
.wd-liste li::before {
content: "";
position: absolute; left: 0; top: .62em;
width: 7px; height: 7px; border-radius: 50%;
background: var(--wd-blau);
box-shadow: 0 0 10px rgba(127, 208, 232, .7);
}
.wd-karte--lila .wd-liste li::before { background: var(--wd-lila); box-shadow: 0 0 10px rgba(183, 157, 255, .7); }
.wd-liste li:last-child { margin-bottom: 0; }
/* ---------- Raster ---------- */
.wd-grid { display: grid; gap: clamp(1rem, 2vw, 1.5rem); }
.wd-grid--2 { grid-template-columns: repeat(2, 1fr); }
.wd-grid--3 { grid-template-columns: repeat(3, 1fr); }
.wd-grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) { .wd-grid--3, .wd-grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .wd-grid--2, .wd-grid--3, .wd-grid--4 { grid-template-columns: 1fr; } }
/* ---------------------------------------------------------------------
4. KNÖPFE
Genau EIN Haupt-CTA pro Seite (Masterplan S.3) — deshalb gibt es
bewusst nur eine einzige auffällige Knopfvariante. Alles andere ist
sichtbar, konkurriert aber nicht.
--------------------------------------------------------------------- */
.wd-btn {
display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
/* min-height 48px = Touch-Ziel-Mindestmaß (Masterplan S.15). */
min-height: 48px;
padding: .85rem 1.7rem;
/* Abgerundetes Rechteck statt Pillenform (999px).
Rueckmeldung 22.08.2026: "das sieht lang gezogen aus". Stimmt — bei
einer Pille waechst der Radius optisch mit der Breite mit, ein breiter
Knopf wirkt dadurch auseinandergezogen wie eine Tablette. Ein fester
Radius haelt die Form bei jeder Breite gleich und wirkt ruhiger und
hochwertiger. */
border-radius: 14px;
border: 1px solid transparent;
font-family: var(--font-head);
font-weight: 700;
font-size: 1rem;
line-height: 1.2;
cursor: pointer;
text-align: center;
transition: transform var(--wd-zeit-schnell) ease, box-shadow var(--wd-zeit) ease,
background var(--wd-zeit) ease, border-color var(--wd-zeit) ease, color var(--wd-zeit) ease;
}
/* Sofortige, sichtbare Reaktion (Masterplan S.6 "Buttons reagieren sofort
und sichtbar") — active feuert ohne Verzögerung, auch auf dem Handy. */
.wd-btn:active { transform: translateY(1px) scale(.985); }
.wd-btn[disabled], .wd-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; transform: none; }
.wd .wd-btn--haupt, .wd-btn--haupt {
/* Dunkler Text auf hellem Babyblau: 11.7:1 — der einzige Weg, einen
leuchtenden Knopf zu bauen, ohne die Lesbarkeit zu opfern. */
background: linear-gradient(135deg, var(--wd-blau-hell), var(--wd-blau) 55%, #63bcd8);
color: #04070c;
box-shadow: 0 12px 34px -14px rgba(127, 208, 232, .8);
}
.wd-btn--haupt:hover { box-shadow: 0 16px 44px -14px rgba(127, 208, 232, .95); transform: translateY(-2px); }
.wd .wd-btn--zweit, .wd-btn--zweit {
background: rgba(127, 208, 232, .07);
border-color: var(--wd-rand-stark);
color: var(--wd-blau-hell);
}
.wd-btn--zweit:hover { background: rgba(127, 208, 232, .14); border-color: var(--wd-blau); }
.wd .wd-btn--still, .wd-btn--still { background: transparent; border-color: var(--wd-rand); color: var(--wd-text-mid); }
.wd-btn--still:hover { border-color: var(--wd-rand-stark); color: var(--wd-text); }
.wd-btn--breit { width: 100%; }
/* "klein" heißt schmaler und leiser, NICHT niedriger als das Touch-Ziel.
Die Höhe stand hier ursprünglich auf 40px — die Handy-Abnahme
(server/pruefe-webdesign-handy.mjs) hat das quer über alle Seiten
angemerkt: „Dieses Paket anfragen“, „Live ansehen“ und „Was genau
enthalten ist“ waren durchgehend 4px zu flach. 44px ist die Untergrenze,
ab der ein Ziel mit dem Daumen zuverlässig getroffen wird. */
.wd-btn--klein { min-height: 44px; padding: .6rem 1.05rem; font-size: .9rem; }
.wd-btn-reihe { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; }
/* ---------------------------------------------------------------------
5. HINWEISFLÄCHEN — Gold ist AUSSCHLIESSLICH hierfür reserviert
(Masterplan S.6: "Gold ausschließlich für wichtige Hinweise und
Zahlungsinformationen"). Wer Gold sieht, soll wissen: das ist wichtig.
--------------------------------------------------------------------- */
.wd-hinweis {
position: relative;
border-radius: var(--wd-r);
padding: 1.15rem 1.35rem 1.15rem 1.6rem;
background: linear-gradient(180deg, rgba(232, 200, 119, .09), rgba(232, 200, 119, .04));
border: 1px solid rgba(232, 200, 119, .32);
border-left: 4px solid var(--wd-gold);
}
.wd-hinweis-titel {
margin: 0 0 .35rem;
font-family: var(--font-head);
font-weight: 800;
font-size: .82rem;
letter-spacing: .12em;
text-transform: uppercase;
color: var(--wd-gold);
}
.wd-hinweis p { margin: 0; color: var(--wd-text-mid); font-size: .98rem; }
.wd-hinweis p + p { margin-top: .6rem; }
/* Neutrale Variante für Erklärungen, die NICHT wichtig-wichtig sind —
damit Gold seine Signalwirkung behält. */
.wd-notiz {
border-radius: var(--wd-r);
padding: 1rem 1.25rem;
background: rgba(127, 208, 232, .05);
border: 1px solid var(--wd-rand);
}
.wd-notiz p { margin: 0; font-size: .96rem; }
/* ---------------------------------------------------------------------
6. TAGS / KENNZEICHEN
--------------------------------------------------------------------- */
.wd-tag {
display: inline-flex; align-items: center; gap: .35rem;
padding: .3rem .7rem;
border-radius: 999px;
font-size: .78rem; font-weight: 700; letter-spacing: .04em;
background: rgba(127, 208, 232, .12);
border: 1px solid var(--wd-rand-stark);
color: var(--wd-blau-hell);
}
.wd-tag--lila { background: rgba(183, 157, 255, .12); border-color: rgba(183, 157, 255, .34); color: var(--wd-lila); }
.wd-tag--gold { background: rgba(232, 200, 119, .12); border-color: rgba(232, 200, 119, .34); color: var(--wd-gold); }
.wd-tag--ok { background: rgba(111, 214, 163, .12); border-color: rgba(111, 214, 163, .34); color: var(--wd-ok); }
.wd-tags { display: flex; flex-wrap: wrap; gap: .45rem; }
/* ---------------------------------------------------------------------
7. PREISKARTEN (Masterplan S.8)
Preis, Dauer und Personalisierungshinweis gehören sichtbar zusammen —
der Hinweis steht deshalb direkt unter dem Preis, nicht im Kleingedruckten.
--------------------------------------------------------------------- */
.wd-preis-karte { display: flex; flex-direction: column; }
.wd-preis {
font-family: var(--font-head);
font-weight: 800;
font-size: clamp(1.9rem, 4.4vw, 2.5rem);
line-height: 1.1;
margin: .2rem 0 .5rem;
color: var(--wd-blau);
}
.wd-karte--lila .wd-preis { color: var(--wd-lila); }
.wd-preis-zeile { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; margin-bottom: .5rem; }
.wd-preis-label { font-size: .78rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--wd-blau); }
.wd-karte--lila .wd-preis-label { color: var(--wd-lila); }
.wd-preis-wert { color: var(--wd-text-mid); font-size: .98rem; }
/* mt:auto schiebt den Knopf immer an den Kartenboden — sonst stehen die
Knöpfe in einer Reihe unterschiedlich hoher Karten treppenförmig. */
.wd-preis-karte .wd-btn { margin-top: auto; }
.wd-personalisierung {
margin-top: .2rem;
font-size: .88rem;
color: var(--wd-text-soft);
font-style: italic;
}
/* ---------------------------------------------------------------------
8. NUMMERIERTE SCHRITTE (Ablauf / Customer Journey)
--------------------------------------------------------------------- */
.wd-schritte { display: grid; gap: 1rem; }
.wd-schritt {
display: grid;
grid-template-columns: auto 1fr;
gap: 1.1rem;
align-items: start;
border-radius: var(--wd-r-gross);
padding: 1.25rem 1.4rem;
background: linear-gradient(180deg, rgba(20, 32, 50, .55), rgba(9, 15, 26, .75));
border: 1px solid var(--wd-rand);
}
.wd-schritt-nr {
font-family: var(--font-head);
font-weight: 800;
font-size: clamp(1.4rem, 3vw, 1.9rem);
line-height: 1;
min-width: 2.2ch;
color: var(--wd-blau);
font-variant-numeric: tabular-nums;
}
.wd-schritt:nth-child(even) { border-color: rgba(183, 157, 255, .18); }
.wd-schritt:nth-child(even) .wd-schritt-nr { color: var(--wd-lila); }
.wd-schritt h3 { margin: 0 0 .3em; font-size: 1.12rem; }
.wd-schritt p { margin: 0; font-size: 1rem; }
@media (max-width: 520px) {
.wd-schritt { grid-template-columns: 1fr; gap: .4rem; }
}
/* ---------------------------------------------------------------------
9. FAQ — natives <details>, damit es ohne JavaScript funktioniert
und die Tastaturbedienung vom Browser kommt statt nachgebaut zu werden.
--------------------------------------------------------------------- */
.wd-faq { border-radius: var(--wd-r); border: 1px solid var(--wd-rand); background: rgba(16, 26, 41, .5); margin-bottom: .7rem; overflow: hidden; }
.wd-faq > summary {
cursor: pointer;
list-style: none;
padding: 1.05rem 3rem 1.05rem 1.25rem;
position: relative;
font-family: var(--font-head);
font-weight: 700;
font-size: 1.04rem;
color: var(--wd-text);
transition: background var(--wd-zeit-schnell) ease;
}
.wd-faq > summary::-webkit-details-marker { display: none; }
.wd-faq > summary:hover { background: rgba(127, 208, 232, .05); }
.wd-faq > summary::after {
content: "+";
position: absolute; right: 1.2rem; top: 50%; transform: translateY(-50%);
font-size: 1.5rem; line-height: 1; color: var(--wd-blau);
transition: transform var(--wd-zeit) ease;
}
.wd-faq[open] > summary::after { transform: translateY(-50%) rotate(45deg); }
.wd-faq-inhalt { padding: 0 1.25rem 1.15rem; }
.wd-faq-inhalt p { margin: 0; font-size: 1rem; }
.wd-faq-inhalt p + p { margin-top: .7rem; }
/* ---------------------------------------------------------------------
10. FORMULARE (Masterplan S.10 + S.15)
Zustände für Fehler und Erfolg sind Pflicht — und der Fehler steht
IMMER unter dem Feld, nie nur als Farbe: Farbe allein ist für
farbfehlsichtige Menschen keine Information.
--------------------------------------------------------------------- */
.wd-feld { margin-bottom: 1.15rem; }
.wd-feld > label,
.wd-feld-legende {
display: block;
margin-bottom: .45rem;
font-weight: 700;
font-size: .95rem;
color: var(--wd-text);
}
.wd-pflicht { color: var(--wd-blau); margin-left: .15rem; }
.wd-feld-hilfe { display: block; margin: -.2rem 0 .5rem; font-size: .88rem; color: var(--wd-text-soft); }
.wd-eingabe,
.wd-feld input[type="text"], .wd-feld input[type="email"], .wd-feld input[type="tel"],
.wd-feld input[type="url"], .wd-feld input[type="number"], .wd-feld input[type="date"],
.wd-feld input[type="password"], .wd-feld input[type="search"],
.wd-feld select, .wd-feld textarea {
width: 100%;
box-sizing: border-box;
padding: .82rem 1rem;
min-height: 48px;
border-radius: 12px;
background: var(--wd-flaeche);
border: 1.5px solid var(--wd-rand);
color: var(--wd-text);
font-family: var(--font-body);
/* 16px verhindert, dass iOS beim Fokus in ein Feld hineinzoomt. */
font-size: 16px;
line-height: 1.5;
transition: border-color var(--wd-zeit-schnell) ease, box-shadow var(--wd-zeit-schnell) ease, background var(--wd-zeit-schnell) ease;
}
.wd-feld textarea { min-height: 130px; resize: vertical; }
.wd-feld select {
/* Eigener Pfeil: das Standard-Dreieck von Windows ist auf dunklem Grund
fast unsichtbar. */
appearance: none;
background-image: linear-gradient(45deg, transparent 50%, var(--wd-blau) 50%), linear-gradient(135deg, var(--wd-blau) 50%, transparent 50%);
background-position: calc(100% - 20px) center, calc(100% - 14px) center;
background-size: 6px 6px, 6px 6px;
background-repeat: no-repeat;
padding-right: 2.6rem;
}
.wd-feld ::placeholder { color: rgba(143, 159, 180, .7); }
.wd-eingabe:focus, .wd-feld input:focus, .wd-feld select:focus, .wd-feld textarea:focus {
outline: none;
border-color: var(--wd-blau);
background: #12203180;
box-shadow: 0 0 0 4px rgba(127, 208, 232, .16);
}
/* Fehlerzustand */
.wd-feld--fehler .wd-eingabe,
.wd-feld--fehler input, .wd-feld--fehler select, .wd-feld--fehler textarea {
border-color: var(--wd-fehler);
box-shadow: 0 0 0 4px rgba(255, 157, 157, .12);
}
.wd-feld-fehler {
display: none;
margin: .45rem 0 0;
font-size: .9rem;
color: var(--wd-fehler);
font-weight: 600;
}
.wd-feld-fehler::before { content: "⚠ "; }
.wd-feld--fehler .wd-feld-fehler { display: block; }
/* Auswahlkacheln (Radio/Checkbox als anklickbare Fläche) — deutlich
fingerfreundlicher als native Punkte und zeigt den gewählten Zustand
nicht nur farblich, sondern über Rand + Häkchen. */
.wd-wahl { display: grid; gap: .7rem; }
.wd-wahl--2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 640px) { .wd-wahl--2 { grid-template-columns: 1fr; } }
.wd-wahl-kachel { position: relative; display: block; cursor: pointer; }
.wd-wahl-kachel input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.wd-wahl-inhalt {
display: block;
padding: 1rem 1.15rem 1rem 2.9rem;
border-radius: 14px;
background: rgba(16, 26, 41, .6);
border: 1.5px solid var(--wd-rand);
transition: border-color var(--wd-zeit-schnell) ease, background var(--wd-zeit-schnell) ease;
}
.wd-wahl-inhalt::before {
content: "";
position: absolute; left: 1rem; top: 1.15rem;
width: 20px; height: 20px; border-radius: 6px;
border: 2px solid var(--wd-rand-stark);
background: rgba(5, 7, 11, .6);
transition: border-color var(--wd-zeit-schnell) ease, background var(--wd-zeit-schnell) ease;
}
.wd-wahl-kachel input[type="radio"] + .wd-wahl-inhalt::before { border-radius: 50%; }
.wd-wahl-kachel:hover .wd-wahl-inhalt { border-color: var(--wd-rand-stark); }
.wd-wahl-kachel input:checked + .wd-wahl-inhalt {
border-color: var(--wd-blau);
background: rgba(127, 208, 232, .09);
}
.wd-wahl-kachel input:checked + .wd-wahl-inhalt::before {
border-color: var(--wd-blau);
background: var(--wd-blau);
/* Häkchen als CSS-Maske — kein Bild, keine Schriftart nötig. */
box-shadow: inset 0 0 0 3px #05070b, inset 0 0 0 20px var(--wd-blau);
}
.wd-wahl-kachel input:focus-visible + .wd-wahl-inhalt { outline: 3px solid var(--wd-blau); outline-offset: 3px; }
.wd-wahl-titel { display: block; font-weight: 700; color: var(--wd-text); }
.wd-wahl-text { display: block; font-size: .9rem; color: var(--wd-text-soft); margin-top: .15rem; }
/* Erfolgs-/Fehlermeldung eines ganzen Formulars */
.wd-meldung { border-radius: var(--wd-r); padding: 1rem 1.2rem; margin-bottom: 1.2rem; font-weight: 600; }
.wd-meldung--ok { background: rgba(111, 214, 163, .1); border: 1px solid rgba(111, 214, 163, .38); color: var(--wd-ok); }
.wd-meldung--fehler { background: rgba(255, 157, 157, .1); border: 1px solid rgba(255, 157, 157, .38); color: var(--wd-fehler); }
.wd-meldung[hidden] { display: none; }
/* ---------------------------------------------------------------------
11. FORTSCHRITT (mehrstufiges Formular)
--------------------------------------------------------------------- */
.wd-fortschritt { margin-bottom: 1.8rem; }
.wd-fortschritt-schiene { height: 6px; border-radius: 999px; background: rgba(127, 208, 232, .12); overflow: hidden; }
.wd-fortschritt-balken {
height: 100%; width: 0%;
border-radius: 999px;
background: linear-gradient(90deg, var(--wd-blau-tief), var(--wd-blau));
transition: width var(--wd-zeit-lang) cubic-bezier(.4, 0, .2, 1);
}
.wd-fortschritt-text { margin: .6rem 0 0; font-size: .88rem; color: var(--wd-text-soft); }
/* ---------------------------------------------------------------------
12. TABELLEN (Verwaltung / Portal)
Auf schmalen Bildschirmen scrollt die Tabelle waagerecht in ihrem
eigenen Kasten, statt die ganze Seite zu verbreitern.
--------------------------------------------------------------------- */
.wd-tabelle-rahmen { overflow-x: auto; border-radius: var(--wd-r); border: 1px solid var(--wd-rand); }
.wd-tabelle { width: 100%; border-collapse: collapse; font-size: .95rem; min-width: 560px; }
.wd-tabelle th, .wd-tabelle td { padding: .8rem 1rem; text-align: left; border-bottom: 1px solid var(--wd-rand); }
.wd-tabelle th {
font-family: var(--font-head); font-size: .78rem; font-weight: 800;
letter-spacing: .1em; text-transform: uppercase; color: var(--wd-blau);
background: rgba(127, 208, 232, .05);
position: sticky; top: 0;
}
.wd-tabelle tbody tr:last-child td { border-bottom: none; }
.wd-tabelle tbody tr:hover { background: rgba(127, 208, 232, .04); }
.wd-tabelle td { color: var(--wd-text-mid); }
/* ---------------------------------------------------------------------
13. BEWEGUNG — "kontrolliert beim Scrollen" (Masterplan S.6)
Die Elemente starten sichtbar und werden erst per JS auf unsichtbar
gesetzt (Klasse .wd-bereit am <html>). Ohne JavaScript oder bei einem
Skriptfehler bleibt dadurch ALLES lesbar — der häufigste schwere Fehler
bei Scroll-Animationen ist eine dauerhaft unsichtbare Seite.
--------------------------------------------------------------------- */
.wd-bereit .wd-auf {
opacity: 0;
transform: translateY(18px);
transition: opacity var(--wd-zeit-lang) ease, transform var(--wd-zeit-lang) cubic-bezier(.22, 1, .36, 1);
}
.wd-bereit .wd-auf.wd-sichtbar { opacity: 1; transform: none; }
/* ---------------------------------------------------------------------
14. KOPF- UND FUSSZEILE des Webdesign-Bereichs
Eigene Leiste statt der Universe-Navigation: der Bereich hat eigene
Ziele (Anfrage statt Bewerbung) und ist bis zur Freigabe nicht
öffentlich. Der Rückweg ins Universe steht trotzdem immer sichtbar
drin (Masterplan S.14 "Direkte Navigation zwischen Universe und
Webdesign").
--------------------------------------------------------------------- */
.wd-kopf {
position: sticky; top: 0; z-index: 60;
background: rgba(5, 7, 11, .92);
backdrop-filter: blur(14px);
border-bottom: 1px solid var(--wd-rand);
}
.wd-kopf-bar {
width: min(1320px, 94vw); margin: 0 auto;
display: flex; align-items: center; gap: 1rem;
padding: .7rem 0;
}
/* min-height 44px: die Marke ist ein Link auf die Startseite und damit
ein echtes Touch-Ziel — sie war vorher exakt so hoch wie das Logo (42px). */
.wd-marke { display: flex; align-items: center; gap: .65rem; flex-shrink: 0; min-height: 44px; }
.wd-marke img { width: 42px; height: 42px; object-fit: contain; }
.wd-marke-text { display: flex; flex-direction: column; line-height: 1.1; }
.wd-marke-oben { font-family: var(--font-head); font-weight: 800; font-size: 1rem; color: var(--wd-text); letter-spacing: .02em; }
.wd-marke-unten { font-size: .68rem; letter-spacing: .18em; text-transform: uppercase; color: var(--wd-blau); font-weight: 700; }
.wd-nav { display: flex; align-items: center; gap: .15rem; margin-left: auto; }
.wd-nav a {
/* inline-flex + min-height statt nur Innenabstand: mit reinem padding
kam der Menüpunkt auf 43px — einen Pixel unter dem Touch-Ziel, was
die Handy-Abnahme zu Recht angemerkt hat. */
display: inline-flex; align-items: center; min-height: 44px;
padding: .5rem .8rem; border-radius: 10px;
font-size: .95rem; font-weight: 600; color: var(--wd-text-mid);
transition: color var(--wd-zeit-schnell) ease, background var(--wd-zeit-schnell) ease;
}
.wd-nav a:hover { color: var(--wd-text); background: rgba(127, 208, 232, .07); }
.wd-nav a.wd-aktiv { color: var(--wd-blau); background: rgba(127, 208, 232, .11); }
.wd-nav .wd-btn { margin-left: .5rem; }
.wd-menue-knopf {
display: none; margin-left: auto;
align-items: center; gap: .45rem;
min-height: 44px; padding: .5rem .9rem;
border-radius: 10px; border: 1px solid var(--wd-rand);
background: transparent; color: var(--wd-text); cursor: pointer; font-weight: 700;
}
/* Sprachschalter — teilt sich die gespeicherte Sprache mit dem Universe
(localStorage "dogi-sprache"), damit ein Wechsel hier auch dort gilt. */
.wd-sprache { position: relative; }
.wd-sprache-knopf {
display: inline-flex; align-items: center; gap: .35rem;
/* 44px statt 40px — auch auf dem Computer ist das der bessere Wert:
Touchscreen-Laptops und Tablets im Querformat landen ebenfalls hier. */
min-height: 44px; padding: .5rem .75rem;
border-radius: 10px; border: 1px solid var(--wd-rand);
background: transparent; color: var(--wd-text-mid); cursor: pointer;
font-weight: 700; font-size: .88rem;
}
.wd-sprache-knopf:hover { color: var(--wd-text); border-color: var(--wd-rand-stark); }
.wd-sprache-liste {
position: absolute; right: 0; top: calc(100% + .4rem);
min-width: 190px; padding: .35rem;
border-radius: 12px;
background: #0b1320;
border: 1px solid var(--wd-rand-stark);
box-shadow: var(--wd-schatten);
display: none;
z-index: 70;
}
.wd-sprache.wd-offen .wd-sprache-liste { display: block; }
.wd-sprache-liste button {
display: flex; align-items: center; gap: .6rem;
width: 100%; min-height: 42px; padding: .5rem .7rem;
border: none; border-radius: 8px; background: transparent;
color: var(--wd-text-mid); cursor: pointer; text-align: left; font-size: .95rem;
}
.wd-sprache-liste button:hover { background: rgba(127, 208, 232, .09); color: var(--wd-text); }
.wd-sprache-liste button[aria-current="true"] { color: var(--wd-blau); font-weight: 700; }
.wd-sprache-punkt { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
@media (max-width: 1080px) {
.wd-menue-knopf { display: inline-flex; }
.wd-nav {
display: none;
position: absolute; left: 0; right: 0; top: 100%;
flex-direction: column; align-items: stretch; gap: .2rem;
padding: .8rem 4vw 1.2rem;
background: #070b12;
border-bottom: 1px solid var(--wd-rand);
box-shadow: var(--wd-schatten);
/* Vollbildnavigation auf dem Handy (Masterplan S.5), aber scrollbar —
bei 8 Punkten + Sprachschalter passt sonst nicht alles auf ein
kleines Display. */
max-height: calc(100vh - 70px);
overflow-y: auto;
}
.wd-nav.wd-offen { display: flex; }
/* Die minimale Kopfzeile (Zugangswand) enthält nur den Sprachschalter und
hat deshalb bewusst keinen Menü-Knopf. Ohne diese Ausnahme wäre sie auf
dem Handy durch die Regel oben komplett unsichtbar — man könnte die
Sprache dort dann gar nicht mehr umstellen. */
.wd-nav--minimal {
display: flex; position: static; flex-direction: row;
padding: 0; background: none; border: none; box-shadow: none;
max-height: none; overflow: visible; width: auto;
}
.wd-nav--minimal .wd-sprache { margin-top: 0; }
.wd-nav--minimal .wd-sprache-knopf { width: auto; }
.wd-nav--minimal .wd-sprache-liste { position: absolute; width: auto; }
.wd-nav a { padding: .8rem .9rem; font-size: 1.02rem; }
.wd-nav .wd-btn { margin: .6rem 0 0; }
.wd-sprache { margin-top: .6rem; }
.wd-sprache-knopf { width: 100%; justify-content: center; }
.wd-sprache-liste { position: static; width: 100%; margin-top: .4rem; }
}
/* Fußzeile */
.wd-fuss { border-top: 1px solid var(--wd-rand); background: rgba(5, 7, 11, .8); padding: 2.6rem 0 2rem; margin-top: 3rem; }
.wd-fuss-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 2rem; }
@media (max-width: 780px) { .wd-fuss-grid { grid-template-columns: 1fr; gap: 1.5rem; } }
.wd-fuss h4 { font-size: .78rem; letter-spacing: .14em; text-transform: uppercase; color: var(--wd-blau); margin-bottom: .8rem; }
.wd-fuss ul li { margin-bottom: .1rem; }
/* Fußzeilenlinks waren nur so hoch wie ihre Zeile (20px) und damit auf dem
Handy praktisch nicht sicher zu treffen — sie liegen zudem dicht
untereinander, was Fehlgriffe zusätzlich begünstigt. Als inline-flex mit
Mindesthöhe sind sie ein ordentliches Touch-Ziel; die Fußzeile wird
dadurch etwas höher, was hier die richtige Abwägung ist. */
.wd-fuss a {
display: inline-flex; align-items: center; min-height: 44px;
color: var(--wd-text-mid); font-size: .95rem;
}
/* Die Marke in der Fußzeile bringt ihre eigene Höhe mit. */
.wd-fuss a.wd-marke { min-height: 48px; }
.wd-fuss a:hover { color: var(--wd-blau); }
.wd-fuss-unten {
margin-top: 2rem; padding-top: 1.2rem;
border-top: 1px solid var(--wd-rand);
display: flex; flex-wrap: wrap; gap: .8rem; justify-content: space-between;
font-size: .86rem; color: var(--wd-text-soft);
}
/* ---------------------------------------------------------------------
15. HERO
"Der erste Bildschirm enthält niemals zu viel Text" (Masterplan S.7).
min-height bewusst mit svh: 100vh ist auf dem Handy die Höhe OHNE
Adressleiste — der Knopf rutscht damit beim ersten Laden unter die
sichtbare Kante, genau das, was die Hero-Regel verbietet.
--------------------------------------------------------------------- */
.wd-hero { position: relative; padding: clamp(2.6rem, 6vw, 4.6rem) 0 clamp(2.2rem, 4vw, 3.4rem); min-height: 68svh; display: flex; align-items: center; }
.wd-hero-inhalt { max-width: 780px; }
.wd-hero h1 { margin-bottom: .45em; }
.wd-hero .wd-lead { margin-bottom: 1.8rem; max-width: 62ch; }
.wd-hero-glanz {
/* Kein Farbverlauf über den ganzen Titel — nur die Kernaussage trägt ihn,
sonst leidet die Lesbarkeit langer Überschriften. */
background: linear-gradient(120deg, var(--wd-blau-hell), var(--wd-blau) 45%, var(--wd-lila));
-webkit-background-clip: text; background-clip: text; color: transparent;
}
.wd-hero-belege { display: flex; flex-wrap: wrap; gap: .5rem 1.4rem; margin-top: 2rem; }
.wd-hero-beleg { display: flex; align-items: center; gap: .45rem; font-size: .92rem; color: var(--wd-text-soft); }
.wd-hero-beleg::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--wd-blau); box-shadow: 0 0 8px var(--wd-blau); }
/* ---------------------------------------------------------------------
16. INSTALLATIONS-HINWEIS ("Als App installieren")
Sitzt unten statt oben: oben würde er die Kopfzeile verdecken, und auf
dem Handy ist der Daumen unten. env(safe-area-inset-bottom) hält ihn
über der Gestenleiste neuerer iPhones — ohne das liegt der Schließen-
Knopf genau unter dem Strich und ist praktisch nicht treffbar.
--------------------------------------------------------------------- */
.wd-install {
position: fixed; z-index: 80;
left: 50%; transform: translateX(-50%);
bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
width: min(560px, calc(100vw - 1.6rem));
display: flex; align-items: center; gap: 1rem;
padding: .85rem 1rem;
border-radius: var(--wd-r);
background: rgba(11, 19, 32, .97);
border: 1px solid var(--wd-rand-stark);
box-shadow: var(--wd-schatten-tief);
backdrop-filter: blur(12px);
animation: wd-install-auf .45s cubic-bezier(.22, 1, .36, 1) both;
}
@keyframes wd-install-auf { from { opacity: 0; transform: translate(-50%, 16px); } to { opacity: 1; transform: translate(-50%, 0); } }
.wd-install-text { display: flex; align-items: center; gap: .8rem; flex: 1; min-width: 0; }
.wd-install-text img { border-radius: 9px; flex-shrink: 0; }
.wd-install-text strong { display: block; font-size: .95rem; color: var(--wd-text); }
.wd-install-text span { display: block; font-size: .84rem; color: var(--wd-text-soft); line-height: 1.45; }
.wd-install-knoepfe { display: flex; align-items: center; gap: .4rem; flex-shrink: 0; }
.wd-install-knoepfe .wd-btn--still { min-width: 44px; padding: .5rem .7rem; }
@media (max-width: 560px) {
/* Auf schmalen Bildschirmen untereinander — nebeneinander wird der Text
auf zwei Wörter pro Zeile gequetscht. */
.wd-install { flex-direction: column; align-items: stretch; gap: .7rem; }
.wd-install-knoepfe { justify-content: flex-end; }
.wd-install-knoepfe .wd-btn--haupt { flex: 1; }
}
/* ---------------------------------------------------------------------
17. BEWEGUNGSREDUKTION — eine Regel für alles
--------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
:root { --wd-zeit-schnell: 0s; --wd-zeit: 0s; --wd-zeit-lang: 0s; }
.wd *, .wd *::before, .wd *::after {
animation-duration: .001ms !important;
animation-iteration-count: 1 !important;
transition-duration: .001ms !important;
scroll-behavior: auto !important;
}
/* Wichtig: die Einblend-Elemente müssen dann SOFORT sichtbar sein,
nicht "unsichtbar mit 0s Übergang". */
.wd-bereit .wd-auf { opacity: 1; transform: none; }
.wd-btn:hover, a.wd-karte:hover, .wd-karte--klickbar:hover { transform: none; }
}
/* Druckansicht: Angebote/Zusammenfassungen werden erfahrungsgemäß
ausgedruckt oder als PDF gesichert. */
@media print {
body.wd { background: #fff; color: #000; }
body.wd::before, body.wd::after, .wd-kopf, .wd-fuss, .wd-btn { display: none !important; }
.wd-karte { border: 1px solid #bbb; background: #fff; box-shadow: none; }
.wd h1, .wd h2, .wd h3, .wd p, .wd li { color: #000 !important; }
}
/* ---------------------------------------------------------------------
18. LEERER ZUSTAND IM KUNDENPORTAL
Ein leerer Bereich mit einem einzigen Satz ist eine verpasste
Gelegenheit. Wer hier zum ersten Mal landet, hat gerade sein Passwort
gesetzt und weiß noch nicht, was ihn erwartet — genau dann entscheidet
sich, ob die Seite souverän wirkt oder unfertig.
Deshalb zeigt der leere Zustand, WAS gleich hier stehen wird, statt
nur festzustellen, dass gerade nichts da ist.
--------------------------------------------------------------------- */
.po-leer { text-align: center; padding: clamp(1.6rem, 4vw, 2.6rem) clamp(1rem, 3vw, 2rem); }
.po-leer-symbol { width: clamp(64px, 12vw, 92px); margin: 0 auto .9rem; position: relative; }
.po-leer-symbol img { width: 100%; height: auto; opacity: .9; }
.po-leer-symbol::before {
content: ""; position: absolute; inset: -24%; z-index: -1; border-radius: 50%;
background: radial-gradient(circle, rgba(127,208,232,.26), transparent 70%);
filter: blur(20px);
}
.po-leer h3 { margin-bottom: .3em; }
.po-leer > p { max-width: 48ch; margin-left: auto; margin-right: auto; }
.po-leer-liste {
display: grid; grid-template-columns: repeat(2, 1fr); gap: .9rem;
margin: 1.6rem 0 1.2rem; text-align: left;
}
@media (max-width: 640px) { .po-leer-liste { grid-template-columns: 1fr; } }
.po-leer-punkt {
display: grid; grid-template-columns: auto 1fr; gap: .8rem; align-items: start;
padding: .9rem 1rem; border-radius: 14px;
background: rgba(127,208,232,.05); border: 1px solid var(--wd-rand);
}
.po-leer-nr {
width: 28px; height: 28px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-family: var(--font-head); font-weight: 800; font-size: .85rem;
color: var(--wd-blau); background: rgba(127,208,232,.12);
border: 1px solid var(--wd-rand-stark);
}
.po-leer-punkt strong { display: block; color: var(--wd-text); font-size: .98rem; margin-bottom: .15rem; }
/* :not(.po-leer-nr) ist hier PFLICHT, kein Feinschliff.
Der Zahlenkreis ist ebenfalls ein <span> in dieser Kachel. Ohne den
Ausschluss trifft ihn diese Regel mit -- und sie ist spezifischer
(Klasse + Element) als ".po-leer-nr" (nur Klasse). Sie erzwang dadurch
display:block, Schriftgroesse 14,4px und Zeilenhoehe 23px; die Ziffer
sass 15px neben der Kreismitte, statt darin.
Gemeldet am 22.08.2026 ("wieso sehen die zahlen immer noch so
scheisse aus?") und per Messung bestaetigt. Derselbe Spezifitaets-
Fehler wie zuvor beim Hauptknopf (blau auf blau) und bei den Namen auf
der Zugangswand -- deshalb steht die Begruendung hier so ausfuehrlich. */
.po-leer-punkt span:not(.po-leer-nr) { display: block; font-size: .88rem; color: var(--wd-text-soft); line-height: 1.5; }
.po-leer-fuss { margin: 0; }
/* ---------------------------------------------------------------------
19. VORSCHAU IM LEEREN PORTAL
Die erste Fassung BESCHRIEB, was hier bald stehen wird ("Eine Leiste
zeigt dir, in welcher Phase dein Projekt ist"). Beschreibungen sind
schwach — man muss sie lesen und sich dann etwas vorstellen.
Diese Fassung ZEIGT es: eine echte, halbdurchsichtige Projektkarte,
deren Phasenleiste langsam durchläuft. Man sieht in zwei Sekunden, was
drei Sätze nicht erklären. Genau das ist der Unterschied zwischen
"erklärt" und "verstanden".
Die Karte ist bewusst als Vorschau erkennbar (gedämpft, mit Etikett) —
sie darf nie mit einem echten Projekt verwechselt werden.
--------------------------------------------------------------------- */
.po-vorschau {
position: relative;
border-radius: var(--wd-r-gross);
padding: clamp(1.1rem, 2.6vw, 1.5rem);
background: linear-gradient(180deg, rgba(20,32,50,.5), rgba(9,15,26,.66));
border: 1px dashed var(--wd-rand-stark);
text-align: left;
overflow: hidden;
}
.po-vorschau::after {
/* Sanfter Lichtstreifen, der einmal langsam durchwandert. Er sagt ohne
Worte "hier passiert gleich etwas", ohne zu blinken oder zu zappeln. */
content: "";
position: absolute; inset: 0;
background: linear-gradient(105deg, transparent 35%, rgba(127,208,232,.07) 50%, transparent 65%);
background-size: 260% 100%;
animation: po-schimmer 5.5s ease-in-out infinite;
pointer-events: none;
}
@keyframes po-schimmer { 0% { background-position: 130% 0; } 60%, 100% { background-position: -130% 0; } }
.po-vorschau-etikett {
position: absolute; top: .7rem; right: .8rem;
font-size: .66rem; letter-spacing: .14em; text-transform: uppercase;
font-weight: 800; color: var(--wd-text-soft);
padding: .2rem .55rem; border-radius: 999px;
background: rgba(5,7,11,.7); border: 1px solid var(--wd-rand);
}
.po-vorschau-nr { font-family: var(--font-head); font-weight: 800; font-size: .78rem; color: var(--wd-blau); opacity: .75; }
.po-vorschau h4 { margin: .15rem 0 .6rem; font-size: clamp(1.05rem, 2.4vw, 1.25rem); color: var(--wd-text); opacity: .85; }
/* Die laufende Phasenleiste — der eigentliche Kern der Vorschau. */
.po-vorschau-phasen { display: flex; gap: 3px; margin-bottom: .5rem; }
.po-vorschau-phasen span {
flex: 1; height: 6px; border-radius: 999px;
background: rgba(127,208,232,.13);
animation: po-phase-lauf 7s ease-in-out infinite;
}
.po-vorschau-phasen span:nth-child(1) { animation-delay: 0s; }
.po-vorschau-phasen span:nth-child(2) { animation-delay: .55s; }
.po-vorschau-phasen span:nth-child(3) { animation-delay: 1.1s; }
.po-vorschau-phasen span:nth-child(4) { animation-delay: 1.65s; }
.po-vorschau-phasen span:nth-child(5) { animation-delay: 2.2s; }
.po-vorschau-phasen span:nth-child(6) { animation-delay: 2.75s; }
.po-vorschau-phasen span:nth-child(7) { animation-delay: 3.3s; }
@keyframes po-phase-lauf {
0%, 8% { background: rgba(127,208,232,.13); }
14%, 55% { background: var(--wd-blau-tief); }
100% { background: rgba(127,208,232,.13); }
}
.po-vorschau-zeile { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; font-size: .82rem; color: var(--wd-text-soft); }
.po-vorschau-marke {
display: inline-flex; align-items: center; gap: .3rem;
padding: .18rem .55rem; border-radius: 999px; font-size: .74rem; font-weight: 700;
background: rgba(127,208,232,.12); color: var(--wd-blau);
}
.po-vorschau-schritt { margin: .7rem 0 0; font-size: .88rem; color: var(--wd-text-mid); opacity: .8; }
/* Bewegungsreduktion: keine Animation, aber die Leiste soll trotzdem
etwas zeigen — sonst steht dort eine leere graue Reihe. */
@media (prefers-reduced-motion: reduce) {
.po-vorschau::after { animation: none; }
.po-vorschau-phasen span { animation: none; }
.po-vorschau-phasen span:nth-child(-n+3) { background: var(--wd-blau-tief); }
}
/* Die vier Merkmale kompakter und mit farbigem Akzent statt nur Nummer. */
.po-leer-punkt { transition: border-color var(--wd-zeit-schnell) ease, background var(--wd-zeit-schnell) ease; }
.po-leer-punkt:hover { border-color: var(--wd-rand-stark); background: rgba(127,208,232,.08); }
.po-leer-nr {
background: linear-gradient(135deg, rgba(127,208,232,.22), rgba(183,157,255,.18));
color: var(--wd-blau-hell); border-color: var(--wd-rand-stark);
}
/* ---------------------------------------------------------------------
20. LEERER ZUSTAND — GEHOBENE FASSUNG
Drei Rückmeldungen vom 22.08.2026, alle drei berechtigt:
"Schrift und Kacheln sollen viel spezieller sein", "die Zahlen sollen
besser im Kreis sein", "die Kisten sollen eine spezielle Farbe
bekommen wenn sie fertig sind".
Der letzte Punkt war der wichtigste und inhaltlich der schwerste:
Vorher waren erledigte und laufende Phase fast gleich blau. Damit ging
die einzige Information verloren, die die Leiste überhaupt trägt —
nämlich WO man gerade steht. Jetzt sind es drei klar verschiedene
Zustände: erledigt (grün), gerade dran (leuchtendes Blau mit Puls),
kommt noch (gedämpft).
--------------------------------------------------------------------- */
/* ---------- Zahlenkreise ----------
Vorher ein flacher Kreis mit Zahl. Jetzt ein doppelter Ring: außen ein
Farbverlauf als Rand, innen die dunkle Fläche. Das ist derselbe Kniff
wie bei den Karten (Verlauf über border-box) und lässt den Kreis
plastisch wirken, statt aufgemalt. */
.po-leer-nr {
width: 40px; height: 40px; border-radius: 50%;
font-size: 1.02rem; font-weight: 800;
color: var(--wd-blau-hell);
border: 2px solid transparent;
background:
linear-gradient(#0c1523, #0c1523) padding-box,
linear-gradient(140deg, var(--wd-blau), var(--wd-lila)) border-box;
box-shadow: 0 0 18px -6px rgba(127, 208, 232, .55);
flex-shrink: 0;
font-variant-numeric: tabular-nums;
letter-spacing: -.02em;
}
/* ---------- Merkmalskacheln ----------
Jede bekommt oben eine eigene Farbkante. Vier gleiche Kacheln wirken
wie eine Aufzählung; vier unterscheidbare wirken wie ein System. */
.po-leer-punkt {
position: relative;
overflow: hidden;
padding: 1.1rem 1.15rem 1.15rem;
border-radius: 16px;
gap: 1rem;
background: linear-gradient(180deg, rgba(20, 32, 50, .58), rgba(9, 15, 26, .74));
}
.po-leer-punkt::before {
content: "";
position: absolute; top: 0; left: 0; right: 0; height: 3px;
background: linear-gradient(90deg, var(--wd-blau-tief), var(--wd-blau));
opacity: .8;
}
.po-leer-punkt:nth-child(2)::before { background: linear-gradient(90deg, var(--wd-lila-tief), var(--wd-lila)); }
.po-leer-punkt:nth-child(3)::before { background: linear-gradient(90deg, #2e8f6b, var(--wd-ok)); }
.po-leer-punkt:nth-child(4)::before { background: linear-gradient(90deg, var(--wd-gold-tief), var(--wd-gold)); }
.po-leer-punkt:nth-child(2) .po-leer-nr {
color: var(--wd-lila);
background: linear-gradient(#0c1523, #0c1523) padding-box,
linear-gradient(140deg, var(--wd-lila), var(--wd-blau)) border-box;
box-shadow: 0 0 18px -6px rgba(183, 157, 255, .55);
}
.po-leer-punkt:nth-child(3) .po-leer-nr {
color: var(--wd-ok);
background: linear-gradient(#0c1523, #0c1523) padding-box,
linear-gradient(140deg, var(--wd-ok), var(--wd-blau)) border-box;
box-shadow: 0 0 18px -6px rgba(111, 214, 163, .5);
}
.po-leer-punkt:nth-child(4) .po-leer-nr {
color: var(--wd-gold);
background: linear-gradient(#0c1523, #0c1523) padding-box,
linear-gradient(140deg, var(--wd-gold), var(--wd-lila)) border-box;
box-shadow: 0 0 18px -6px rgba(232, 200, 119, .5);
}
/* ---------- Typografie ----------
Die Überschrift der Kachel war so groß wie der Fließtext darunter und
ging dadurch unter. Jetzt größer, enger gesetzt und mit einem Hauch
negativer Laufweite — das ist der Unterschied, den man als "wertig"
empfindet, ohne ihn benennen zu können. */
.po-leer-punkt strong {
font-family: var(--font-head);
font-size: 1.06rem; font-weight: 800;
letter-spacing: -.015em; line-height: 1.25;
margin-bottom: .3rem;
}
.po-leer-punkt span:not(.po-leer-nr) { font-size: .9rem; line-height: 1.6; }
.po-leer h3 {
font-size: clamp(1.5rem, 3.6vw, 2rem);
letter-spacing: -.02em;
background: linear-gradient(120deg, var(--wd-text), var(--wd-blau-hell) 70%);
-webkit-background-clip: text; background-clip: text; color: transparent;
}
.po-leer > p { font-size: 1.02rem; }
/* ---------- Phasen: drei klar verschiedene Zustände ----------
Das war der eigentliche Mangel. Erledigt und laufend sahen fast gleich
aus — damit ging die einzige Aussage der Leiste verloren. */
.po-phase, .po-vorschau-phasen span { height: 7px; }
.po-phase.po-erledigt {
background: linear-gradient(90deg, #2e8f6b, var(--wd-ok));
box-shadow: 0 0 8px -2px rgba(111, 214, 163, .5);
}
.po-phase.po-jetzt {
background: linear-gradient(90deg, var(--wd-blau-tief), var(--wd-blau));
box-shadow: 0 0 14px -2px rgba(127, 208, 232, .85);
animation: po-jetzt-puls 2.4s ease-in-out infinite;
}
@keyframes po-jetzt-puls { 0%, 100% { opacity: .82; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .po-phase.po-jetzt { animation: none; opacity: 1; } }
/* Dieselbe Logik in der Vorschau: die durchlaufende Leiste wechselt von
"gerade dran" (blau) nach "erledigt" (grün), statt einfach nur an- und
auszugehen. Damit erklärt die Vorschau die Farblogik gleich mit. */
@keyframes po-phase-lauf {
0%, 8% { background: rgba(127, 208, 232, .13); box-shadow: none; }
14%, 30% { background: linear-gradient(90deg, var(--wd-blau-tief), var(--wd-blau));
box-shadow: 0 0 12px -2px rgba(127, 208, 232, .8); }
38%, 62% { background: linear-gradient(90deg, #2e8f6b, var(--wd-ok));
box-shadow: 0 0 8px -2px rgba(111, 214, 163, .45); }
100% { background: rgba(127, 208, 232, .13); box-shadow: none; }
}
/* Kleine Legende unter der Vorschau, damit die Farben nicht geraten
werden müssen. Farbe allein ist nie Information. */
.po-legende {
display: flex; flex-wrap: wrap; gap: .5rem 1.1rem;
margin-top: .9rem; font-size: .78rem; color: var(--wd-text-soft);
}
.po-legende span { display: inline-flex; align-items: center; gap: .4rem; }
.po-legende i {
width: 16px; height: 6px; border-radius: 999px; display: inline-block;
}
.po-legende .po-l-fertig { background: linear-gradient(90deg, #2e8f6b, var(--wd-ok)); }
.po-legende .po-l-jetzt { background: linear-gradient(90deg, var(--wd-blau-tief), var(--wd-blau)); }
.po-legende .po-l-offen { background: rgba(127, 208, 232, .18); }
/* ---------------------------------------------------------------------
21. ZAHLENKREISE REPARIERT + VIER PROZESSFARBEN
a) "wieso sehen die zahlen immer noch so scheisse aus?"
Zu Recht. Die Ziffer sass nicht mittig im Kreis. Ursache war die
geerbte Zeilenhoehe: body.wd setzt line-height 1.7, und in einem
40px hohen Kreis erzeugt das einen Textkasten von rund 28px, der
die Ziffer nach unten drueckt. Zusaetzlich hing die Zentrierung an
einer weiter oben stehenden Regel — verlaesst man sich darauf, ist
man beim naechsten Umbau wieder verlassen.
Deshalb hier ALLES explizit: eigenes Raster, place-items, und vor
allem line-height: 1. Eine Ziffer in einem Kreis braucht genau die
Hoehe ihrer selbst, nichts sonst.
b) "es soll 4 farben geben wie 4 kategorien zum prozess"
Sehr gute Idee — und sie macht das System erst schluessig. Die
sieben Phasen sind in Wahrheit vier Abschnitte, und die vier
Merkmalskacheln tragen ohnehin schon vier Farben. Jetzt bedeuten
diese Farben ueberall dasselbe:
1 Blau Start Briefing, Angebot
2 Lila Gestaltung Design
3 Gruen Umsetzung Entwicklung, Tests
4 Gold Abschluss Abnahme, Uebergabe
Damit ist die Farbe nicht mehr Dekoration, sondern Sprache: Wer
Gold sieht, weiss, dass es auf die Zielgerade geht.
--------------------------------------------------------------------- */
/* ---------- a) Der Kreis ---------- */
.po-leer-nr {
display: grid;
place-items: center;
width: 42px; height: 42px;
padding: 0;
border-radius: 50%;
/* Der entscheidende Wert: ohne ihn erbt die Ziffer 1.7 und rutscht. */
line-height: 1;
font-family: var(--font-head);
font-size: 1.15rem;
font-weight: 800;
letter-spacing: 0;
font-variant-numeric: tabular-nums;
flex-shrink: 0;
border: 2px solid transparent;
background:
linear-gradient(#0d1624, #0d1624) padding-box,
linear-gradient(140deg, var(--wd-blau), var(--wd-lila)) border-box;
}
/* Die Ziffer selbst noch einmal optisch ausrichten: Zahlen haben oben
mehr Luft als unten, rein geometrisch zentriert wirken sie deshalb
leicht zu tief. Ein Hauch nach oben gleicht das aus. */
.po-leer-nr { padding-bottom: .06em; }
/* ---------- b) Die vier Prozessfarben ---------- */
:root {
--wd-p1: #7fd0e8; /* Start — Briefing, Angebot */
--wd-p2: #b79dff; /* Gestaltung — Design */
--wd-p3: #6fd6a3; /* Umsetzung — Entwicklung, Tests */
--wd-p4: #e8c877; /* Abschluss — Abnahme, Übergabe */
}
.po-leer-punkt:nth-child(1)::before { background: linear-gradient(90deg, #3d9dbd, var(--wd-p1)); }
.po-leer-punkt:nth-child(2)::before { background: linear-gradient(90deg, #7c5cd6, var(--wd-p2)); }
.po-leer-punkt:nth-child(3)::before { background: linear-gradient(90deg, #2e8f6b, var(--wd-p3)); }
.po-leer-punkt:nth-child(4)::before { background: linear-gradient(90deg, #a8873a, var(--wd-p4)); }
.po-leer-punkt:nth-child(1) .po-leer-nr { color: var(--wd-p1); background: linear-gradient(#0d1624,#0d1624) padding-box, linear-gradient(140deg, var(--wd-p1), #3d9dbd) border-box; box-shadow: 0 0 20px -7px var(--wd-p1); }
.po-leer-punkt:nth-child(2) .po-leer-nr { color: var(--wd-p2); background: linear-gradient(#0d1624,#0d1624) padding-box, linear-gradient(140deg, var(--wd-p2), #7c5cd6) border-box; box-shadow: 0 0 20px -7px var(--wd-p2); }
.po-leer-punkt:nth-child(3) .po-leer-nr { color: var(--wd-p3); background: linear-gradient(#0d1624,#0d1624) padding-box, linear-gradient(140deg, var(--wd-p3), #2e8f6b) border-box; box-shadow: 0 0 20px -7px var(--wd-p3); }
.po-leer-punkt:nth-child(4) .po-leer-nr { color: var(--wd-p4); background: linear-gradient(#0d1624,#0d1624) padding-box, linear-gradient(140deg, var(--wd-p4), #a8873a) border-box; box-shadow: 0 0 20px -7px var(--wd-p4); }
/* ---------- Die Phasenleiste spricht dieselbe Sprache ----------
Erledigte Phasen tragen die Farbe IHRES Abschnitts, nicht pauschal
Gruen. So sieht man auf einen Blick, wie weit man im Prozess ist —
und nicht nur, dass etwas erledigt wurde. */
.po-phase { background: rgba(127, 208, 232, .12); }
.po-phase:nth-child(1).po-erledigt, .po-phase:nth-child(2).po-erledigt { background: var(--wd-p1); box-shadow: 0 0 9px -3px var(--wd-p1); }
.po-phase:nth-child(3).po-erledigt { background: var(--wd-p2); box-shadow: 0 0 9px -3px var(--wd-p2); }
.po-phase:nth-child(4).po-erledigt, .po-phase:nth-child(5).po-erledigt { background: var(--wd-p3); box-shadow: 0 0 9px -3px var(--wd-p3); }
.po-phase:nth-child(6).po-erledigt, .po-phase:nth-child(7).po-erledigt { background: var(--wd-p4); box-shadow: 0 0 9px -3px var(--wd-p4); }
.po-phase:nth-child(1).po-jetzt, .po-phase:nth-child(2).po-jetzt { background: var(--wd-p1); box-shadow: 0 0 16px -2px var(--wd-p1); }
.po-phase:nth-child(3).po-jetzt { background: var(--wd-p2); box-shadow: 0 0 16px -2px var(--wd-p2); }
.po-phase:nth-child(4).po-jetzt, .po-phase:nth-child(5).po-jetzt { background: var(--wd-p3); box-shadow: 0 0 16px -2px var(--wd-p3); }
.po-phase:nth-child(6).po-jetzt, .po-phase:nth-child(7).po-jetzt { background: var(--wd-p4); box-shadow: 0 0 16px -2px var(--wd-p4); }
/* Die Vorschau zeigt denselben Verlauf: jede Phase leuchtet in der Farbe
ihres Abschnitts auf, wenn sie an der Reihe ist. */
.po-vorschau-phasen span:nth-child(1), .po-vorschau-phasen span:nth-child(2) { --po-f: var(--wd-p1); }
.po-vorschau-phasen span:nth-child(3) { --po-f: var(--wd-p2); }
.po-vorschau-phasen span:nth-child(4), .po-vorschau-phasen span:nth-child(5) { --po-f: var(--wd-p3); }
.po-vorschau-phasen span:nth-child(6), .po-vorschau-phasen span:nth-child(7) { --po-f: var(--wd-p4); }
@keyframes po-phase-lauf {
0%, 8% { background: rgba(127,208,232,.12); box-shadow: none; }
14%, 60% { background: var(--po-f); box-shadow: 0 0 12px -3px var(--po-f); }
100% { background: rgba(127,208,232,.12); box-shadow: none; }
}
/* ---------- Legende: vier Abschnitte statt drei Zustände ----------
Die alte Legende erklärte den Zustand (erledigt / läuft / offen). Der
ist aus der Position ohnehin ablesbar. Wertvoller ist, WAS gerade
passiert — deshalb erklärt sie jetzt die vier Abschnitte. */
.po-legende { gap: .45rem .9rem; font-size: .76rem; }
.po-legende i { width: 14px; height: 7px; }
.po-legende .po-l-1 { background: var(--wd-p1); }
.po-legende .po-l-2 { background: var(--wd-p2); }
.po-legende .po-l-3 { background: var(--wd-p3); }
.po-legende .po-l-4 { background: var(--wd-p4); }
/* =====================================================================
PORTAL — AUFGABENLISTE UND POSTFACH (22.08.2026)
"wenn sie drauf drücken sollen sie auch sehen was ich schon gemacht
habe von dem was im plan war."
Dieselben vier Prozessfarben wie auf der Ablaufseite, in der Vorschau
und in der Verwaltung. Das ist der eigentliche Wert: Eine Farbe
bedeutet im ganzen Bereich dasselbe — sonst wäre sie Dekoration.
===================================================================== */
/* Die grosse Zahl. "9 von 14 erledigt" ist greifbar, "64 %" ist eine
Rechnung, die niemand fühlt. */
.po-aufg-stand { margin: .9rem 0 .2rem; font-size: .92rem; color: var(--wd-text-soft); }
.po-aufg-stand b {
font-family: var(--font-head); font-weight: 800;
font-size: 1.7rem; color: var(--wd-text); margin-right: .3rem;
}
.po-fortschritt { display: flex; gap: 4px; height: 8px; margin-bottom: 1.2rem; }
.po-fs-teil { flex: 1; border-radius: 999px; background: rgba(255,255,255,.07); position: relative; overflow: hidden; }
.po-fs-teil > i { position: absolute; inset: 0 auto 0 0; border-radius: 999px; }
.po-fs-teil[data-k="start"] > i { background: var(--wd-p1); }
.po-fs-teil[data-k="gestaltung"] > i { background: var(--wd-p2); }
.po-fs-teil[data-k="umsetzung"] > i { background: var(--wd-p3); }
.po-fs-teil[data-k="abschluss"] > i { background: var(--wd-p4); }
/* ---------- "Das brauche ich noch von dir" ----------
Ein EIGENER Kasten ganz oben, nicht nur eine farbige Zeile irgendwo
in der Liste. Wer eine lange Liste sieht, liest sie als Bericht über
fremde Arbeit und überliest seinen eigenen Teil — und genau daraus
entstehen die meisten Verzögerungen.
Gold, weil es im ganzen Bereich für "das betrifft dich" steht. Nicht
Rot: Es ist eine Bitte, kein Fehler. */
.po-dubist {
margin: 0 0 1.3rem;
padding: .9rem 1rem 1rem;
border-radius: 14px;
background: rgba(232,200,119,.07);
border: 1px solid rgba(232,200,119,.32);
}
.po-dubist h4 {
margin: 0; font-size: 1rem; color: var(--wd-gold);
font-family: var(--font-head); font-weight: 700;
}
/* Der beruhigende Gegenpart. Wenn nichts offen ist, soll das auch
dastehen — Abwesenheit einer Aufforderung ist eine gute Nachricht und
darf ruhig ausgesprochen werden. */
.po-allesgut {
margin: 0 0 1.3rem; padding: .75rem .95rem;
border-radius: 12px; font-size: .9rem;
background: rgba(111,214,163,.08);
border: 1px solid rgba(111,214,163,.28);
color: var(--wd-ok);
}
/* ---------- Gruppen und Zeilen ---------- */
.po-aufg-gruppe { margin-bottom: 1.1rem; }
.po-aufg-kopf {
display: flex; align-items: baseline; gap: .5rem;
font-size: .74rem; letter-spacing: .13em; text-transform: uppercase;
margin-bottom: .45rem; padding-bottom: .35rem;
border-bottom: 1px solid var(--wd-rand);
}
.po-aufg-zahl { margin-left: auto; letter-spacing: 0; text-transform: none; font-size: .8rem; color: var(--wd-text-soft); }
.po-aufg-gruppe[data-k="start"] .po-aufg-kopf { color: var(--wd-p1); }
.po-aufg-gruppe[data-k="gestaltung"] .po-aufg-kopf { color: var(--wd-p2); }
.po-aufg-gruppe[data-k="umsetzung"] .po-aufg-kopf { color: var(--wd-p3); }
.po-aufg-gruppe[data-k="abschluss"] .po-aufg-kopf { color: var(--wd-p4); }
/* Zeile und Spalte ausdrücklich für JEDES Kind.
Ohne Spaltenangabe geht es schief, und zwar auf eine Art, die man
nicht errät: Das Raster platziert zuerst alle Elemente mit
FESTGELEGTER Zeile und erst danach die freien. Kästchen und Marke
haben beide eine feste Zeile — sie würden zusammen nach vorne rutschen
und der Titel landete ganz rechts. Genau das ist am 22.08.2026 in der
Verwaltung passiert und erst am Screenshot aufgefallen. */
.po-aufg {
display: grid;
grid-template-columns: auto minmax(0,1fr) auto;
gap: .12rem .7rem; align-items: start;
padding: .55rem .6rem; margin-bottom: .25rem;
border-radius: 10px; border: 1px solid transparent;
}
.po-aufg-haken { grid-row: 1 / span 2; grid-column: 1; }
.po-aufg-titel { grid-row: 1; grid-column: 2; font-size: .94rem; color: var(--wd-text); overflow-wrap: anywhere; }
.po-aufg-marken { grid-row: 1; grid-column: 3; }
.po-aufg-text { grid-row: 2; grid-column: 2 / span 2; font-size: .82rem; color: var(--wd-text-soft); line-height: 1.5; }
.po-aufg--fertig .po-aufg-titel { color: var(--wd-text-soft); text-decoration: line-through; text-decoration-thickness: 1px; }
.po-aufg--weg .po-aufg-titel { color: var(--wd-text-soft); text-decoration: line-through; opacity: .55; }
.po-aufg--du { background: rgba(232,200,119,.06); }
/* Im oberen Kasten stehen dieselben Punkte noch einmal. Dort brauchen
sie den eigenen Hintergrund nicht — der Kasten ist schon golden, ein
zweiter Goldton darin würde nur schmutzig wirken. */
.po-aufg--hervor { background: transparent; padding-left: 0; padding-right: 0; }
/* Das Kästchen. Bei eigenen Punkten ein echter Knopf (tastaturbedienbar,
44px Trefferfläche über das Innenabstands-Polster), sonst nur Anzeige.
Ein Knopf, der nichts tut, lässt die Seite kaputt wirken. */
.po-aufg-haken {
width: 26px; height: 26px; margin-top: .05rem; padding: 0;
border-radius: 8px; border: 2px solid var(--wd-rand-stark);
background: transparent; color: transparent;
display: grid; place-items: center;
font-size: .95rem; line-height: 1;
transition: all var(--wd-zeit-schnell) ease;
}
button.po-aufg-haken { cursor: pointer; }
button.po-aufg-haken:hover { border-color: var(--wd-gold); background: rgba(232,200,119,.1); }
.po-aufg-haken--fest { cursor: default; }
.po-aufg--fertig .po-aufg-haken { background: var(--wd-ok); border-color: var(--wd-ok); color: #06120c; }
.po-aufg--jetzt .po-aufg-haken { border-color: var(--wd-p2); color: var(--wd-p2); }
.po-aufg--weg .po-aufg-haken { border-style: dashed; color: var(--wd-text-soft); }
/* Offene EIGENE Punkte: der Rand ist golden, damit klar ist, dass hier
geklickt werden kann und soll. */
.po-aufg--du button.po-aufg-haken { border-color: rgba(232,200,119,.55); }
.po-aufg-marke {
display: inline-block; white-space: nowrap;
font-size: .68rem; letter-spacing: .05em; text-transform: uppercase;
padding: .14rem .45rem; border-radius: 999px;
}
.po-aufg-marke--ok { background: rgba(111,214,163,.13); color: var(--wd-ok); }
.po-aufg-marke--jetzt { background: rgba(183,157,255,.15); color: var(--wd-p2); }
.po-aufg-marke--du { background: rgba(232,200,119,.16); color: var(--wd-gold); }
.po-aufg-nicht {
display: inline-block; margin-left: .4rem;
font-size: .68rem; letter-spacing: .05em; text-transform: uppercase;
padding: .12rem .4rem; border-radius: 999px;
background: rgba(255,157,157,.12); color: var(--wd-fehler);
}
/* Auf dem Handy rutscht die Marke unter den Titel — nebeneinander bliebe
für den Titel eine Spalte von zwei Wörtern Breite. */
@media (max-width: 520px) {
.po-aufg { grid-template-columns: auto minmax(0,1fr); }
.po-aufg-marken { grid-row: 2; grid-column: 2; margin-bottom: .15rem; }
.po-aufg-text { grid-row: 3; grid-column: 2; }
}
/* ---------- Postfach auf der Übersicht ---------- */
.po-pf-verlauf {
max-height: 46vh; overflow-y: auto;
margin: .8rem 0 .2rem; padding-right: .3rem;
display: flex; flex-direction: column; gap: .5rem;
}