91 Commits
Author SHA1 Message Date
DogFatherGitandClaude Opus 5 37f1b4a8f5 Handy: Sicherheitsabstaende, Wisch-Reiter, zweispaltige Uebersicht
Der wichtigste Fund: env(safe-area-inset-*) stand bereits im CSS, lieferte
aber immer null -- viewport-fit=cover fehlte auf allen dreizehn Seiten.
Der Code sah richtig aus und tat nichts. Zusammen mit
apple-mobile-web-app-status-bar-style=black-translucent (schon gesetzt)
hiess das: installiert lag die Kopfzeile auf einem iPhone hinter Uhr und
Akkuanzeige.

Behoben:
- viewport-fit=cover auf allen 13 Seiten.
- Vier Sicherheitsabstaende zentral benannt statt an jeder Stelle
  einzeln geschrieben. Kopfzeile weicht der Statusleiste, Container dem
  seitlichen Notch im Querformat, Fusszeile der Gestenleiste.
- Der 'Ueberspringen'-Knopf des Vorspanns lag mit bottom:2rem praktisch
  AUF dem Entsperr-Strich (34px). Man haette die App verlassen statt
  uebersprungen.
- Eigener Zweig fuer den installierten Betrieb: kein Gummiband-
  Nachfedern (sieht in einer App nach einem Fehler aus), kein
  Installations-Hinweis.
- Die vier Sprungmarken auf der Rechtsseite waren 39px hoch -- fuenf
  unter dem Daumenmass. Ausgerechnet dort muss man zum Widerrufsrecht
  springen koennen.
- 'Waehle links einen Verlauf aus': Auf dem Handy gibt es kein links,
  die Liste steht darueber. Richtungswort entfernt.
- Sechs Reiter brauchten auf dem Handy drei Zeilen. Jetzt ein
  Wischstreifen mit Einrasten und Auslauf am Rand; der aktive Reiter
  wird herangeholt, wenn man ueber eine Kachel springt.
- Uebersicht zweispaltig statt zwoelf Zeilen untereinander: 2635px ->
  1924px. Eine Uebersicht, an der man vorbeiwischen muss, ist keine.

Geprueft mit 55 neuen Handy-Pruefungen auf iPhone 14 Pro, Pixel 7 und
320px Breite, jeweils im Browser und im installierten Zweig. Drei
Fehlalarme der eigenen Pruefung wurden begruendet ausgenommen (Honigtopf
bei left:-9999px, Eingabefeld in einer Beschriftung, Inline-Link im
Fliesstext -- WCAG 2.5.8 nimmt letztere ausdruecklich aus).

Zwei Selbstkorrekturen an der Pruefung dokumentiert: Die Emulation von
display-mode wirkt nicht (Chromium nimmt den Befehl an und ignoriert
ihn) -- ohne das waeren die zwoelf 'installiert'-Zeilen ein zweiter
Browser-Durchgang gewesen. Und die Messung gegen die Systemleisten mass
zuerst die Kastenkante statt der Inhaltskante und meldete elf korrekte
Seiten als fehlerhaft. Eine Selbstpruefung mit einem absichtlich falsch
gesetzten Knopf belegt jetzt, dass die Messung echte Fehler findet.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 19:51:10 +02:00
DogFatherGitandClaude Opus 5 c1cb51884f Verwaltung: Übersicht als Startansicht, Reiter unter den Titel
Die Reiter standen neben dem Titel. Das las sich wie eine einzige lange
Zeile, in der der Titel nur der erste von sechs Knöpfen zu sein schien --
man sah nicht auf einen Blick, in welchem Bereich man war. Jetzt zwei
Zeilen: oben WO man ist, darunter WOHIN man kann.

Die Verwaltung öffnete bisher mit der Anfragenliste. Eine Liste ist eine
Ablage: Sie zeigt, WAS es gibt, nicht was zu TUN ist. Neu ist ein
Cockpit, das in drei Stufen antwortet -- was auf mich wartet, was beim
Kunden liegt, wie es ums Geld steht -- und dann laufende Projekte mit
Fortschritt sowie den Verlauf.

Zwei Grundsätze machen die Zahlen brauchbar: Getrennt nach 'wartet auf
mich' und 'wartet auf den Kunden' (zwölf offene Punkte sind entspannt,
wenn elf beim Kunden liegen). Und das ALTER färbt, nicht die Menge --
vier neue Anfragen sind kein Problem, eine seit sechs Tagen liegende
schon. Ein offener Widerruf ist immer rot, weil eine gesetzliche Frist
läuft.

Jede Kachel ist ein echter <button> und führt in den passenden Reiter.
Farbe ist nie der einzige Träger: Neben jedem farbigen Zustand steht der
Text ('älteste seit 8 Tagen').

Drei Fehler dabei gefunden und behoben:
- Der Titel wurde nur beim Klicken gesetzt. Frisch geladen zeigte die
  Seite das Cockpit, während darüber noch 'Projektanfragen' stand. Die
  Zuordnung Reiter->Titel liegt jetzt ausserhalb des Klick-Zuhörers.
- '.wd h2' überstimmte '.vw-ub-h': 44px Überschrift über 33px Zahl, die
  Seite las sich wie ein Plakat. Dieselbe Spezifitätsfalle wie früher
  bei '.wd a'.
- Eine Antwort mit ok:true aber ohne Inhalt riss die ganze Verwaltung
  mit. Wird jetzt abgefangen -- ein halber Server ist ein realistischer
  Fall.

Geprüft: 22 Serverprüfungen gegen eine echte Datenbank (inkl. vier
Fällen, die belegen, dass die Rechteprüfung wirklich greift), 56 im
Browser auf Computer und Handy, 69 im bestehenden Verwaltungstest,
0 Fundstellen im Design-/WCAG-Test, 5 im Farbsystemtest.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 19:21:12 +02:00
DogFatherGitandClaude Opus 5 4fe66e1e0e "Preise & Zeit" entfernt -- Inhalte in die Leistungen uebernommen
"leistungen und preis&zeit ist ja das gleiche, nimm die kategorie
preise&zeit komplett weg"

Stimmt bei den Paketen und Preisen: Beide Seiten zeigten dieselben
Zahlen. Zwei Orte fuer dieselbe Zahl sind eine Einladung, dass sie
irgendwann auseinanderlaufen -- und dann steht ein falscher Preis auf
der Seite, ohne dass es jemand merkt.

NICHT ALLES WAR DOPPELT

Vor dem Loeschen nachgesehen statt einfach geloescht. Zwei Abschnitte
gab es NUR dort:

  "Was den Preis bewegt"  -- beantwortet die Frage, die nach jeder
       Preisliste kommt: Warum kostet es bei mir mehr oder weniger?
       Ohne sie ist eine Preisspanne eine Behauptung.

  "Wie bezahlt wird"  -- Angebot, 30 % Anzahlung, Restbetrag, Betreuung.
       Rechtlich relevant und aus den AGB verlinkt.

Beide sind in die Leistungen umgezogen, samt ihrer 24 Textbausteine in
allen fuenf Sprachen. Waeren sie mitgeloescht worden, haette es niemand
sofort bemerkt -- und die Seite haette ab dann Preise genannt, ohne sie
zu erklaeren.

WEITERLEITUNG STATT 404

Die Adresse /webdesign/preise.html bleibt bedient und fuehrt auf die
Leistungen. Lesezeichen, alte Links aus Nachrichten und die installierte
App zeigen sonst ins Leere, und ein 404 auf einer Preisseite ist der
denkbar schlechteste erste Eindruck.

302 statt 301: Eine dauerhafte Weiterleitung merken sich Browser
hartnaeckig; sollte die Seite je zurueckkehren, muesste jeder Besucher
seinen Zwischenspeicher leeren.

EIN FEHLER BEIM EINBAU

Die Weiterleitung stand zuerst weiter unten in der Schranke, bei den
ohne Code erreichbaren Seiten. Dort haette sie nur fuer NICHT angemeldete
Besucher gegriffen -- wer angemeldet ist, passiert die Schranke vorher
mit next() und haette einen 404 auf die geloeschte Datei bekommen.
Genau die Person also, die die Seite am ehesten im Lesezeichen hat.
Jetzt steht sie ganz vorne, vor jeder Zugangspruefung.

GEPRUEFT: 10 Pruefungen -- beide uebernommenen Abschnitte erscheinen in
allen fuenf Sprachen, kein unuebersetzter Schluessel sichtbar. Kein
Verweis auf die alte Seite blieb irgendwo stehen (ablauf.html hatte
einen, der ist umgebogen). Gestaltung 0 Befunde, Textkodierung sauber,
Designsystem 5.

Versionsstempel und Cache auf v20.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 19:00:49 +02:00
DogFatherGitandClaude Opus 5 d6e75ce56a Kacheln: Licht folgt dem Zeiger, Rand glueht mit
"ich will das die kacheln richtig speziell sind und modern ... dass viel
mehr auffaellt und doch modern und profissionell"

Die Kacheln hatten Verlaufsrand, Verlaufsflaeche, Schatten und
Lichtkante -- alles richtig, alles STATISCH. Was fehlte, war das Gefuehl
von Material: eine Flaeche, die auf Licht reagiert.

ZWEI EBENEN

Ein weicher Lichtfleck folgt dem Zeiger ueber die Flaeche. Und -- der
Teil, der wirklich auffaellt -- der RAND glueht an derselben Stelle auf
und verlaeuft nach beiden Seiten aus.

Das geht ohne zusaetzliches Element: Die Kachel hat bereits zwei
Hintergrundebenen (Flaeche padding-box, Verlaufsrand border-box). Beim
Ueberfahren bekommt die Randebene einen Lichtpunkt an der Zeigerstelle.
Der Rand ist nur einen Pixel breit -- genau dort laesst sich Licht am
staerksten zeigen, ohne kitschig zu werden. Ein Lichtfleck OHNE
mitleuchtende Kante wirkt wie ein Fleck AUF der Kachel; mit ihr wirkt
die ganze Kachel beleuchtet.

Die Flaeche selbst bleibt beim Ueberfahren unveraendert -- sonst wuerde
der Text flackern.

VIER ENTSCHEIDUNGEN GEGEN BILLIGE OPTIK

Die Farbe folgt der Kachel: blaue leuchten blau, lila lila. Sonst braeche
der Effekt die Farbordnung, die ueberall sonst Bedeutung traegt.

Nur bei echtem Zeiger (hover: hover, pointer: fine). Auf dem Handy gibt
es keinen; dort bliebe der Lichtfleck an einer zufaelligen Stelle kleben.

Aus bei prefers-reduced-motion. Auch wenn sich nichts bewegt: Etwas, das
dem Zeiger folgt, ist Bewegung.

Erste Fassung war mit 13 % zu zurueckhaltend -- am Screenshot geprueft
und auf 22 % angehoben. "Man soll es spueren" ist richtig, aber es muss
auch ankommen.

SPARSAM GEBAUT

EIN Zuhoerer am Dokument statt einem je Kachel -- sonst muesste jede
nachgeladene Kachel einzeln nachgeruestet werden. Geschrieben wird erst
im naechsten Bildaufbau: Der Zeiger meldet sich bis zu tausendmal je
Sekunde, der Bildschirm zeichnet sechzigmal; ohne Drosselung rechnet der
Browser neunhundertmal umsonst.

Der Inhalt bekommt z-index 1. Ohne das legt sich der absolut gesetzte
Lichtfleck ueber den Text -- absolut positionierte Elemente malen ueber
Fluss-Inhalt, auch wenn sie im Quelltext davor stehen. Das Ergebnis waere
ein Schleier auf der Schrift, den man erst beim Vergleich zweier Kacheln
bemerkt. Eigens geprueft.

GEPRUEFT: 7 Pruefungen fuer den Effekt selbst -- unsichtbar im
Ruhezustand, erscheint beim Ueberfahren, folgt dem Zeiger auf 6 Pixel
genau, Inhalt liegt darueber, lila Kacheln leuchten lila, bei
Bewegungsempfindlichkeit vollstaendig abgeschaltet.

Gestaltung 0 Befunde, Designsystem 5, Verwaltung 69, Portal 32.

Versionsstempel und Cache auf v19.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 18:53:05 +02:00
DogFatherGitandClaude Opus 5 e495542fe5 Typografie: Lesebreite begrenzt -- 105 zu breite Absaetze behoben
Gemessen ueber alle Seiten: 105 von 200 Textabsaetzen waren zu breit,
der schlimmste mit 151 Zeichen pro Zeile.

WARUM DAS ZAEHLT

Beim Zeilensprung muss das Auge zurueck an den Zeilenanfang finden. Je
laenger die Zeile, desto haeufiger landet es in der falschen -- man
liest eine Zeile doppelt oder ueberspringt eine und merkt es erst zwei
Saetze spaeter. Der Text ist dann nicht "schwer", er ist schlecht
gesetzt.

Bewaehrt sind 45 bis 75 Zeichen. Das ist der aelteste und
bestbelegte Grundsatz der Typografie ueberhaupt -- jedes ordentlich
gesetzte Buch haelt sich daran.

