Files
dogfather-universe/assets/css/webdesign.css
T
DogFatherGitandClaude Opus 5 4b3ec450d5 Webdesign-Bereich: Fundament, oeffentliche Seiten, Zugangsschutz, PayPal
Umsetzung des "Website Masterplan" (16 Seiten) unter /webdesign.

Zugangsschutz mit EIGENER Schranke (server/webdesign-gate.js) statt gate.js:
gate.js laesst seit dem oeffentlichen Start am 21.08.2026 jeden durch, weil
die Pruefung auf SITE_PUBLIC_LAUNCH_AT als allererste Zeile steht. Haette man
/webdesign dahintergehaengt, waere der ausdruecklich nicht-oeffentliche Bereich
inklusive Preisen und spaeteren Kundendaten ab der ersten Sekunde fuer jeden
lesbar gewesen. Eigenes Sitzungs-Cookie, bereich="webdesign" im Token, damit
ein gueltiges Universe-Cookie hier NICHT gilt. 37/37 Tests.

Sieben oeffentliche Seiten in fuenf Sprachen (de, de-CH mit echtem Dialekt, en,
fr, pt). Preise, Zeitrahmen, Paketnamen und die 30-%-Regel stehen an genau
EINER Stelle in wd-core.js -- der Masterplan verlangt "ueberall
widerspruchsfrei", und vier Kopien laufen bei der ersten Preisaenderung
auseinander.

Als App installierbar auf Handy und PC. Der Service Worker speichert bewusst
KEINE HTML-Seite zwischen: nach dem Abmelden wuerden sonst geschuetzte Seiten
weiter ausgeliefert, ohne dass der Server je gefragt wird. 18/18 Tests.

Handy-Abnahme ueber alle Seiten in fuenf Breiten (320-1440) und fuenf Sprachen:
40/40. Der Test fand 35 echte Fehler (Touch-Ziele unter 44px), behoben im
Designsystem statt einzeln pro Seite.

PayPal (Wunsch 22.08.2026 "sofort auf meinem paypal"): Orders API mit
intent=CAPTURE, also sofortiger Einzug statt blosser Reservierung. Gebuehr und
Nettobetrag getrennt gespeichert. Betraege durchgehend als Ganzzahl in Cent.
Gefaelschte Webhooks werden abgewiesen. Fail closed solange Zugangsdaten
fehlen. 28/28 Tests gegen einen nachgebauten PayPal-Server.

Datenbank: 15 Tabellen mit Praefix wd_, fachlich vollstaendig vom Universe
getrennt.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 18:06:52 +02:00

852 lines
38 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;
}
/* ---------------------------------------------------------------------
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); }
.wd-abschnitt { padding: clamp(3.4rem, 7vw, 6.5rem) 0; position: relative; }
.wd-abschnitt--eng { padding: clamp(2rem, 4vw, 3.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);
/* Verhindert, dass lange deutsche Komposita ("Buchhaltungsverwaltungs-
seiten") auf dem Handy aus dem Kasten laufen. */
overflow-wrap: break-word;
hyphens: auto;
}
.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); }
.wd a { color: var(--wd-blau); text-decoration: none; }
.wd a:hover { color: var(--wd-blau-hell); }
.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; }
.wd-visuell-versteckt {
position: absolute; width: 1px; height: 1px; overflow: hidden;
clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
/* ---------------------------------------------------------------------
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.6rem;
border-radius: 999px;
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-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-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-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(3.5rem, 9vw, 7rem) 0 clamp(3rem, 6vw, 5rem); min-height: 78svh; 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; }
}