Jetzt 68 Zeichen fuer Fliesstext, 60 fuer Kleingedrucktes. Die Einheit
ist ch statt Pixel: Damit haengt die Breite an der SCHRIFTGROESSE.
Kleingedrucktes bekommt automatisch einen schmaleren Block, grosse
Schrift einen breiteren -- beide landen bei aehnlich vielen Zeichen.

max-width macht nie etwas breiter. In schmalen Karten und Spalten
aendert sich also nichts; die Regel greift nur dort, wo eine Zeile
wirklich ueber das Lesbare hinauswaechst. Ergebnis: von 105 auf 0.

DREI FEHLER BEIM EINBAU, ALLE VON DER MESSUNG GEFUNDEN

1. Zentrierter Text stand ploetzlich links. Eine Breitenbegrenzung
   zentriert den KASTEN nicht mit -- die Schrift war mittig, ihr Kasten
   klebte am linken Rand, mit 384 Pixeln Luft rechts und null links.
   Gefunden, weil die Pruefung den Abstand links mit dem rechts
   VERGLEICHT, statt nur zu zaehlen, ob zentriert ist.

2. Meine erste Regel deckte nur den Fall ab, dass das ELTERNELEMENT
   zentriert -- nicht den, dass der Absatz es selbst tut.

3. Und dann blieb einer uebrig, bei dem beides stimmte. Ursache: ein
   Inline-Stil "margin:1.2rem 0 0". Die Kurzschreibweise setzt links und
   rechts hart auf 0 und schlaegt jede Stilvorlage. 11 solche Stellen
   ueber fuenf Seiten auf margin-top umgestellt -- gemeint war ohnehin
   immer nur der Abstand nach oben.

Ausnahmen bewusst gesetzt: Nachrichtenblasen tragen ihre Breite schon
selbst, Tabellenzellen und Beschreibungslisten richten sich nach ihrer
Spalte, die Fusszeile ist mehrspaltig und ohnehin schmal.

ALLES GRUEN: Gestaltung 0 Befunde, Designsystem 5, Verwaltung 69,
Portal 32, Widerruf 58, Anfragedetail 20.

Versionsstempel und Cache auf v18.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 18:47:34 +02:00
DogFatherGitandClaude Opus 5 10a075cc33 Gestaltung: Hoehensystem -- mehrschichtige Schatten und Lichtkante
Bis hierher trug jede Karte EINEN Schatten. Das ist solide und genau der
Grund, warum eine Oberflaeche "ordentlich" statt "teuer" wirkt.

Echtes Licht erzeugt zwei Dinge gleichzeitig: einen engen, dunklen
Kontaktschatten an der Kante -- er sagt dem Auge, dass etwas AUFLIEGT --
und einen weiten, weichen Umgebungsschatten, der sagt, wie HOCH es
darueber schwebt. Nur einen von beiden zu setzen sieht aus wie ein
Aufkleber; beide zusammen ergeben einen Gegenstand.

Dazu die LICHTKANTE: eine 1 Pixel hohe, sehr schwache weisse Linie an der
Oberkante. Sie tut so, als kaeme das Licht von oben und braeche sich an
der Kante. Das ist das meistuebersehene Detail in dunklen Oberflaechen
und dasjenige mit der groessten Wirkung -- ohne sie wirkt eine Karte wie
ein Loch im Hintergrund, mit ihr wie ein Stueck Material.

Drei Stufen, mehr braucht es nicht: ruhende Flaechen, hervorgehobene
Flaechen, Schwebendes. Dazu eine vierte, umgekehrte fuer Eingabefelder:
Die liegen nicht AUF der Flaeche, sie sind hineingeschnitten -- oben
dunkel, unten hell.

Weil es die gemeinsamen Bausteine sind, wirkt es sofort auf allen 13
Seiten: Hauptseite, Portal und Verwaltung.

Dazu Feinheiten, die einzeln niemand bemerkt und in Summe den
Unterschied machen: Uebergaenge auf 160-180 ms verkuerzt (alles darueber
wirkt beim Ueberfahren traege), eigene Rueckmeldung beim Druecken,
optische Laufweitenkorrektur fuer grosse Ueberschriften (-.028em bei h1;
das Auge sieht bei 48px mehr Weissraum zwischen Buchstaben als bei 16px),
text-wrap: balance gegen einzelne Woerter in der letzten Zeile.

EIN FEHLER BEIM EINBAU, GEMESSEN STATT UEBERSEHEN

Nach dem ersten Durchgang hatten die Karten ihre Lichtkante, der
Hauptknopf nicht. Grund: Die Grundregel lautet
".wd .wd-btn--haupt, .wd-btn--haupt" -- der erste Teil zaehlt ZWEI
Klassen. Mein Nachtrag zaehlte eine und verlor, obwohl er spaeter steht.
Dieselbe Falle wie am 22.08.2026 bei ".wd a" gegen ".wd-btn--haupt".
Aufgefallen nur, weil die Pruefung die Lichtkanten ZAEHLT.

PRUEFWERKZEUGE ANGEPASST

diagnose.html ist jetzt ausgenommen. Sie traegt bewusst alles fest in
sich -- eigene Farben, keine Uebersetzung -- weil sie funktionieren muss,
wenn genau das kaputt ist, was sie untersucht. Sie an den Regeln der
eigentlichen Seite zu messen erzeugte zwei Meldungen, die man auf Dauer
wegsieht. Und irgendwann sieht man dann auch eine echte weg.

ALLES GRUEN: Gestaltung 0 Befunde (12 Seiten x 5 Sprachen gegen
WCAG 2.2 AA), Designsystem 5, Verwaltung 69, Portal 32.

Versionsstempel und Cache auf v17.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 18:37:17 +02:00
DogFatherGitandClaude Opus 5 a964a078f0 Zahlungen: Verwaltung sticht Serverdatei -- der Schalter wirkt jetzt
Filipes Bildschirm zeigte alles, was noetig war, um es zu erkennen:

  Betriebsart: hinterlegt (auf dem Server) . 7 Zeichen
  Client ID:   hinterlegt . 82 Zeichen
  Secret:      hinterlegt . 80 Zeichen
  Fehler:      "PayPal hat die Anmeldung abgelehnt."

7 Zeichen sind "sandbox". Der Wert kam aus der .env, und die hatte
Vorrang. Sein Klick auf "Echtbetrieb" blieb wirkungslos -- seine echten
Zugangsdaten wurden gegen den TESTSERVER von PayPal geprueft, der sie
zwangslaeufig ablehnt.

Die Fehlermeldung zeigte dabei auf die Zugangsdaten ("stimmen Client ID
und Secret nicht zusammen") und damit in die voellig falsche Richtung.

DER ENTWURFSFEHLER

Ich hatte der .env bewusst Vorrang gegeben, damit ein Fehlgriff im
Formular keine funktionierende Servereinstellung aushebelt. Das klingt
vorsichtig und war falsch:

Ein Formular mit Schaltern, die nichts bewirken, ist schlimmer als gar
kein Formular. Es behauptet eine Wirkung, die es nicht hat, und schickt
bei der Fehlersuche in die Irre.

Der Sinn dieser Ablage ist gerade, dass die Werte OHNE SSH gesetzt
werden koennen. Dann muss das, was dort steht, auch gelten.

Ungefaehrlich, weil diese Werte ausschliesslich der Webdesign-Bereich
liest. Das DogiCrew-Supporter-Abo hat sein eigenes Modul und liest
weiter direkt aus der Umgebung -- ein Eintrag hier kann es nicht
abschalten. Eigens geprueft.

AUCH DIE ANZEIGE WAR UNEHRLICH

Sie sagte nur "hinterlegt (auf dem Server)" und verschwieg, dass genau
dieser Wert die eigene Eingabe ueberstimmt. Jetzt steht dort, welche
Quelle GILT -- "aus der Serverdatei" oder "hier eingetragen" -- und bei
doppelter Belegung zusaetzlich "Serverwert wird nicht benutzt".

GEPRUEFT: 16 Pruefungen auf dem Server, alle bestanden. Darunter der
genaue Fall: Serverdatei sagt sandbox, Formular sagt live -> istLive()
wird WAHR. Und der Rueckweg: Feld leeren -> Serverwert greift wieder.

Beim Testen noch ein Werkzeugfehler behoben: Der Absturz von
better-sqlite3 beim Beenden verschluckte die gesamte gepufferte
Ausgabe -- der Test lief durch und sah aus, als waere er nie gestartet.
Jetzt schreibt er unumgepuffert.

Versionsstempel und Cache auf v16.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 18:12:50 +02:00
DogFatherGit ebe10b9c49 WIP Vorrang umgedreht (Test folgt auf dem Server) 2026-08-23 18:09:39 +02:00
DogFatherGitandClaude Opus 5 d870a9c1d7 PayPal: falsche Angabe zur Webhook-ID berichtigt, Abo-Plan-Weg ergaenzt
Filipe: "webhook id faengt bei mir nicht mit w an und wo finde ich plan
fuer betreung"

Er hat recht, ich hatte unrecht. An der Quelle nachgeprueft:

  Webhook-ID:   0NH55953DH663215D        -- OHNE Vorsilbe, ~17 Zeichen
  Ereignis-ID:  WH-3F562076HD293871E-... -- DIE beginnt mit WH-

Meine Anleitung und der Hinweistext im Formular behaupteten beide
"beginnt mit WH-". Wer sich daran haelt, sucht an der falschen Stelle
oder traegt eine Ereignis-Kennung ein -- und die Signaturpruefung
scheitert dann bei der ersten echten Zahlung, mit einer Meldung, die
nicht auf die Ursache zeigt.

Beide Stellen berichtigt, in der Anleitung mit ausdruecklichem Hinweis,
dass dort vorher etwas Falsches stand. Wer sie schon gelesen hat, soll
den Widerspruch erklaert bekommen und nicht stillschweigend eine andere
Fassung vorfinden.

ABO-PLAN: Der Grund fuer die Frage ist ein echter Stolperstein --
Abo-Plaene werden NICHT im Entwicklerbereich angelegt, sondern im
normalen Geschaeftskonto. Unter developer.paypal.com sucht man vergeblich.

Jetzt mit direkter Adresse (paypal.com/billing/plans), dem Weg ueber das
Menue und dem Schritt, den man am ehesten vergisst: den Plan nach dem
Speichern auch AKTIVIEREN. Ein gespeicherter, aber nicht aktivierter
Plan sieht fertig aus und funktioniert nicht.

Ausserdem klargestellt, dass dieser ganze Schritt entfaellt, wenn kein
monatliches Abo verkauft wird -- Anzahlung und Restbetrag laufen ohne.

Versionsstempel und Cache auf v15.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 18:04:55 +02:00
DogFatherGitandClaude Opus 5 9421bd5cfe Verwaltung: Endlosschleife bei abgewiesenem Ausweis behoben
DIE URSACHE FUER "die ganze seite haengt"

In ladeAnfragen stand seit Tagen dieser Code:

    if (!ausweisVersucht) {
      ausweisVersucht = true;
      var frisch = await ausweisHolen();
      if (frisch) {
        token = frisch; tokenSchreiben(token);
        ausweisVersucht = false;     // <-- VOR dem Neuversuch geloest
        return ladeAnfragen();       // <-- und ruft sich selbst auf
      }
    }

Die Sperre wird zurueckgesetzt, BEVOR der neue Versuch laeuft. Solange
der Ausweis akzeptiert wurde, fiel das nie auf. Weist der Server ihn
dagegen ab, dreht es sich unbegrenzt: Ausweis holen, 401, Ausweis holen,
401 -- ohne Fehlermeldung, ohne Anmeldemaske, nur ein Ladehinweis, der
zehn Minuten stehen bleibt. Die schlimmste Sorte Fehler: Sie sieht aus
wie Langsamkeit.

WARUM DER AUSWEIS ABGEWIESEN WIRD

Die Diagnose mit echtem Ausweis zeigte es eindeutig:
  Ausweis erhalten in 23 ms
  Einstellungen abrufen -> 401, {"ok":false,"error":"Kein Zugriff."}

Die Zugangswand stellt also aus, der interne Dienst lehnt ab. Beide
benutzen nicht dasselbe WEBDESIGN_API_SECRET. Auf dem oeffentlichen
Server ist es gesetzt (Fingerabdruck e7d63573174f661a); der interne ist
fuer mich nicht lesbar -- Filipe prueft das mit einem Befehl, der nur
den Fingerabdruck ausgibt, nie den Wert.

UND EIN FEHLER, DEN ICH SELBST EINGEBAUT HATTE

Die Erneuerung aus v12/v13 ersetzte bei jedem 401 den Schluessel durch
einen Ausweis -- auch dann, wenn er aus der Anmeldung mit dem
Zugangscode stammte. Bei untauglichem Ausweis wurde daraus ein
Totalausfall: Alle zehn Minuten ersetzte sie eine FUNKTIONIERENDE
Sitzung durch eine kaputte.

Eine Reparatur, die den Normalfall verschlechtert, ist keine.

Jetzt fuehrt die Seite mit, WOHER der Schluessel stammt. Eine
Code-Sitzung wird nie durch einen Ausweis ersetzt, und die vorsorgliche
Erneuerung laeuft fuer sie gar nicht erst. Nach einem Neuladen gilt ein
vorhandener Schluessel vorsichtshalber als Code-Sitzung -- lieber einmal
zu viel nach dem Code fragen als eine laufende Sitzung zerstoeren.

Die Erneuerung sitzt jetzt an EINER Stelle (api()) mit genau einem
Neuversuch. Die zweite, aeltere Fassung in ladeAnfragen ist raus; zwei
Mechanismen, die sich gegenseitig den Schluessel ueberschreiben, waren
ein Teil des Problems.

GEPRUEFT mit genau dieser Lage -- Zugangswand stellt aus, interner
Dienst lehnt ab:
  2 Ausweis-Abrufe in 3 Sekunden statt unbegrenzt
  abgewiesener Ausweis fuehrt zur Codeeingabe statt zum Haengen
  Anmeldung mit Code oeffnet die Verwaltung
  sechs Reiterwechsel, null Rauswuerfe, null Ausweis-Abrufe
  Zahlungen-Kasten zeigt Inhalt

Verwaltung weiterhin 69 von 69. Versionsstempel und Cache auf v14.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 17:36:34 +02:00
DogFatherGit 4ad99b5c37 Diagnose: Volltest mit echtem Ausweis
Ein 401 ohne Anmeldung beweist nur, dass die Adresse existiert -- nicht,
dass die Antwort auch bei ANGEMELDETEM Zugriff kommt. Genau dort blieb
die Verwaltung stehen.

Die Diagnose geht jetzt denselben Weg wie die Verwaltung: Ausweis von
der Zugangswand holen, damit die Einstellungen abrufen, Zeit messen. Mit
eigenem Zeitlimit von 12 Sekunden, damit die Diagnose nicht selbst
haengt, wenn die Adresse haengt -- ein Pruefwerkzeug, das am selben
Problem scheitert, ist wertlos.

Damit ist der Befund eindeutig statt vermutet: entweder 'Erfolgreich in
X ms', oder eine Statusnummer samt Antworttext, oder 'KEINE Antwort
innerhalb von 12 Sekunden'.
2026-08-23 17:30:23 +02:00
DogFatherGitandClaude Opus 5 2ec935ccc6 Verwaltung: Ausweis vorsorglich erneuern statt erst nach dem Fehlschlag
"wenn ich von postfach auf projekte oder so gehe da werd ich immer wieder
mien zugangscode gefragt ... ich will nur den zugangscode anfrage wenn
ich auf die seite will und fertig"

Die Wiederholung bei 401 (v12) rettet zwar jeden Fall, greift aber erst,
NACHDEM eine Anfrage abgewiesen wurde: ein unnoetiger Umlauf, und
solange steht ein Ladehinweis auf dem Schirm.

Jetzt laeuft der Ausweis gar nicht erst ab. Er gilt 15 Minuten, erneuert
wird alle 10 -- mit Abstand, damit ein langsamer Netzzugang nicht ins
Zeitfenster hineinlaeuft. Im Hintergrund pausiert die Erneuerung, das
waere Verschwendung.

Dazu beim Zurueckkommen ins Fenster: War der Rechner zwischendurch zu,
ist der Ausweis mit Sicherheit abgelaufen. Dann soll der erste Klick
sofort sitzen statt ueber einen Fehlschlag zu gehen. Beim schnellen Hin-
und Herwechseln zwischen zwei Fenstern passiert nichts -- unter einer
Minute wird nicht erneuert.

Die Codeeingabe erscheint jetzt nur noch in genau zwei Faellen: beim
ersten Betreten der Seite und wenn die Zugangssitzung wirklich abgelaufen
ist (8 Stunden oder Seite geschlossen). Genau so war es gewuenscht.

GEPRUEFT: sieben Reiterwechsel hintereinander -- postfach, projekte,
kunden, zahlungen, anfragen, postfach, zahlungen -- und vor JEDEM wurde
der Ausweis kuenstlich fuer ungueltig erklaert. Null Codeabfragen, die
Verwaltung blieb offen, der Inhalt erschien. Verwaltung weiterhin
69 von 69.

Versionsstempel und Cache-Name auf v13.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 17:28:35 +02:00
DogFatherGitandClaude Opus 5 bd9051bfb7 Verwaltung: Ausweis erneuert sich selbst statt nach dem Code zu fragen
Rueckmeldung: "wieso werd ich auch immer meinen zugangscode gefragt wenn
ich die kategorie wechseln tue das ist schwachsin."

Er hat recht, und es war ein echter Fehler.

DIE URSACHE

Der Ausweis fuer die interne Schnittstelle (/webdesign/api-ausweis) gilt
15 Minuten. Danach antwortete jede Anfrage mit 401, und die Verwaltung
tat das Haerteste, was moeglich ist: Token verwerfen und Codeeingabe
zeigen -- beim blossen Wechsel eines Reiters.

Doppelt falsch:

  Die ZUGANGSSITZUNG selbst gilt 8 Stunden. Der Code war also gar nicht
  noetig; ein frischer Ausweis haette genuegt und war jederzeit
  abrufbar.

  Ein Rauswurf mitten in der Arbeit ist die haerteste denkbare Reaktion
  auf ein Problem, das sich unsichtbar loesen laesst. Wer gerade ein
  Angebot beziffert hat, verliert damit seinen Platz.

DIE LOESUNG

Bei 401 wird EINMAL ein neuer Ausweis geholt und die Anfrage wiederholt.
Nur wenn auch das scheitert, kommt die Codeeingabe -- dann ist die
Sitzung wirklich abgelaufen.

Das Wiederholen ist auch bei Absendungen unbedenklich: Eine mit 401
abgewiesene Anfrage hat serverseitig nichts bewirkt.

Alle gleichzeitig wartenden Aufrufe teilen sich EINEN Erneuerungsversuch.
Ohne das holt beim Oeffnen eines Reiters mit drei Abfragen jede ihren
eigenen Ausweis -- drei statt einem.

GEPRUEFT: 5 Pruefungen mit kuenstlich abgelaufenem Ausweis. Der
Reiterwechsel fragt NICHT mehr nach dem Code, der Inhalt erscheint
trotzdem, genau EIN neuer Ausweis wird geholt, und der naechste Wechsel
laeuft ebenfalls durch. Ist dagegen die Zugangssitzung selbst abgelaufen,
erscheint die Codeeingabe weiterhin -- das soll sie dann auch.

Verwaltung weiterhin 69 von 69.

Versionsstempel und Cache-Name auf v12.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 17:23:19 +02:00
DogFatherGitandClaude Opus 5 a5cd4bdcbd Diagnose: Normalzustaende nicht mehr als Befund melden
Filipes Diagnose zeigte zwei "!", obwohl alles in Ordnung war:

  ! Service Worker aktiv       -> 1 registriert
  ! Zwischenspeicher           -> dogfather-webdesign-v11
  ! Anmeldung Verwaltung       -> keiner vorhanden

Alle drei sind der NORMALFALL:

Ein aktiver Service Worker ist gewollt -- ohne ihn liesse sich die Seite
nicht als App installieren. Das war ausdruecklicher Wunsch.

Der Zwischenspeicher enthielt v11 -- also genau die Fassung, die der
Server ausliefert. Die erste Fassung meldete JEDEN gefuellten
Zwischenspeicher als auffaellig, auch den topaktuellen. Das ist
Panikmache, kein Befund.

Die Anmeldung gilt je Tab. In einem frisch geoeffneten Tab ist
zwangslaeufig keine da -- und sie SOLL beim Schliessen ohnehin
verschwinden, das war eine ausdrueckliche Vorgabe.

Ein Pruefwerkzeug, das den Normalzustand anmahnt, ist schlimmer als
keines: Es schickt einen auf die Suche nach einem Fehler, den es nicht
gibt -- und wenn dann einmal ein echter kommt, sieht er genauso aus wie
das Rauschen davor.

Jetzt liest die Diagnose die erwartete Fassung aus dem
Service-Worker-Skript auf dem Server und VERGLEICHT. Nur eine
Abweichung ist ein Befund.

GEPRUEFT mit beiden Faellen: bei v11 sechsmal gruen, bei kuenstlich
gesetztem v3 ein "!" mit beiden Fassungsnummern im Klartext.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 17:18:05 +02:00
DogFatherGitandClaude Opus 5 b9f6829a63 Diagnoseseite: Text landete im Statuskreis statt daneben
Filipes Screenshot zeigte den Beschreibungstext als schmale
Buchstabensaeule ueber die halbe Seite laufen. Die Ursache ist eindeutig
und mein Fehler:

  d.innerHTML = '<span class="mark">✓</span><div><b></b><span></span></div>';
  d.querySelector("span").textContent = text;

querySelector liefert den ERSTEN passenden span -- und das war der
Statuskreis, nicht das Textfeld darunter. Der gesamte Beschreibungstext
wurde also in einen 26 Pixel breiten Kreis geschrieben und lief dort
heraus.

Zwei Regeln machten es schlimmer:
  .zeile span { ... }   traf ebenfalls BEIDE spans
  fehlendes min-width:0 verhinderte, dass die Textspalte schrumpfen darf

Jetzt wird die Zeile Element fuer Element aufgebaut, mit direkten
Verweisen statt Suche -- da gibt es nichts zu verwechseln. Die
CSS-Regeln zielen auf eigene Klassen (.inhalt, .text) statt auf den
Elementnamen, der Kreis ist auf feste 26px genagelt und schneidet
ueberzaehligen Inhalt ab, statt die Seite aufzubrechen.

Auch die feste Platzhalterzeile im HTML nutzte noch den alten Aufbau und
haette denselben Fehler gezeigt, sobald sie sichtbar wird.

GEPRUEFT im Browser: alle sechs Zeilen, jeder Kreis exakt 26x26, Text
danebenstehend. Zusaetzlich als Screenshot angesehen -- bei einem
Anzeigefehler ist Messen allein nicht genug, denn genau das hatte die
erste Fassung ja auch bestanden.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 17:13:34 +02:00
DogFatherGitandClaude Opus 5 dd4010e75d Diagnoseseite: findet und behebt haengende Zwischenspeicher
Rueckmeldung: "garnichts laedt in der verwaltungsseite".

Geprueft statt geraten -- die Serverseite ist in Ordnung:
  Dienst aktiv, keine Fehler im Protokoll
  CORS-Vorabanfrage 204 mit allow-origin
  echte Anfrage 401 (korrekt ohne Anmeldung), Antwortzeit unauffaellig
  ausgelieferte Seite enthaelt den neuen Code

Damit bleibt fast nur der Browser: ein alter Service Worker, der
veraltete Dateien ausliefert. Er ueberlebt ein normales Neuladen, und
niemand kann ihn ohne Entwicklerwerkzeuge sehen.

webdesign/diagnose.html prueft sechs Dinge und sagt im Klartext, welches
davon klemmt: Service Worker aktiv? Zwischenspeicher gefuellt? Server
erreichbar und wie schnell? Kennt der Server die neuen Adressen
(404 = Server veraltet)? Liegt eine Anmeldung vor? Und wird die AKTUELLE
Gestaltungsdatei ausgeliefert -- erkennbar an einem Merkmal, das es erst
seit heute gibt.

Ein Knopf meldet den Service Worker ab, loescht die Zwischenspeicher und
laedt die Verwaltung mit Zeitstempel neu. Der Text sagt ausdruecklich,
dass Anmeldung und Daten unberuehrt bleiben -- sonst traut sich niemand
zu klicken.

ZWEI ENTSCHEIDUNGEN

Die Seite laedt KEINE externen Dateien, alles steht inline. Sie muss
funktionieren, wenn genau das kaputt ist, was sie untersucht -- eine
Diagnoseseite, die an derselben veralteten CSS-Datei scheitert, ist
wertlos.

Sie ist von der Zugangswand ausgenommen, wie Widerruf und Rechtstexte.
Gebraucht wird sie genau dann, wenn etwas klemmt; dann darf nicht
ausgerechnet die Zugangswand davorstehen. Sie enthaelt keine Kunden-
oder Projektdaten, sondern prueft nur den eigenen Browser und meldet
Statusnummern.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 17:10:54 +02:00
DogFatherGitandClaude Opus 5 d68d10d002 Zahlungen: Ladefehler sichtbar machen statt ewig "Wird geladen"
Rueckmeldung 23.08.2026: "da steht das aber passiert nichts" -- der
Reiter Zahlungen zeigte in beiden Kaesten dauerhaft "Wird geladen...".

Geprueft statt vermutet: Der Server antwortet (401 auf unangemeldete
Anfragen, Webhook 400), die ausgelieferte Seite enthaelt die Funktion,
und lokal nachgestellt laeuft der Ablauf sauber durch. Die Anfrage
bricht nach 15 Sekunden von selbst ab.

Der eigentliche Mangel liegt woanders und ist meiner: Ein Ladehinweis
ohne Ende ist die schlechteste aller Rueckmeldungen. Er sieht aus wie
Arbeit und ist doch nur Stillstand -- man kann nicht unterscheiden, ob
die Anfrage laeuft, fehlgeschlagen ist oder das Skript gar nicht
angesprungen ist. Und wenn der Fehler dann kommt, verschwindet er in
einer Meldung am Bildschirmrand.

DREI AENDERUNGEN

Jeder Fehler wird im Kasten selbst angezeigt, mit STATUSNUMMER im
Klartext ("Konnte nicht geladen werden (Status 403)"). Die kann Filipe
mir nennen, ohne die Entwicklerwerkzeuge zu oeffnen -- 403 heisst etwas
voellig anderes als 500 oder "keine Verbindung", und ohne diese Zahl
raet man.

Dazu ein Knopf "Nochmal versuchen". Bei einem Aussetzer im Mobilfunk ist
das der ganze Unterschied zwischen "geht nicht" und "geht doch".

Die statischen "Wird geladen..."-Texte im HTML sind raus. Der Kasten ist
jetzt leer, bis das Skript ihn fuellt -- und die Ladetexte lauten anders
als vorher. Bleibt spaeter der alte Text stehen, weiss man sofort: Die
Funktion ist nie angelaufen. Das ist eine Aussage, "Wird geladen" war
keine.

Auch die Zahlungsliste verschluckt ihren Fehler nicht mehr. Sie leerte
den Kasten stillschweigend -- ein leerer Bereich ohne Erklaerung ist
nicht weniger verwirrend als ein haengender Ladehinweis.

GEPRUEFT: alle vier Zustaende im Browser nachgestellt -- Serverfehler
500, kein Zugriff 403, Netzausfall und Erfolgsfall. In den ersten drei
erscheint Klartext samt Wiederholen-Knopf, im vierten der normale
Inhalt. Verwaltung weiterhin 69 von 69.

Versionsstempel und Cache-Name auf v11.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 17:07:35 +02:00
DogFatherGitandClaude Opus 5 6a2aa13dd8 PayPal ohne Konsole einrichten -- Formular in der Verwaltung
Auf die Frage "soll ich das Secret hier reinschicken?" ist die Antwort
nein: Es stuende dauerhaft im Gespraechsverlauf, und schreiben koennte
ich es trotzdem nicht (kein Zugriff auf /home/dogiintern, sudo nur fuer
apt/systemctl/docker). Risiko ohne Nutzen.

Der Fehler lag aber bei mir: Ich hatte SSH-Befehle als Loesung angeboten.
Filipe soll gar nicht in die Konsole. Jetzt traegt er die Werte in seiner
Verwaltung ein.

AUFBAU

lib/webdesign-geheimnisse.js legt die Werte verschluesselt in
app_settings ab -- derselbe AES-GCM-Weg wie fuer die Zugangscodes des
Universe. Wer die Datenbankdatei in die Haende bekommt, etwa ueber eine
alte Sicherung, hat damit nichts.

Die .env behaelt VORRANG. Sonst koennte ein Fehlgriff im Formular
stillschweigend eine funktionierende Servereinstellung aushebeln und
laufenden Zahlungsverkehr umleiten. Die Datenbank ergaenzt, was dort
fehlt -- sie konkurriert nicht.

Kein Neustart noetig: Nach jedem Speichern werden die Werte neu geladen.

DER KNIFF MIT DEM SYNCHRONEN ZUGRIFF

Entschluesseln ist asynchron, die Pruefungen des PayPal-Moduls
(istLive, istEingerichtet, fehlendeEinstellungen) sind synchron und
werden an einem Dutzend Stellen aufgerufen, teils mitten im Aufbau einer
Antwort. Sie alle auf async umzustellen waere ein Eingriff quer durch den
Bezahlvorgang gewesen -- viel Flaeche fuer Fehler genau dort, wo Fehler
Geld kosten.

Stattdessen werden die Werte einmal beim Start entschluesselt und danach
synchron gelesen. Alle 12 Zugriffe auf process.env.PAYPAL* im Modul
laufen jetzt ueber einen einzigen Zugriffspunkt.

WERTE KOMMEN NIE ZURUECK

Es gibt keinen Weg, ein gespeichertes Geheimnis wieder auszulesen. Die
Anzeige zeigt nur: ob etwas da ist, woher es stammt, wie lang es ist,
wann es zuletzt geaendert wurde. Das Formular leert sich nach dem
Speichern selbst -- ein Secret soll nicht stehen bleiben, wenn jemand
anders auf den Bildschirm schaut.

Ein leeres Feld bedeutet "nicht anfassen", nicht "loeschen". Sonst wuerde
das Nachtragen eines einzelnen Werts alle anderen leeren.

Nach jeder Aenderung wird das gemerkte PayPal-Zugangstoken vergessen --
sonst liefe die naechste Zahlung noch ueber die alten Zugangsdaten oder
scheiterte mit "invalid client".

"Verbindung testen" meldet sich probeweise bei PayPal an. Erst das
beweist, dass die Werte stimmen: "gesetzt" heisst nur, dass etwas
dasteht. Es fliesst dabei kein Geld.

GEPRUEFT: 23 Pruefungen auf dem Server, alle bestanden. Darunter die
wichtigsten Verneinungen: In der Datenbank steht kein Klartext, auch
kein Teil davon. Der Stand enthaelt das Geheimnis nicht. Ein fremder
Schluessel wird abgewiesen. Und: Ein gewechselter ENCRYPTION_KEY bringt
den Dienst NICHT zum Stehen -- der Wert gilt dann als nicht vorhanden,
die Seite laeuft weiter.

Verwaltung 69, Gestaltung 0 Befunde, Designsystem 5 -- unveraendert gruen.

Versionsstempel und Cache-Name auf v10.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 16:51:56 +02:00
DogFatherGit 5043642951 WIP: PayPal-Einstellungen ueber die Verwaltung (Test folgt auf dem Server) 2026-08-23 16:50:18 +02:00
DogFatherGitandClaude Opus 5 be3599239d Designsystem: eine Quelle je Farbe, Radien auf eine Skala
Diese Runde ging eine Ebene tiefer als "sieht es gut aus": Ist das
System, aus dem das Aussehen entsteht, ueberhaupt eines?

DIE MESSUNG VORWEG

  Markenfarben ausgeschrieben im Quelltext:  155 Stellen
    davon Blau 74, Gold 33, Lila 22, Gruen 16, Rot 10
  verschiedene Eckenradien:                   12
    darunter 5px, 7px, 9px, 11px

Die Farben gab es laengst als Variablen. Sie standen trotzdem ueberall
ausgeschrieben da, weil halbdurchsichtige Toene -- Raender, Leuchten,
sanfte Flaechen -- einen Alphawert brauchen, und das mit einer fertigen
Farbvariablen nicht geht: rgba(127, 208, 232, .16).

Die Folge waere beim ersten Farbwechsel sichtbar geworden: Man findet
150 Stellen, uebersieht fuenf, und die Seite hat danach zwei Blautoene,
die sich um eine Nuance unterscheiden. Genau das ist der Unterschied
zwischen einer gewachsenen und einer gestalteten Oberflaeche.

WAS GEAENDERT WURDE

Kanalvariablen (--wd-blau-rgb: 127 208 232) neben den fertigen Farben.
Damit schreibt man rgb(var(--wd-blau-rgb) / .16), und eine Aenderung
wirkt ueberall. 164 Stellen umgestellt, verteilt ueber CSS und neun
Seiten.

Auch die abgeleiteten Farben zeigen jetzt auf die Kanaele statt eigene
Werte zu fuehren -- und die vier Prozessfarben (--wd-p1 bis p4) sind
keine eigenen Farben mehr, sondern Rollen: --wd-p1: var(--wd-blau).
Sonst haette man vier weitere Stellen, die beim naechsten Farbwechsel
stillschweigend zurueckbleiben.

Ergebnis: Jede Markenfarbe hat genau EINE Quelle. Ausgeschriebene
Markenfarben im Quelltext: 0.

Radien auf vier Stufen plus Pillenform: 6 / 10 / 14 / 20 / 999. Kein
Wert wurde um mehr als 2px verschoben, optisch aendert sich also nichts
Spuerbares -- 12 verschiedene Werte sind auf 3 tatsaechlich verwendete
zusammengeschmolzen. Zwischenwerte wie 7px oder 11px entstehen nicht aus
Absicht, sondern weil man beim Bauen einer neuen Kachel nicht nachschaut,
was nebenan schon gilt.

DER BEWEIS, DASS ES EIN SYSTEM IST

Neue Pruefung pruef-system.mjs. Sie behauptet nicht, sie STELLT UM: Die
Markenfarbe wird von Babyblau auf kraeftiges Orange gesetzt und dann
nachgezaehlt, ob irgendwo der alte Ton stehen bleibt.

  658 von 1975 sichtbaren Elementen tragen die Markenfarbe
  0 bleiben nach der Umstellung beim alten Ton
  Prozessfarben folgen nachweislich mit
  Radien: 3 Stufen

UND DIE WICHTIGSTE ERKENNTNIS -- ueber das Messen selbst

Der erste Anlauf meldete 110 haengengebliebene Elemente, alle in Kopf-
und Fusszeile. Die naheliegende Erklaerung waere gewesen: "da steht die
Farbe noch ausgeschrieben". Sie war falsch.

Nachgewiesen ueber die DevTools-Schnittstelle: Auf diese Elemente wirkt
die Regel ".wd a:not(.wd-btn) -> var(--wd-blau)", und --wd-blau
resolviert an genau dieser Stelle korrekt zum neuen Orange. Trotzdem
blieb die berechnete Textfarbe alt -- auch nach erzwungener
Neuberechnung.

Der Unterschied: Kopf- und Fusszeile werden von wd-core.js per innerHTML
eingefuegt. Chromium erneuert solche Teilbaeume nicht zuverlaessig, wenn
man eine Variable NACHTRAEGLICH umstellt. Laedt man dieselbe Seite mit
bereits geaenderter Variable, sind sie orange -- gegengeprueft mit einem
Minimalbeispiel, in dem derselbe Mechanismus einwandfrei funktioniert.

Das Pruefverfahren wurde deshalb umgestellt: Die Variable wird VOR dem
Laden ueberschrieben. Das entspricht genau dem, was eine Aenderung in der
CSS-Datei bewirkt -- also dem Fall, um den es wirklich geht.

Haette ich der ersten Messung geglaubt, haette ich 110 einwandfreie
Stellen "repariert" und dabei das gerade aufgebaute System wieder
zerlegt. Es ist der siebte Fehlalarm in eigener Messtechnik innerhalb
von zwei Runden -- und der subtilste.

ALLE PRUEFUNGEN GRUEN: Gestaltung 0 Befunde (13 Seiten x 5 Sprachen
gegen WCAG 2.2 AA), Anfragedetail 20, Verwaltung 69, Portal 32,
Widerruf 58, Textkodierung 55 Kombinationen, Designsystem 5.

Versionsstempel und Cache-Name auf v9.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 13:05:12 +02:00
DogFatherGitandClaude Opus 5 3ca9f0b0cd Gestaltung: WCAG-Messung ueber alle Seiten, alle Befunde behoben
"Sieht gut aus" ist Geschmack und laesst sich nicht pruefen. Handwerkliche
Qualitaet laesst sich pruefen -- und bei einer WEBDESIGN-Seite ist sie
zugleich das Verkaufsargument: Wer selbst schludert, kann schlecht
Sorgfalt verkaufen.

Neues Werkzeug pruef-design.mjs misst 13 Seiten x 5 Sprachen auf
Handy-Breite gegen WCAG 2.2 AA -- denselben Standard, auf den auch das
Barrierefreiheitsstaerkungsgesetz verweist. Der Browser rechnet, es wird
nichts geschaetzt.

ERGEBNIS: 0 Befunde. Kontrast, Klickflaechen, Tastaturfokus,
Ueberschriftenstruktur, Bildalternativen, Feldbeschriftungen,
lang-Attribut, Schriftgroessen.

ECHTE BEFUNDE, DIE BEHOBEN WURDEN

1. 23 Schriftgroessen unter 12px (bis hinunter zu 10,9px), verteilt ueber
   CSS und sieben Seiten. Betroffen waren durchweg gesperrte
   Grossbuchstaben-Beschriftungen -- also genau die Textsorte, die klein
   ohnehin am schlechtesten lesbar ist. Alle auf mindestens 12px, die
   gesperrten auf 12,8px. Das ist zugleich die Dauervorgabe
   "augenschonend" ernst genommen.

2. Ueberschriftensprung h2 -> h4 in der Fusszeile, auf ALLEN 13 Seiten in
   allen 5 Sprachen (42 Stellen). Wer sich mit einem Screenreader durch
   die Ueberschriften bewegt, hoert dadurch eine Gliederung, die es nicht
   gibt, und vermutet uebersprungene Abschnitte. Jetzt h2 mit
   Gestaltungsklasse: Die Ebene sagt etwas ueber die STRUKTUR, die
   Groesse ueber die GEWICHTUNG -- zwei verschiedene Dinge.

3. code-Auszeichnung auf der Rechtsseite rutschte durch relative
   Groessenangabe auf 11,2px. Jetzt mit Untergrenze abgesichert.

SECHS FEHLALARME IM WERKZEUG -- ALLE GEFUNDEN UND BESEITIGT

Der erste Lauf meldete 302 Fundstellen. Fast alle waren falsch. Haette
ich sie "repariert", haette ich funktionierende Gestaltung zerstoert.
Jeder Fehlalarm hatte eine eigene, nicht offensichtliche Ursache:

  * Farbverlaeufe: getComputedStyle().backgroundColor liefert bei einer
    reinen Verlaufsflaeche "rgba(0,0,0,0)". Die Suche lief an der hellen
    Knopfflaeche VORBEI bis zum dunklen Seitengrund und verglich dunkle
    Schrift mit dunklem Grund -- Ergebnis 1:1 fuer 60 einwandfreie
    Knoepfe. Jetzt werden die Farbstopps ausgelesen und der
    unguenstigste Fall gerechnet.

  * MEHRERE Hintergrundebenen: Die Karten nutzen den bekannten Kniff
    "Flaeche padding-box, Rahmenverlauf border-box". Der helle
    Rahmenverlauf ist im Textbereich gar nicht sichtbar. Alle Ebenen
    zusammenzurechnen ergab 820 Meldungen mit Werten wie "3,45:1" fuer
    Text, der in Wahrheit ueber 7:1 liegt. CSS malt die ERSTE Ebene oben
    -- nur die zaehlt. Das Trennen an Kommas muss dabei die Kommas
    INNERHALB der Verlaufsklammern respektieren.

  * Verlaufsschrift (background-clip:text): Dort ist die Schriftfarbe
    durchsichtig und der Verlauf IST der Text. Farbe gegen Hintergrund zu
    vergleichen ergibt zwangslaeufig 1:1.

  * Verlaufsstopps mit wenig Deckkraft (9 % und 4 % Gold in den
    Hinweiskaesten) wurden verworfen statt auf den Untergrund gerechnet.
    Uebrig blieb "nicht messbar" fuer 72 Textstellen. Ein Pruefwerkzeug,
    das bei allem passt, prueft nichts.

  * Laufende Ueberblendungen: getComputedStyle liefert waehrend einer
    Ueberblendung den ZWISCHENWERT. Nach blur() verblasst der Fokusring
    ueber 0,16 s -- misst man sofort, sieht man ihn noch, und "vorher"
    ist identisch mit "nachher". Das Codefeld der Verwaltung wurde
    dadurch als "ohne sichtbaren Fokus" gemeldet. Nachgewiesen mit
    el.matches(":focus") === false bei gleichzeitig sichtbarem Schatten.
    Loesung: Ueberblendungen fuer die Messung abschalten.

  * Ausgeblendete Abschnitte: Eine Ueberschrift in einem versteckten
    Bereich hat selbst weiterhin display:block. Im Portal wurden dadurch
    drei h1 gezaehlt, obwohl immer nur eine sichtbar ist. Jetzt
    getClientRects().

Dazu zwei bekannte Muster, die das Werkzeug jetzt kennt: der Sprunglink
(absichtlich aus dem Bild geschoben) und die winzigen Auswahlfelder
hinter den Kacheln (die Kachel IST die Klickflaeche).

ALLE UEBRIGEN PRUEFUNGEN WEITERHIN GRUEN nach den Aenderungen:
Anfragedetail 20, Verwaltung 69, Portal 32, Widerruf 58, Textkodierung
55 Seiten-Sprach-Kombinationen.

Versionsstempel und Cache-Name auf v8.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 12:49:29 +02:00
DogFatherGitandClaude Opus 5 14ad108c87 Rechtliches: elektronische Widerrufsfunktion (§ 356a BGB), Impressum, AGB,
Widerrufsbelehrung und Datenschutz

RECHERCHIERT, NICHT AUS DEM GEDAECHTNIS

Der Webdesign-Bereich hatte KEINE eigene Rechtsseite -- obwohl dort
Vertraege geschlossen und Zahlungen ausgeloest werden. Die Fusszeile
verwies auf die Kontaktseite des Universe, die ein Content-Projekt
beschreibt, kein Dienstleistungsgeschaeft.

Die Web-Recherche hat eine Pflicht zutage gefoerdert, die seit zwei
Monaten gilt und die die Seite nicht erfuellt hat:

  § 356a BGB -- elektronische Widerrufsfunktion, in Kraft seit
  19.06.2026. Sie gilt fuer ALLE Fernabsatzvertraege, die ueber eine
  Online-Benutzeroberflaeche geschlossen werden, nicht nur fuer
  Finanzdienstleistungen.

WARUM DAS HIER GILT: Im Kundenportal nimmt der Kunde Zusatzangebote per
Klick VERBINDLICH an ("Damit nimmst du das Zusatzangebot verbindlich
an"). Das ist ein Vertragsschluss ueber eine Online-Benutzeroberflaeche.
Fuer die geplanten PayPal-Zahlungen gilt dasselbe.

Der Anbieter sitzt in Luxemburg. Fuer Verbraucher mit gewoehnlichem
Aufenthalt in Deutschland gilt nach Art. 6 Rom-I-VO trotzdem das
deutsche zwingende Verbraucherrecht, weil die Seite sich erkennbar an den
deutschsprachigen Markt richtet. Deshalb wurde der STRENGERE Standard
umgesetzt, nicht der bequemere.

WAS GEBAUT WURDE

webdesign/widerruf.html -- die Widerrufsfunktion, genau nach dem
Wortlaut der Vorschrift:
  * Beschriftung "Vertrag widerrufen" (gesetzlich vorgegeben)
  * ZWEITE Schaltflaeche "Widerruf bestaetigen" (ebenfalls vorgegeben --
    ein einstufiges Formular wuerde die Vorschrift nicht erfuellen)
  * unverzuegliche Eingangsbestaetigung mit Nummer, ZEITPUNKT (nicht nur
    Datum), Empfaenger und dem Wortlaut der Erklaerung
  * Link in der Fusszeile JEDER Seite -- "staendig verfuegbar,
    hervorgehoben platziert, leicht zugaenglich" heisst nicht "in den AGB
    versteckt"

Drei Entscheidungen, die unmittelbar aus dem Sinn der Vorschrift folgen:

  KEINE ANMELDUNG. Die Seite ist von der Zugangswand ausgenommen. Wer
  seinen Code verlegt hat, wuerde sonst seine Frist verlieren --
  Fristverlust durch eine selbstgebaute Huerde ist der schlimmste
  denkbare Fall.

  KEINE MENGENBEGRENZUNG. Ueberall sonst richtig, hier ein
  Rechtsverlust: Wer in der letzten Stunde seiner Frist wegen eines
  hakenden Netzes dreimal klickt, darf nicht abgewiesen werden.

  KEIN ZWISCHENSPEICHER. Beim Anfrageformular ein Segen, hier eine
  Falle: Auf einem geteilten Rechner laege der halb ausgefuellte Widerruf
  des einen im Browser des naechsten.

webdesign/rechtliches.html -- Impressum, AGB, Widerrufsbelehrung samt
Muster-Widerrufsformular, Datenschutzerklaerung. Alle Betreiberangaben
sind aus den bestehenden Seiten UEBERNOMMEN, nichts erfunden: Anschrift
in Mondercange, Kleinunternehmerregelung nach Art. 57 TVA-Gesetz LU und
Richtlinie (EU) 2020/285, netcup/Cloudflare, PayPal Luxemburg.

Migration 0014: wd_widerrufe (der dauerhafte Datentraeger und der
Nachweis, wird nie geleert) und wd_zustimmungen. Letztere speichert nicht
nur den Haken, sondern den WORTLAUT, den der Kunde gesehen hat -- die
Beweislast fuer die Zustimmung zum vorzeitigen Leistungsbeginn liegt beim
Unternehmer (§ 356 Abs. 4 BGB), und im Streit zaehlt, WAS bestaetigt
wurde. Bewusst OHNE Fremdschluessel: CASCADE wuerde den Nachweis mit dem
Kunden mitloeschen, RESTRICT wuerde eine DSGVO-Loeschung blockieren.

Druckansicht: Die Eingangsbestaetigung ist ein Rechtsnachweis. Auf Papier
schwarz auf weiss, ohne Navigation und Knoepfe -- ein Nachweis, den
niemand ausdruckt, weil er eine halbe Patrone kostet, erfuellt seinen
Zweck nicht.

ZWEI ECHTE FEHLER GEFUNDEN

1. Die Pflicht-Sternchen verschwanden nach der Uebersetzung. Ursache:
   data-i18n stand auf dem <label> selbst und ersetzte dessen ganzen
   Inhalt -- samt <span class="wd-pflicht">. Das Anfrageformular macht es
   laengst richtig (data-i18n auf einem INNEREN span); die neue Seite
   hatte das Muster nicht uebernommen. Aufgefallen ist es nur, weil der
   Test die Pflichtfelder GEZAEHLT hat statt sie vorauszusetzen.

2. window.WD.sprache() gibt es nicht, die Funktion heisst getSprache().
   Dadurch brach der Uebergang zur zweiten Stufe stumm ab.

GEPRUEFT: 58 Pruefungen, alle bestanden. Darunter die gesetzlich
vorgegebenen Beschriftungen in allen FUENF Sprachen, "kein Grund noetig",
genau drei Pflichtfelder, Datum UND Uhrzeit in der Bestaetigung, und die
Druckansicht.

WAS FILIPE NOCH PRUEFEN LASSEN MUSS: Diese Texte sind sorgfaeltig
recherchiert, aber ich bin keine Rechtsanwaeltin. Vor dem oeffentlichen
Start gehoert das Ganze einmal zu einer im luxemburgischen Recht
qualifizierten Fachperson -- besonders die grenzueberschreitende Lage
(Sitz LU, Kunden in DE/CH/FR/PT) und die Frage, ob die Seite in
Franzoesisch und Portugiesisch aktiv verkaufen soll. Dann muessen die
Rechtstexte auch dorthin uebersetzt werden, und zwar fachlich.

Versionsstempel und Cache-Name auf v7.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 12:29:09 +02:00
DogFatherGitandClaude Opus 5 98fc04c666 Verwaltung: Projektstand aendern, Wuensche beziffern, im Projekt antworten
Drei Server-Funktionen existierten seit Tagen und hatten KEINE Oberflaeche.
Erst im Vergleich "was kann der Server" gegen "was ruft die Seite auf"
ist es aufgefallen:

  POST /admin/projekte/:id           projektAendern
  POST /admin/aenderungen/:id/beziffern
  POST /admin/projekt-nachricht

Jede davon schliesst einen Kreis, der bisher offen war.

1. DIE SCHMERZHAFTESTE LUECKE: DER STAND

Der Kunde sieht in seinem Portal GANZ OBEN die Phasenleiste und den
"naechsten Schritt". Beides liess sich nirgends aendern. Ein Projekt blieb
also fuer immer im Briefing stehen, egal wie weit es wirklich war -- und
der prominenteste Text im ganzen Kundenportal war dauerhaft leer.

Jetzt: sieben Phasen als Knoepfe (plus Pausiert/Abgebrochen daneben, denn
das sind keine Phasen, sondern Zustaende), "wer ist am Zug", naechster
Schritt, Richttermin, Zahlungsstand, Portfolio-Freigabe.

Phase und "wer ist am Zug" speichern SOFORT ohne Speichern-Knopf: Es ist
ein Klick auf genau einen Wert, ein zweiter Klick waere Zeremonie. Die
Textfelder haben einen Knopf, weil man beim Tippen zwischendurch nicht
speichern will.

2. AENDERUNGSWUENSCHE

Der Kunde konnte Ideen einreichen, seit es das Portal gibt. Beziffern ging
serverseitig auch -- nur gab es keine Oberflaeche. Der Kreis war offen: Er
schickt etwas los und hoert nie wieder davon.

Jetzt stehen alle Wuensche im Projekt, offene mit Feldern fuer Preis,
Dauer und einer kurzen Erklaerung. Ohne Preis geht nichts raus (geprueft)
-- ohne Preis kann der Kunde nicht entscheiden, und ein "Angebot" ohne
Zahl ist keins.

3. NACHRICHTEN ZUM PROJEKT

Getrennt vom allgemeinen Postfach, weil sie zum Projekt gehoeren und im
Portal auch dort erscheinen. Sie hier nicht zu haben hiess: Der Kunde
schreibt im Projekt, und ich kann ihm nur woanders antworten.

AUFBAU

Neuer Endpunkt /admin/projekte/:id/alles liefert Projekt, Aufgaben,
Fortschritt, Aenderungswuensche und Nachrichten in EINER Antwort. Fuenf
Anfragen hintereinander wuerden die Ansicht sichtbar ruckelnd aufbauen.

Dieselbe Aufteilung wie in der Anfrageansicht -- links die Arbeit
(Aufgaben), rechts das Steuern. Wer zwischen beiden Ansichten wechselt,
muss nicht umdenken.

GEPRUEFT: 69 Pruefungen, Computer und Handy, alle bestanden.

Die neuen Pruefungen schauen nicht darauf, ob sich ein Knopf einfaerbt --
das beweist nichts. Sie schneiden mit, was die Seite TATSAECHLICH an den
Server schickt: {"status":"entwicklung"}, {"restBezahlt":true},
{"preisEuro":250,"dauer":"3 Tage"}. Und sie pruefen den Fall, in dem
nichts rausgehen darf: Ohne Preis bleibt die Mitschrift leer.

Ein Fehler im Test selbst behoben: Die Nachrichtenzaehlung war
document-weit und zaehlte die Nachrichten der geschlossenen Projektansicht
mit -- geschlossen heisst nicht aus dem Dokument entfernt. Jetzt auf den
Postfach-Verlauf eingegrenzt.

Versionsstempel und Cache-Name auf v6.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 12:08:57 +02:00
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 &amp;amp; Aenderungswuensche". Ursache ist
eine Falle mit zwei Wegen: Texte ueber data-i18n landen als HTML in der
Seite, dort ist "&amp;" 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 "&amp;" 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
DogFatherGitandClaude Opus 5 b7c333fca3 Verwaltung: Aufgabenlisten abhaken und Postfach
Schritt 3 von 4 zu den zwei Wuenschen vom 22.08.2026. Die Datenbank und
die Server-Routen standen schon; das hier ist die Seite, auf der ICH
arbeite. Was hier passiert, sieht der Kunde unmittelbar in seinem Portal
(Schritt 4).

ZWEI NEUE REITER

"Projekte" -- bisher gab es Projekte nur als Zahl neben dem Kunden
("3 Proj."), man konnte kein einzelnes oeffnen. Man denkt aber in
Projekten, nicht in Kunden. Neuer Endpunkt projekteListe liefert die
flache Liste samt Aufgabenzahlen; die einzeln nachzufragen haette bei
zwanzig Projekten einundzwanzig Anfragen bedeutet.

"Postfach" -- mit Abzeichen fuer Ungelesenes. Steht nichts an, ist das
Abzeichen GANZ weg statt eine 0 zu zeigen: Eine Null, die man taeglich
sieht, wird zu Rauschen, und irgendwann uebersieht man auch die 3.

Die Reiterumschaltung war vorher ein Ja/Nein zwischen zwei Ansichten. Mit
vier Reitern haette jede neue Ansicht eine weitere "hidden = ..."-Zeile
gebraucht -- und beim naechsten Reiter vergisst man eine, dann liegen zwei
Ansichten uebereinander. Jetzt eine Zuordnung Reiter -> Kasten, die sich
selbst aufraeumt.

AUFGABENLISTE

Vier Abschnitte in den vier Prozessfarben -- dieselben wie im Portal und
auf der Ablaufseite. Das ist der Punkt: Eine Farbe bedeutet ueberall
dasselbe, sonst waere sie Deko.

Ein Klick aufs Kaestchen schaltet weiter: offen -> in Arbeit -> erledigt.
Drei Zustaende ueber einen Knopf statt eines Auswahlfeldes -- beim
Abarbeiten einer Liste zaehlt jeder gesparte Klick.

Punkte, die auf den KUNDEN warten, sind golden hinterlegt und tragen eine
Marke. Ohne diese Unterscheidung liest man die Liste als reinen
Fortschrittsbericht und uebersieht, dass man selbst gar nicht am Zug ist.
Der goldene Grund verschwindet, sobald der Punkt erledigt ist -- er
braucht dann keine Aufmerksamkeit mehr.

Abhaken faerbt die Zeile sofort um, ohne auf den Server zu warten. Bei
zehn Punkten hintereinander waere ein Neuaufbau nach jedem Klick zaeh, und
man verliert die Stelle. Geht es schief, wird die Liste neu geholt und der
Zustand ist wieder ehrlich.

POSTFACH

Links Verlaeufe, rechts das Gespraech. Nicht aus Nachahmung, sondern weil
man ein Gespraech abarbeitet und nicht eine Zeile: Man will sehen, was
vorher besprochen wurde, waehrend man antwortet. Kunde links, eigene
Nachrichten rechts -- man erkennt den Absender an der Seite, bevor man den
Namen liest.

Der Schalter "Nur interne Notiz" faerbt das ganze Schreibfeld um. Ein
Haekchen allein uebersieht man, und eine interne Bemerkung, die beim
Kunden landet, ist der peinlichste Fehler, den dieses System machen kann.
Interne Notizen im Verlauf sind gestrichelt umrandet und golden -- sie
duerfen nicht wie etwas Gesendetes aussehen.

Strg+Enter sendet, Enter allein nicht: In einem mehrzeiligen Feld will man
Absaetze machen koennen, ohne dass die halbe Nachricht rausgeht.

EIN FEHLER, DEN DIE TESTS NICHT GEFUNDEN HABEN

Der erste Lauf meldete 37 von 37 gruen -- und jede Aufgabenzeile war
sichtbar falsch herum gebaut: Kaestchen, dann die kleinen Knoepfe, Titel
ganz rechts. Aufgefallen ist es erst am Screenshot.

Ursache: Das Raster platziert zuerst alle Elemente mit FESTGELEGTER Zeile
und erst danach die freien. Kaestchen und Knopfgruppe hatten beide
"grid-row: 1 / span 2" und wurden deshalb zusammen nach vorne gesetzt; der
Titel landete als letzter in der dritten Spalte. Jetzt bekommt jedes Kind
Zeile UND Spalte ausdruecklich.

Die eigentliche Lehre steckt im Test: Alle 37 Pruefungen betrafen
Bestandteile (Farben, Anzahl, Durchgestrichenes), keine einzige die
ANORDNUNG. Wer eine Anordnung baut, muss die Anordnung pruefen. Drei neue
Pruefungen vergleichen jetzt die tatsaechlichen Bildschirmpositionen --
und sie wurden gegengeprueft: Mit dem alten Zustand schlagen sie fehl,
mit dem neuen nicht. Ein Test, der nie fehlschlaegt, ist wertlos.

GEPRUEFT: 43 Pruefungen, Computer und Handy, alle bestanden. Darunter:
alle Touch-Ziele mindestens 24 px, interne Notiz sieht anders aus als eine
gesendete, Verlauf springt ans Ende, keine Fehler im Protokoll.

Versionsstempel und Cache-Name auf v4.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 23:30:11 +02:00
DogFatherGitandClaude Opus 5 9186d4cc1a Verwaltung uebersichtlicher, Bildlaufleiste dunkel
Rueckmeldung 22.08.2026 zur Anfrage-Detailansicht: "das ganze soll viel
uebersichtlicher sein und nicht so durcheinander" und "die leiste rechts
zum hoch und runter, kannst du die mal geil aussehen lassen anstatt
einfach so kake weiss."

1. DAS DURCHEINANDER HATTE EINE URSACHE

Die Kaesten standen in "columns: 2" -- Zeitungsspalten. Die fuellen sich
von selbst: erst Spalte eins bis oben voll, dann Spalte zwei. Wo ein
Kasten landet, haengt allein davon ab, wie lang die vor ihm sind. Bei
einer Anfrage stand "Interne Notizen" oben rechts, bei der naechsten
unten links. Es gab schlicht keine Ordnung, der man haette folgen koennen.

Jetzt ein festes Raster mit einer Aussage:
  LINKS  = was der Kunde geschickt hat   (lesen)
  RECHTS = was du damit machst           (handeln)

Immer gleich. Nach der zweiten Anfrage weiss man, wo man hinschaut, ohne
zu suchen. Rechts ist schmaler (Knoepfe brauchen weniger Platz als
laufender Text) und klebt beim Scrollen mit -- die Handlungen sind der
Grund, warum man die Ansicht oeffnet, sie duerfen nicht aus dem Bild
wandern.

Reihenfolge rechts korrigiert: "Anfrage uebernehmen" steht jetzt oben.
Es ist der Knopf, den man bei einer neuen Anfrage druecken WILL -- er
stand unter den Notizen und damit ausserhalb des sichtbaren Bereichs.

2. "KEINE ANGABE" WAR DIE HALBE ANSICHT

Jede fehlende Angabe bekam eine eigene Zeile. Der Kasten "Umfang"
enthielt zweimal nichts und war trotzdem so gross wie einer mit Inhalt.

Leere Felder sind aber keine Information, sondern deren Fehlen. Sie
stehen jetzt als EINE leise Zeile am Fuss: "Ohne Angabe: Bereiche,
Funktionen". Aus sechs Zeilen wird eine. Weggelassen werden sie nicht --
man muss sehen, wonach gefragt wurde und was unbeantwortet blieb, genau
daraus entstehen die Rueckfragen.

Neu darueber: "Auf einen Blick" mit Paket, Budget, Wunschtermin und
Alter. Die vier Fragen, die man immer zuerst hat, standen vorher auf drei
Kaesten verteilt. Das Alter als "vor 3 Tagen" statt als Datum -- die
Frage ist nie "welcher Tag war das", sondern "wie lange liegt das schon
hier", und die beantwortet ein Datum erst nach Kopfrechnen.

3. BILDLAUFLEISTE -- und ein Fehler, der fast durchgegangen waere

Auf einer durchgehend dunklen Seite ist eine weisse Bildlaufleiste der
einzige grelle Streifen im Bild. Sie zieht den Blick dorthin, wo nichts
Wichtiges steht, und blendet. Verstoesst gegen die Dauervorgabe
"augenschonend".

Zwei Wege noetig, weil kein Browser beide versteht: color-scheme: dark
fuer Firefox/Safari (wirkt zusaetzlich auf Auswahl- und Datumsfelder, die
sonst weiss aufblitzen), ::-webkit-scrollbar fuer Chrome/Edge.
scrollbar-width/-color bewusst NICHT gesetzt -- sobald es dasteht,
ignoriert Chrome die feineren ::-webkit-Regeln.

Beim ersten Versuch stand dort nur ".wd ::-webkit-scrollbar" -- MIT
Leerzeichen. Das trifft nur Elemente INNERHALB der Seite, nicht den body
selbst. Alle Messungen sahen gut aus; an der einen Leiste, ueber die sich
jemand beschwert hatte, haette sich nichts geaendert. Jetzt beide
Fassungen, mit einem Warnhinweis im CSS.

GEPRUEFT

Neue Datei pruef-detail.mjs: echter Browser, 1440x900 und 390x844, mit
einer absichtlich sehr knappen Anfrage -- genau die sah vorher schlecht
aus. 20 Pruefungen, alle bestanden: Spalten nebeneinander bzw. auf dem
Handy untereinander, rechte schmaler als linke, keine Ueberlappung, kein
waagerechtes Schieben, nichts ragt aus dem Fenster, keine einzelne
"keine Angabe"-Zeile mehr, keine Fehler im Protokoll.

Die Bildlaufleiste liess sich nur in einem ECHTEN Browserfenster pruefen:
Headless-Chromium blendet Leisten grundsaetzlich ueber dem Inhalt ein und
meldet deshalb immer 0 px Breite. Mit sichtbarem Fenster gemessen: 12 px,
alle sechs Regeln vom Browser akzeptiert.

Versionsstempel auf allen 11 Seiten und Cache-Name des Service Workers
auf v3 -- sonst liefert der eigene Zwischenspeicher beim ersten Laden
weiter die alte Fassung aus.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 23:05:47 +02:00
DogFatherGitandClaude Opus 5 71b9fc09c1 Anfrage-Detail: zentriertes Fenster statt seitlicher Leiste
Rueckmeldung 22.08.2026 mit Bildschirmfoto: "ich will das nicht so ich
will es viel viel viel besser und uebersichtlicher und schoener zentriert
in der mitte."

Berechtigt, und aus mehreren Gruenden. Eine seitlich eingeschobene Leiste
ist fuer so viel Inhalt das falsche Format:
  * Der Blick springt beim Oeffnen nach rechts.
  * Die Liste dahinter bleibt halb sichtbar und lenkt ab.
  * Alles muss sich in eine schmale Spalte quetschen -- auf dem
    Bildschirmfoto stand "keine Angabe" dadurch achtmal untereinander,
    und die Abwesenheit von Information nahm mehr Platz ein als die
    Information selbst.

Jetzt: mittig, 940px breit, zweispaltig ab Tablet. Der Blick bleibt, wo
er ist, und zusammengehoerende Angaben stehen nebeneinander.

Weitere Entscheidungen:
* Mauerwerk-Umbruch (columns) statt Raster. Die Abschnitte sind
  unterschiedlich hoch; ein Raster haette grosse Luecken gerissen.
* Jeder Abschnitt bekommt eine eigene Flaeche statt nur einer Trennlinie.
* Die Kopfzeile klebt beim Scrollen oben fest. Bei einer langen Anfrage
  weiss man sonst nach dem Scrollen nicht mehr, wessen Daten man liest.
* "keine Angabe" wird kleiner und blasser dargestellt. Es ist die
  ABWESENHEIT einer Information und darf nicht aussehen wie eine.
* Die Oeffnen-Animation skaliert dezent aus der Mitte statt von rechts
  hereinzufahren, und ist bei prefers-reduced-motion ganz aus.

9/9 Tests weiterhin gruen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 22:28:09 +02:00
DogFatherGitandClaude Opus 5 96458b58aa Anfrage mit einem Klick zu Kunde und Projektraum machen
Der wichtigste Handgriff im ganzen Bereich -- und der Weg, den man bei
JEDEM echten Kunden geht. Bisher haette man Name, E-Mail, Paket und
Wunschtermin von Hand in die Kundenmaske abgetippt: vier Gelegenheiten
fuer einen Tippfehler, und einer davon ist spaeter nicht mehr
korrigierbar, weil die E-Mail gleichzeitig der Anmeldename ist.

Jetzt steht in der Anfrage-Detailansicht eine Uebernahme mit Vorschau
(Kunde, E-Mail, Projekttitel, Sprache) und einem optionalen Preisfeld,
das die 30 % Anzahlung beim Tippen mitrechnet. Ein Klick legt an:
  * den Kundenzugang, freigeschaltet, in der Sprache der Anfrage
  * das Projekt, verknuepft mit der Anfrage, mit Wunschtermin und
    "Briefing-Termin vereinbaren" als erstem sichtbaren Schritt
  * die Anfrage wechselt automatisch auf "angenommen"
Danach springt die Ansicht auf "Kunden" und zeigt sofort den
Einladungslink -- den einzigen Weg, wie der Kunde an sein Passwort kommt.

Die beiden Schritte laufen bewusst nacheinander, nicht parallel: das
Projekt braucht die Kunden-Kennung. Schlaegt der zweite fehl, existiert
der Kunde trotzdem schon. Genau das sagt die Fehlermeldung dann auch
ausdruecklich -- sonst versucht man es blind noch einmal und scheitert an
der doppelten E-Mail-Adresse, ohne zu verstehen warum.

Ist aus einer Anfrage bereits ein Kunde geworden, erscheint statt der
Uebernahme ein Hinweis darauf. Zweimal denselben Kunden anzulegen soll
gar nicht erst angeboten werden.

Dabei denselben Anfuehrungszeichen-Fehler wie schon einmal gemacht und
behoben: das gerade " in „Kunden" beendet die JavaScript-Zeichenkette.
Typografisch richtig ist ohnehin das schliessende " -- beides in einem Zug.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 21:48:07 +02:00
DogFatherGitandClaude Opus 5 77674cb801 Kennzahlen der Verwaltung: aus stillen Zahlen werden Werkzeuge
Rueckmeldung 22.08.2026: "mach es noch krasser noch detaillierter noch
viel besser und perfekter und auch die kacheln viel geiler."

Die Kacheln waren eine Reihe stiller Zahlen. Zahlen, die man nur anschauen
kann, sind Dekoration. Jetzt:

* Jede Kachel FILTERT die Liste darunter beim Antippen. Als echter
  <button>, nicht als div mit Klickzuhoerer -- sonst ist sie mit der
  Tastatur nicht erreichbar und ein Screenreader kuendigt sie nicht als
  Bedienelement an.
* Jede Kachel sagt, was zu TUN ist, nicht nur wie viele es sind:
  "warten auf dich" / "du bist dran" / "Kunde ist dran" /
  "Projekt anlegen".
* Neue Kachel: der aelteste unbearbeitete Vorgang in Tagen. Das ist die
  ehrlichste Kennzahl ueberhaupt -- sie sagt nicht, wie viel man
  geschafft hat, sondern wie lange jemand schon auf Antwort wartet.
  Genau daran misst ein Kunde Zuverlaessigkeit. Ab sieben Tagen rot.
  Diese eine Kachel filtert bewusst NICHT und ist deshalb auch kein
  Knopf: sie zeigt einen Zustand, keinen Status.
* Eine Null wird gedaempft dargestellt. Sonst konkurriert "0 abgelehnt"
  optisch mit "3 neu" -- und genau die Drei ist die, auf die man schauen
  soll. Was nichts zu tun gibt, soll auch nicht leuchten.
* Gold bleibt ausschliesslich dem echten Handlungsbedarf vorbehalten.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 21:44:37 +02:00
DogFatherGitandClaude Opus 5 d93625439a Verwaltung: mehr Information pro Zeile statt leerer Flaeche
Rueckmeldung 22.08.2026 mit Bildschirmfoto: die Anfragenliste wirkte blass
und leer. Zu Recht -- sie zeigte Nummer, Name, Paket, Status, Datum. Das
ist korrekt, beantwortet aber nicht die Fragen, die man beim Draufschauen
WIRKLICH hat.

Jetzt steht in jeder Zeile:
* E-Mail direkt sichtbar (vorher musste man die Anfrage dafuer oeffnen)
* Paket, Budgetrahmen, Wunschtermin als eigene Marken
* Sprache, falls es NICHT Deutsch ist -- dann antwortet man auch in der
  richtigen Sprache
* ob daraus schon ein Kunde geworden ist

Statt eines Datums steht dort "vor 3 Tagen". Beim Datum muss man selbst
rechnen, wie lange jemand schon wartet -- und genau das ist die Frage,
die zaehlt. Ab sieben Tagen ohne Bearbeitung wird die Angabe rot: eine
Anfrage, die eine Woche liegt, ist ein verlorener Kunde.

Ein farbiger Streifen links codiert den Status zusaetzlich zur Textmarke.
Farbe ALLEIN waere fuer farbfehlsichtige Menschen keine Information --
zusammen mit dem Text ist sie ein schneller Anker beim Ueberfliegen.

Der leere Zustand stellt nicht mehr nur fest, dass nichts da ist, sondern
erklaert, WO Anfragen herkommen, und legt den Link zum Formular gleich
daneben.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 21:42:15 +02:00
DogFatherGitandClaude Opus 5 097e80b845 Projekte anlegen und ein leerer Zustand, der fuehrt statt zu enttaeuschen
Rueckmeldung 22.08.2026 mit Bildschirmfoto aus dem eigenen Testzugang:
"die seite soll jetzt schon bitte richtig krass sein und hoch profissionel,
auch sehr detailliert."

Zwei Luecken, beide geschlossen:

1) Projekte liessen sich nur ueber die Schnittstelle anlegen. Jetzt in der
   Verwaltung: pro Kunde ein "+ Projekt" mit Titel, Paket, Preis,
   Richttermin und naechstem Schritt. Bewusst als Einblendung direkt bei
   der Kundenzeile statt als eigene Seite -- man legt ein Projekt IMMER
   fuer einen bestimmten Kunden an, nie im luftleeren Raum. Der Kundenname
   steht deshalb gross im Formular, damit es nicht versehentlich dem
   Falschen angehaengt wird.
   Die 30 % Anzahlung wird beim Tippen live mitgerechnet. Sie wird zwar
   serverseitig berechnet, aber wer sie beim Eintippen sieht, merkt eine
   falsche Null sofort -- und nicht erst, wenn der Kunde ueberweisen soll.

2) Der leere Zustand im Portal war ein einziger Satz. Das ist eine
   verpasste Gelegenheit: Wer dort zum ersten Mal landet, hat gerade sein
   Passwort gesetzt und weiss noch nicht, was ihn erwartet -- genau dann
   entscheidet sich, ob die Seite souveraen wirkt oder unfertig. Jetzt
   zeigt er in vier Punkten, WAS gleich hier stehen wird (Projektstand,
   wer am Zug ist, Dateien und Nachrichten, Ideen jederzeit) und schliesst
   mit der Zusicherung, dass nichts zu tun ist. Fuenfsprachig.

45/45 Handy-Abnahme, i18n vollstaendig.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 21:40:27 +02:00
DogFatherGitandClaude Opus 5 74091590b8 Verwaltung: nur noch EINMAL den Code eingeben
Rueckmeldung 22.08.2026: "ich hab auf der verwaltungs seite 2 mal dass ich
den zugangscode eingeben muss und vanvan auch, ich will es nur einmal
eingeben muessen." Berechtigt.

Die Zugangswand hat serverseitig laengst geprueft, WER da ist -- Dogfather
oder VanVan, laut Masterplan S.4 beide gleichberechtigte
Volladministratoren. Ein zweites Passwort danach bringt keinen
zusaetzlichen Schutz, es kostet nur jedes Mal Zeit.

Warum es nicht einfach "Cookie mitschicken" ist: Die Verwaltungsdaten
liegen hinter postfach.dogfather-universe.com, einem ANDEREN Rechnernamen.
Das Sitzungs-Cookie gilt dort nicht -- so sind Cookies gebaut, und das ist
gut so.

Loesung: Die Zugangswand stellt unter /webdesign/api-ausweis einen
kurzlebigen, signierten Ausweis aus, den die interne API anerkennt.
  - 15 Minuten gueltig, die Seite holt bei Bedarf still einen neuen
  - traegt bereich="wd-admin", damit ein Sitzungs-Token der Zugangswand
    hier NICHT durchgeht und umgekehrt
  - nur mit gueltiger Zugangssitzung zu bekommen
  - gilt AUSSCHLIESSLICH fuer die /webdesign-Endpunkte. Postfach,
    Bewerbungen, Supporter und Teamverwaltung bleiben unberuehrt

Fehlt WEBDESIGN_API_SECRET auf einer der beiden Seiten, gilt kein Ausweis
und die Verwaltung fragt wie bisher nach dem Team-Code. Ein fehlender
Konfigurationswert darf niemals eine Tuer oeffnen -- nur eine schliessen.
Genau das prueft der letzte Testfall.

Bei einem 401 wird EINMAL still ein neuer Ausweis geholt und die Anfrage
wiederholt, statt jemanden mitten im Arbeiten rauszuwerfen.

10/10 Tests, darunter: gefaelschte Signatur, fremdes Geheimnis,
abgelaufen, falscher Bereich, erfundene Rolle.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 21:36:11 +02:00
DogFatherGitandClaude Opus 5 2542a2598e Kunden und Projekte in der Verwaltung anlegen, inklusive Testzugang
Wunsch 22.08.2026: "ich will einen provisorischen zugang fuer mich".
Der richtige Weg dahin war ohnehin ueberfaellig -- Kundenzugaenge
entstehen ausschliesslich hier, es gibt bewusst keine Selbstregistrierung.

Neu:
* Kundenzugang anlegen (Name, E-Mail, Firma, Sprache, sofort freischalten
  ja/nein) mit Einladungslink
* "Testzugang fuer mich" -- ein Klick, legt einen als Test erkennbaren
  Zugang mit Datumsstempel an. Bewusst NICHT die echte Geschaeftsadresse:
  die E-Mail ist gleichzeitig der Anmeldename und laesst sich aus gutem
  Grund nicht mehr aendern, ein Test wuerde also spaeter mit einem echten
  Kundenkonto kollidieren.
* Zugaenge auflisten, freischalten, sperren, neuen Einladungslink erzeugen
* Projekte anlegen und aendern, Aenderungswuensche beziffern, Nachrichten

Entscheidungen:
* Der Einladungslink geht EINMAL im Klartext raus, direkt beim Anlegen.
  In der Datenbank liegt nur sein Hash. Wer ihn verliert, bekommt einen
  neuen -- das ist sicherer, als ihn dauerhaft abrufbar zu halten. Die
  Oberflaeche sagt das auch klar dazu, sonst klickt man ihn weg und
  wundert sich.
* Ein neuer Link entwertet alle offenen alten. Sonst sammeln sich mehrere
  gueltige Generalschluessel fuer dasselbe Konto an.
* "Sofort freischalten" ist eine bewusste Handlung. Ohne Haekchen wird der
  Zugang angelegt, kommt aber noch nicht hinein -- Masterplan S.12
  verlangt, dass Projektkauf oder Betreuung VOR der Freischaltung geprueft
  werden.
* Sperren beendet laufende Sitzungen sofort, nicht erst nach Ablauf.
* Die 30 % Anzahlung werden aus dem Preis BERECHNET, nicht eingetippt.
  Ein Tippfehler in der Anzahlung faellt sonst erst beim Geldeingang auf.
* Preise kommen als Euro herein und werden sofort in Cent umgerechnet
  (Math.round, damit 49.99 nicht zu 4998 wird). Ab da nie wieder Komma.
* Vier klar unterscheidbare Zustaende in der Liste. Wichtig vor allem
  "Einladung offen": freigeschaltet, aber noch kein Passwort gesetzt --
  der Kunde war also noch nie drin.
* Kopieren faellt auf Markieren zurueck, wenn die Zwischenablage
  blockiert ist. Eine Fehlermeldung waere dort nutzlos.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 21:23:15 +02:00
DogFatherGitandClaude Opus 5 1b432f456f Kundenportal: Oberflaeche (Masterplan S.12)
Vier Ansichten in einer Seite: Anmeldung, Passwort festlegen ueber den
Einladungslink, Uebersicht, Projektdetail. 71 Textbausteine in fuenf
Sprachen.

Korrektur an einer frueheren Entscheidung: Ich hatte das Portal als "nur
Deutsch" eingestuft wie die Verwaltung. Denkfehler -- die Verwaltung
nutzen Dogfather und VanVan, das PORTAL nutzen Kunden, und die koennen
Franzosen oder Portugiesen sein. Jetzt fuenfsprachig, und die Sprache des
Kunden wird bei der Anmeldung automatisch uebernommen.

Gestaltungsentscheidungen:
* Eine Phasenleiste zeigt auf einen Blick, wo das Projekt steht. Das ist
  die haeufigste Frage ueberhaupt und der Grund, warum Kunden anrufen.
  Bei pausierten oder abgebrochenen Projekten wird KEINE Leiste gezeigt --
  ein Fortschrittsbalken waere dort irrefuehrend.
* Eine Marke sagt, wer gerade am Zug ist ("Wir warten auf dich" /
  "Dogfather ist dran"). Das beendet die haeufigste Unklarheit im
  Projektverlauf.
* Offene Zahlungen stehen ganz oben und in Gold -- das Einzige, was den
  Kunden wirklich zum Handeln auffordert.
* Rueckfrage nur beim ANNEHMEN eines Zusatzangebots, nicht beim Ablehnen.
  Annehmen erzeugt eine Zahlungspflicht, Ablehnen ist folgenlos.
* Abgelaufene Sitzung fuehrt zur Anmeldung mit klarer Ansage statt zu
  einer leeren Seite, die wie "du hast keine Projekte" aussaehe.
* Der Einladungslink wird nach Gebrauch aus der Adresszeile entfernt --
  er ist verbraucht und hat in der Chronik nichts verloren.
* Die Zahlungsknoepfe sagen ehrlich, dass PayPal noch eingerichtet wird,
  statt so zu tun als wuerde etwas passieren.

Pruefskript zweimal geschaerft, beide Male waren es Fehlalarme:
* Die Heuristik fuer Nachschlagetabellen hielt gewoehnliche Woerter wie
  "abnahme" und "uebergeben" fuer Woerterbuch-Schluessel. Jetzt muss ein
  Unterstrich im Namen sein, so wie bei allen echten Schluesseln.
* Eine Ueberschrift gilt jetzt auch als uebersetzt, wenn die Uebersetzung
  INNEN sitzt (fester Teil + dynamischer Teil).

i18n vollstaendig, 45/45 Handy-Abnahme.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 21:17:22 +02:00
DogFatherGitandClaude Opus 5 ae9878cb4c Sprungmarken auf breiten Bildschirmen alle in einer Reihe
Rueckmeldung 22.08.2026: "alle neben einander bitte". Vorher passten vier
in die Zeile und die fuenfte rutschte allein darunter -- das sieht aus wie
ein Versehen, nicht wie eine Gestaltung.

Ab 700px teilen sich jetzt alle fuenf den Platz zu gleichen Teilen
("flex: 1 1 0" statt "auto"). Mit "auto" waere "Preise & Zahlung" schmal
und "Inhalte & Zusammenarbeit" breit gewesen -- ungleiche Kacheln in einer
Reihe, also genau das, was hier schon einmal bemaengelt wurde.
"min-width: 0" ist dabei noetig, weil Flex-Elemente sonst nicht unter ihre
Inhaltsbreite schrumpfen und die Reihe trotzdem umbrechen wuerde.

Nachgemessen bei 700 / 900 / 1280 / 1440px: 5 Knoepfe, 1 Reihe, alle
gleich breit UND gleich hoch. Unter 700px bleibt der Umbruch -- fuenf
Spalten waeren auf einem Handy unlesbar schmal.

45/45 Handy-Abnahme weiterhin sauber.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 19:08:47 +02:00
DogFatherGitandClaude Opus 5 9f74167f84 Sprungmarken brechen um statt zu scrollen, keine Silbentrennung in Ueberschriften
Rueckmeldung 22.08.2026: "ich will nicht dass man die hin und her
schieben muss man soll die alle sehen aber nicht schieben muessen."

Richtig, und aus zwei Gruenden: Eine Wischleiste verbirgt, DASS es noch
mehr gibt -- was rechts aus dem Bild ragt, existiert fuer die meisten
Menschen schlicht nicht. Dazu kam ein haesslicher Scrollbalken quer ueber
die Seite. Jetzt brechen die Knoepfe um, alle fuenf sind auf einen Blick
da, auch bei 320px.

Der Text in den Knoepfen darf dabei mitbrechen (white-space: normal) --
ohne das sprengt ein langer Name wie "Buchhaltungs- &
Steuerverwaltungsseiten" auf schmalen Bildschirmen die Zeile und der
waagerechte Ueberlauf waere durch die Hintertuer zurueck.

Dabei mitgefunden: "hyphens: auto" auf Ueberschriften. Auf dem Handy
stand dadurch "Alles, was vorher ge-klaert sein sollte". Der Browser
trennt damit nach Silben, auch wenn ueberhaupt kein Platzproblem
besteht. In Fliesstext ist das ein Gewinn, in grossen Ueberschriften
sieht es billig aus -- und genau die sind das Erste, was jemand sieht.
overflow-wrap: break-word bleibt und faengt echte Ueberlaeufe weiterhin ab.

Pruefskript: die Sprungmarken-Leisten waren als "absichtlich scrollbar"
von der Ueberlaufpruefung ausgenommen. Diese Ausnahme ist raus -- sonst
wuerde ein zurueckkehrender Ueberlauf dort nie auffallen. 45/45 weiterhin
sauber.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 19:03:30 +02:00
DogFatherGitandClaude Opus 5 de4a90362e Verwaltungsbereich fuer Projektanfragen
Masterplan S.13. Anfragen ansehen, filtern, durchsuchen, Status aendern,
interne Notizen, archivieren. 9/9 Sicherheitstests.

Bewusste Entscheidungen:

* NUR AUF DEUTSCH. Der oeffentliche Teil laeuft in fuenf Sprachen, weil
  dort Kunden landen. Hier landen ausschliesslich Dogfather und VanVan --
  fuenf Sprachen waeren fuenffache Pflege und fuenffache Fehlerflaeche
  ohne einen einzigen Nutzer, der sie braucht. Genau wie der bestehende
  interne Bereich des Universe.

* Anmeldung ueber die BESTEHENDE Team-Anmeldung (/auth/login) statt einer
  zweiten eigenen. Zwei Anmeldungen fuer dieselben zwei Personen waeren
  doppelte Pflege und ein zweiter Ort, an dem ein Zugang vergessen werden
  kann. Der Code der Zugangswand gilt hier ausdruecklich NICHT --
  die Verwaltung steckt hinter zwei getrennten Tueren.

* Sitzungstoken im sessionStorage, nicht localStorage: es verschwindet
  beim Schliessen, dieselbe Regel wie an der Zugangswand. Der Test prueft
  das ausdruecklich.

* Bei abgelaufener Sitzung geht es zurueck zur Anmeldung statt zu einer
  leeren Liste. Eine leere Liste sieht aus wie "keine Anfragen" und ist
  damit eine stille Falschaussage.

* Gold nur beim Status "neu" -- also genau dort, wo wirklich etwas zu tun
  ist. Wuerde alles leuchten, leuchtet nichts.

* Archivieren statt Loeschen, und die Oberflaeche sagt das auch dazu.

Pruefskript: kennt jetzt bewusst einsprachige Seiten (verwaltung, portal)
und prueft dort nur die Struktur, statt ein fehlendes Woerterbuch zu
melden.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 18:54:58 +02:00
DogFatherGitandClaude Opus 5 eaeaec6b56 Anfrageformular fertig - vier Schritte, Zwischenspeicherung, echte Absendung
Masterplan S.10 "Projektanfrage ohne Informationsverlust" umgesetzt.
End-to-End gegen die echte Datenbank belegt: Anfrage A-2608-0002 liegt drin.
38/38 Browsertests, 45/45 Handy-Abnahme.

Aufbau: 4 Schritte + Zusammenfassung + Dankeseite.
- Zwischenspeicherung nach jedem Tastendruck. Geschlossener Tab, leerer
  Akku oder versehentliches Zurueck kosten keine Arbeit. Entwuerfe
  verfallen nach 30 Tagen -- ein halbes Jahr alter Entwurf verwirrt mehr
  als er hilft.
- Folgefragen erscheinen nur passend zur Auswahl und werden beim
  Zurueckwechseln NICHT mitgeschickt, sonst landen alte Shop-Antworten in
  einer Onepager-Anfrage.
- Die Zusammenfassung wird aus den Feldern gelesen, nicht aus einem
  nebenher gepflegten Objekt -- sie kann dadurch nie etwas anderes
  behaupten als das, was tatsaechlich abgeschickt wird.
- Telefon wird zur Pflicht, sobald "Per Telefon" gewaehlt ist. Ein Wunsch,
  der nicht erfuellbar ist, ist schlimmer als eine Pflichtangabe.

Drei Fehler, die erst der Test gefunden hat:
1. Der "Zurueck"-Knopf stand auch auf Schritt 1 da. Ursache: das
   hidden-Attribut wird nur ueber "display:none" umgesetzt und verliert
   gegen jedes eigene display -- und Knoepfe sind inline-flex. Zentral
   behoben ueber ".wd [hidden] { display:none !important }".
2. Nach erfolgreichem Absenden legte zeigeSeite() den geloeschten Entwurf
   sofort wieder an. Beim naechsten Besuch haette eine bereits gesendete
   Anfrage erneut im Formular gestanden.
3. Der Server meldet bei Spamverdacht bewusst Erfolg ohne Nummer. Ein
   echter Mensch, der zufaellig sehr schnell war, haette eine Dankeseite
   mit "—" gesehen und auf eine Antwort gewartet, die nie kommt. Jetzt
   ein ehrlicher Hinweis mit zweitem Weg, und der Entwurf bleibt erhalten.

Pruefskripte geschaerft:
- i18n-Pruefung liest jetzt auch assets/js/wd-<seite>.js, sonst meldet sie
  reihenweise "unbenutzt" fuer Schluessel, die aus dem Seitenskript kommen.
- Handy-Abnahme ueberspringt absichtlich unsichtbare Eingabefelder
  (Auswahlkacheln, Honigtopf). Fehlalarme sind das Ende jeder Pruefung,
  weil man sie irgendwann pauschal ignoriert.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 18:47:45 +02:00
DogFatherGitandClaude Opus 5 8ace955740 Service Worker lieferte alte Stilvorlagen aus - Korrekturen blieben unsichtbar
Gemeldet 22.08.2026 mit Bildschirmfoto: "immer noch so" -- das Logo im
Marken-Intro stand weiterhin hochkant gestreckt da, obwohl die Korrektur
(height:auto gegen die height-Attribute) laengst live war.

Ursache war NICHT die Korrektur, sondern mein eigener Service Worker. Er
lief fuer /assets/ als "stale-while-revalidate": die gespeicherte Fassung
geht sofort raus, im Hintergrund wird eine frische geholt. Das ist schnell
-- bedeutet aber, dass jede Aenderung an CSS oder JavaScript beim ersten
Aufruf unsichtbar bleibt und erst beim zweiten wirkt. Ein behobener Fehler
sieht dadurch aus wie ein nicht behobener. Die unangenehmste Sorte.

Nachgemessen ist das Logo jetzt 160x161px bei einem natuerlichen
Verhaeltnis von 472x476 -- also unverzerrt. Vorher erzwang das Attribut
height="476" bei 160px Breite ein Verhaeltnis von 0,34 statt 0,99, genau
das lange Gesicht auf dem Bildschirmfoto.

Behoben:
- Stilvorlagen und Skripte laufen jetzt "Netz zuerst", Zwischenspeicher
  nur als Notfallnetz. Richtigkeit vor Millisekunden.
- Bilder und Symbole bleiben beim schnellen Weg -- die aendern sich
  praktisch nie und bekaemen sonst einen neuen Dateinamen.
- CACHE_NAME auf v2 gesetzt, damit der alte Speicher beim naechsten Start
  vollstaendig weggeworfen wird.
- Versionsnummer an allen CSS/JS-Verweisen hochgesetzt, damit es sich auch
  ohne Service Worker sofort selbst heilt.

Ausserdem: Woerterbuch fuer das Anfrageformular, 101 Textbausteine in fuenf
Sprachen (vier Schritte, Zusammenfassung, Fehlermeldungen).

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 18:34:15 +02:00
DogFatherGitandClaude Opus 5 356bb974b8 Knopf war unlesbar, und der Code wird jetzt bei jedem Schliessen neu verlangt
Zwei Rueckmeldungen vom 22.08.2026, beide behoben und mit Tests abgesichert.

1) "das sieht nicht gut aus" (Bildschirmfoto des Hauptknopfs)
   Ursache: ".wd a" ist Klasse+Element und damit spezifischer als die reine
   Knopfklasse ".wd-btn--haupt". Die Textfarbe des Knopfs wurde dadurch
   ueberstimmt -- hellblaue Schrift auf hellblauem Grund, praktisch
   unlesbar. Derselbe Spezifitaetsfehler wie zuvor bei den Namen auf der
   Zugangswand. Fix: ".wd a:not(.wd-btn)" plus zweistufig geschriebene
   Knopfregeln, damit das nicht wieder passieren kann.

2) "das sieht lang gezogen aus"
   Die Pillenform (border-radius 999px) laesst breite Knoepfe
   auseinandergezogen wirken, weil der Radius optisch mit der Breite
   mitwaechst. Jetzt fester Radius von 14px -- gleiche Form bei jeder
   Breite, ruhiger und hochwertiger.

3) "ich will das ich jedes mal den code gefragt werde wenn man die seite
   zu macht"
   Das Sitzungs-Cookie allein reicht dafuer nicht: Browser stellen genau
   solche Cookies beim Wiederherstellen von Tabs zurueck ("Dort
   fortfahren, wo du aufgehoert hast"), man landet dann ohne Codeabfrage
   wieder mitten in der Seite. Zusaetzlich jetzt eine Sitzungsmarke im
   sessionStorage, die beim echten Schliessen verschwindet. Fehlt sie bei
   vorhandenem Cookie, wird die Sitzung serverseitig beendet und zur
   Zugangswand geleitet. Token-Notbremse von 24 auf 8 Stunden gesenkt.
   13/13 Tests im echten Browser, inklusive Schutz vor Endlosschleife.

DEPLOY.md: zwei Checkouts auf dem Server dokumentiert (/home/dogiweb und
/home/dogiintern) und der Vorfall, dass /webdesign nach dem Pull kurz ohne
Zugangsschutz erreichbar war, weil der Dienstneustart fehlte.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 18:20:34 +02:00
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