Commit Graph
253 Commits
Author SHA1 Message Date
DogFatherGitandClaude Opus 5 131bc8a755 Anfragen annehmen und ablehnen — mit laufender Zeit bis zur Übergabe
Annehmen war bisher nur ein Etikett: Man stellte den Status um, und es
passierte nichts. Kunde, Projekt, Aufgabenliste, Termin und Zugang musste
man danach von Hand in fünf Schritten nachbauen. Der alte Code gab das im
Kommentar selbst zu -- schlug der zweite von zwei Aufrufen fehl, stand der
Kunde schon in der Datenbank und man durfte es nicht noch einmal
versuchen.

Jetzt macht das EIN Aufruf, ganz oder gar nicht:
Kunde finden oder anlegen, Projekt anlegen, die komplette Aufgabenliste
des Pakets einsetzen, Liefertermin berechnen, Einladungslink erzeugen.
Der Kunde verfolgt ab diesem Moment alles in seinem Portal.

Die Zeit läuft wirklich:
- Eigenes Datumsfeld (termin_am) neben dem freien Text. Aus 'Mitte
  Oktober' kann man keine verbleibenden Tage rechnen.
- Werktage statt Kalendertage, inklusive luxemburgischer Feiertage. Die
  beweglichen werden über die Osterformel berechnet statt gepflegt --
  eine Liste ist im übernächsten Jahr lautlos falsch.
- Vorschlag je Paket (Onepager 10, Website 20, Shop 30 Werktage),
  überschreibbar vor dem Bestätigen.
- Verbleibende Zeit wird SERVERSEITIG gerechnet. Der Browser kennt die
  Feiertage nicht; zwei verschiedene Zahlen für denselben Termin wären
  schlimmer als gar keine.

Ablehnen mit Grund und vorbereiteter Absage in fünf Sprachen, Text
serverseitig erzeugt und vor dem Abschicken lesbar. Ein laufendes
Projekt lässt sich nicht nachträglich als Anfrage ablehnen.

Sechs Fehler dabei gefunden:
- Ein unbekanntes Paket hätte GAR KEINEN Termin bekommen statt des
  Ersatzwerts. Zwei Funktionen lasen dieselbe Tabelle, nur eine hatte
  einen Rückfallwert. Eine fehlende Zahl fällt nirgends auf.
- wd_anfragen hat keine Spalte 'firma' -- better-sqlite3 weist undefined
  ab, die ganze Annahme wäre gescheitert.
- Migrationen stehen in einer ausdrücklichen Liste; 0015 fehlte darin.
- datumKurz() wurde aufgerufen, gab es aber nicht. Der Fehler wäre erst
  NACH dem Anlegen aufgetreten.
- Der Installations-Hinweis lag fest über dem Annehmen-Knopf und machte
  ihn auf dem Handy untreffbar. Die Seite reserviert jetzt Platz dafür.
- 'richttermin' ist freier Text, lief aber durch einen Datumsformatierer:
  Der Kunde las 'Invalid Date' an der wichtigsten Stelle seines Projekts.

Geprüft: 49 Prüfungen der Terminrechnung gegen nachschlagbare Osterdaten
und Wochentage, 70 gegen eine echte Datenbank (darunter: zweiter Klick
legt nichts doppelt an, Abbruch mittendrin lässt NICHTS zurück, gesperrter
Kunde wird nicht still entsperrt), 42 im Browser auf Computer und Handy,
40 im Portal. Alle bestehenden Prüfungen weiter grün.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-23 22:44:08 +02:00
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 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 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 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 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
DogFatherGit 38bc741660 Aufraeumen: versehentlich mitcommittete Dateien entfernt
Ein 'git add -A' hat 13 Bild-Sicherungskopien (.bak-*, zusammen 2,6 MB),
den lokalen Testserver und eine erzeugte package-lock.json mitgenommen.

Die package-lock.json war der schaedlichste Teil: Auf dem Server existiert
eine eigene, dort erzeugte Fassung. Eine versionierte Datei gleichen Namens
laesst 'git pull' abbrechen -- der Deploy stand sofort still.

Alle drei Muster stehen jetzt in .gitignore.
2026-08-22 22:57:26 +02:00
DogFatherGit 4ce51c127e WIP: Aufgaben- und Postfach-Routen (Test folgt auf dem Server) 2026-08-22 22:56:59 +02:00
DogFatherGitandClaude Opus 5 2539fdea8d Zahlenkreise repariert und vier Prozessfarben durchgaengig
"wieso sehen die zahlen immer noch so scheisse aus?" -- zu Recht, und die
Ursache war nicht Geschmack, sondern ein Fehler. Nachgemessen sass die
Ziffer 15px NEBEN der Kreismitte.

Ursache: ".po-leer-punkt span" (fuer den Beschreibungstext) trifft auch
den Zahlen-Span und ist spezifischer (Klasse + Element) als
".po-leer-nr" (nur Klasse). Sie erzwang display:block, 14,4px Schrift und
23px Zeilenhoehe -- exakt die gemessenen Werte. Meine eigene
"line-height: 1"-Regel kam gar nicht zum Zug.

Das ist derselbe Spezifitaets-Fehler wie zuvor beim Hauptknopf (blaue
Schrift auf blauem Grund) und bei den Namen auf der Zugangswand. Dreimal
dieselbe Falle, deshalb steht die Begruendung jetzt ausfuehrlich im Code.

Behoben ueber :not(.po-leer-nr) an beiden Textregeln. Nachgemessen:
  Versatz waagerecht  -15px -> 0px
  Versatz senkrecht    -8px -> -1,3px
  display             block -> grid
  Schrift/Zeile   14,4/23px -> 18,4/18,4px

Zweite Rueckmeldung: "es soll 4 farben geben wie 4 kategorien zum
prozess". Sehr gute Idee -- sie macht das System erst schluessig. Die
sieben Phasen sind in Wahrheit vier Abschnitte, und die vier
Merkmalskacheln trugen ohnehin schon vier Farben. Jetzt bedeuten diese
Farben ueberall dasselbe:

  1  Blau   Start        Briefing, Angebot
  2  Lila   Gestaltung   Design
  3  Gruen  Umsetzung    Entwicklung, Tests
  4  Gold   Abschluss    Abnahme, Uebergabe

Die Phasenleiste faerbt erledigte Abschnitte in IHRER Farbe statt
pauschal gruen -- man sieht dadurch, wie weit man ist, nicht nur DASS
etwas fertig ist. Die Vorschau laeuft in denselben Farben durch. Die
Legende nennt die vier Abschnitte beim Namen, damit Farbe nicht geraten
werden muss: Farbe allein ist nie Information.

45/45 Handy-Abnahme, i18n vollstaendig.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 22:26:04 +02:00
DogFatherGitandClaude Opus 5 c597753abf Portal: Zahlenkreise, Typografie und eine echte Farblogik fuer Phasen
Drei Rueckmeldungen vom 22.08.2026, alle drei berechtigt.

1) "die kisten sollen auch eine spezielle farbe bekommen wenn sie fertig
   sind" -- das war inhaltlich der wichtigste Punkt. Vorher sahen
   erledigte und gerade laufende Phase fast gleich blau aus. Damit ging
   die einzige Aussage verloren, die die Leiste ueberhaupt traegt:
   naemlich WO man steht. Jetzt drei klar getrennte Zustaende:
     erledigt     gruen, ruhig
     laeuft grad  leuchtendes Blau mit langsamem Puls
     kommt noch   gedaempft
   Die Vorschau erklaert die Logik gleich mit: ihre Leiste wandert von
   blau nach gruen, statt nur an- und auszugehen.
   Dazu eine Legende in Worten. Farbe allein ist nie Information -- wer
   sie nicht unterscheiden kann, liest hier trotzdem, was sie bedeutet.

2) "die zahlen sollen besser im kreis sein" -- vorher ein flacher Kreis
   mit Zahl. Jetzt ein doppelter Ring: aussen ein Farbverlauf als Rand,
   innen die dunkle Flaeche, dazu ein weicher Schein. Derselbe Kniff wie
   bei den Karten (Verlauf ueber border-box); der Kreis wirkt dadurch
   plastisch statt aufgemalt. Jede der vier Kacheln hat ihre eigene
   Farbe -- vier gleiche Kacheln wirken wie eine Aufzaehlung, vier
   unterscheidbare wie ein System.

3) "schrift soll spezieller sein" -- die Kachel-Ueberschrift war so gross
   wie der Text darunter und ging unter. Jetzt groesser, in der
   Headline-Schrift, enger gesetzt mit leicht negativer Laufweite. Die
   Ueberschrift "Gleich geht es los" bekommt einen Farbverlauf.

45/45 Handy-Abnahme, i18n vollstaendig, prefers-reduced-motion beachtet.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 22:14:00 +02:00
DogFatherGitandClaude Opus 5 ad58ab99d3 Leeres Portal: zeigen statt erzaehlen
Rueckmeldung 22.08.2026 mit Bildschirmfoto: "dass muss noch viel
spezieller, krasser und geiler sein, nicht so einfach".

Der Kern des Problems war nicht die Optik, sondern die Haltung: Die Seite
BESCHRIEB, was hier bald stehen wird ("Eine Leiste zeigt dir, in welcher
Phase dein Projekt ist"). Beschreibungen sind schwach -- man muss sie
lesen und sich dann etwas vorstellen.

Jetzt steht dort eine echte, als Vorschau gekennzeichnete Projektkarte:
Projektnummer, Titel, eine Phasenleiste, die langsam durchlaeuft, die
Marke "Dogfather ist dran" und ein naechster Schritt. Man sieht in zwei
Sekunden, was drei Saetze nicht erklaeren.

Die Karte ist bewusst als Vorschau erkennbar -- gestrichelter Rand,
Etikett oben rechts, gedaempfte Schrift, Nummer P-0000-0000. Sie darf nie
mit einem echten Projekt verwechselt werden.

Dazu ein sehr langsamer Lichtstreifen, der einmal durchwandert. Er sagt
ohne Worte "hier passiert gleich etwas", ohne zu blinken oder zu zappeln
-- augenschonend bleibt Dauervorgabe.

Bei prefers-reduced-motion laeuft nichts, aber die Phasenleiste zeigt
trotzdem drei erledigte Phasen. Ohne das staende dort eine leere graue
Reihe und die Vorschau erklaerte gar nichts mehr -- ein abgeschaltetes
Element muss trotzdem noch seine Aussage transportieren.

45/45 Handy-Abnahme, i18n vollstaendig.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 22:07:06 +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 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 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 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 29a054c359 Bilder waren hochkant gestreckt und ungleich hoch, Abstaende halbiert
Rueckmeldung 22.08.2026 per Bildschirmfoto: "die sollen alle gleich
aussehen und nicht einer groesser oder kleiner" und "ich will nicht soooo
viel abstand".

1) Verzerrte, ungleich hohe Projektbilder
   Nachgemessen: 576px breit, aber 750px bzw. 696px hoch -- also hochkant
   gestreckt und unterschiedlich, obwohl im CSS sauber "aspect-ratio:
   16/10" stand. Ursache: die width/height-Attribute im HTML (die dort
   bewusst stehen, damit der Browser vor dem Laden den Platz reserviert
   und die Seite nicht springt) wirken wie eine CSS-Hoehe und schlagen
   aspect-ratio. Fix zentral ueber ".wd img[width][height] { height:
   auto }" statt in jeder einzelnen Regel -- so kann es bei einem neuen
   Bild nicht vergessen werden.
   Jetzt beide 576x360, Karten beide 853px hoch.

2) Zu viel Leerraum
   .wd-abschnitt hatte 100,8px oben UND unten, also gut 200px zwischen
   zwei Abschnitten. Halbiert auf 57,6px, Hero von 78svh auf 68svh.
   Seitenlaenge dadurch 8798px -> 7089px bei gleichem Inhalt.

3) Zwei neue Dauerpruefungen in pruefe-webdesign-handy.mjs, damit genau
   diese beiden Fehlerarten nicht wieder per Bildschirmfoto auffallen
   muessen:
   - verzerrte Bilder (gewuenschtes vs. tatsaechlich gerendertes
     Seitenverhaeltnis, 2 % Toleranz)
   - ungleich hohe Karten innerhalb EINER Rasterzeile

40/40 Abnahme weiterhin sauber.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 18:26:07 +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
DogFatherGitandClaude Opus 5 2010b5ec33 Live benutzte Hintergrundbilder + Stimmen-Avatare in die Ablage aufgenommen
Beim Abgleich zwischen Rechner und Netcup-Server am 22.08.2026 aufgefallen:
20 Bilddateien wurden live von mehreren Seiten benutzt (bewerben-modi.html,
links.html, medien-casper.html, medien-hasidog.html, supporter.html,
stimmen.html u.a.), lagen aber in keiner Git-Ablage -- nur auf diesem
Rechner und auf dem Server. Waeren beide verloren gegangen, waeren diese
Seiten ohne Hintergrund/Avatare dagestanden.

Vor dem Hinzufuegen jede Datei per Pruefsumme gegen den Server abgeglichen
-- alle identisch, kein abweichender Stand wird hier verdeckt.

dogfather-universe-app.ico ist aktuell nirgends verlinkt (vermutlich ein
nie eingebauter Favicon-Entwurf), trotzdem mit gesichert statt verworfen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 15:47:38 +02:00
DogFatherGitandClaude Opus 5 3f9997456a Handy: Sprachfenster (DE) klappte halb aus dem Bild auf
Nutzer-Report per Foto: beim Tippen auf "DE" im Handy-Menue erschien das
Sprachfenster halb links ausserhalb des Bildschirms, man konnte keine
Sprache mehr lesen oder treffen.

Ursache: Die Handy-Regel, die alle Aufklapp-Fenster auf statische Position
und volle Breite umstellt, hat den Sprachschalter nicht erreicht -- seine
Desktop-Regel (.sprach-schalter .nav-dropdown, 0-2-0) ist spezifischer,
und eine @media-Abfrage erhoeht die Spezifitaet nicht. Dadurch lief die
Desktop-Animation "sprach-dropdown-in" weiter, die per fill-mode:both
dauerhaft transform: translateX(-50%) setzt. Auf dem Desktop korrekt
(schmales Fenster mittig unter dem Knopf), im Handy-Menue aber toedlich:
das Fenster ist dort bildschirmbreit und wurde um seine halbe Breite nach
links geschoben (gemessen live: x = -148px bei 390px Viewport).

Fix: dieselben Handy-Regeln erneut mit ausreichender Spezifitaet fuer den
Sprachschalter, samt Kommentar zur Begruendung.

Geprueft mit Playwright (echter Browser): 390x844, 360x640, Querformat
844x390 und Tablet 768x1024 -> Fenster jeweils vollstaendig im Bild, alle
5 Sprachen sichtbar; Desktop 1920 unveraendert schmal und zentriert;
Sprachwechsel (English) funktioniert weiterhin.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-22 11:27:22 +02:00
DogFatherGitandClaude Sonnet 5 adb1042915 Namenskorrektur Cigdem (statt Cidgem) auch lokal + in allen 5 Sprachen nachgezogen
War beim Server-Deploy schon als Konflikt aufgefallen (Diene/das Team hatte
die richtige Schreibweise bereits korrigiert) -- hier fehlte die Korrektur
noch in i18n-zeitreise.js (alle 5 Sprachen) sowie in der HTML-Fallback-
Version, weil mein ursprünglicher Fix von heute Nachmittag ("Cidem" ->
"Cidgem") selbst schon falsch war.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 23:39:29 +02:00
DogFatherGitandClaude Sonnet 5 1f0ec994a9 Drei Handy-Nachbesserungen: Trio-Bild hinter dem Text, auffälliger Menü-Knopf, abgeschnittener Öffnen-Knopf
Nutzer-Report mit drei Bildern vom Handy:

1. HERO-BILD SASS NICHT MEHR HINTER DEM TEXT (index.html)
   .hero-artwork hat "inset:0" -- füllt also die GESAMTE Höhe von
   .hero-cinematic, und diese Sektion umschließt nicht nur die Überschrift,
   sondern auch die 3 Welt-Kacheln darunter. Auf dem Handy wird die Sektion
   durch den 4-zeilig umbrechenden Titel + Kacheln riesig (~1570px bei
   390px Breite) -- das Trio-Bild (16:9, contain-skaliert an die Breite)
   wurde dadurch nur ~220px hoch und mittig in dieser riesigen Fläche
   zentriert, landete also als schmaler Streifen zwischen den Buttons und
   den Welt-Kacheln statt hinter der Überschrift.
   Fix: eigenes festes Seitenverhältnis (4:3) für die Bildbox auf dem
   Handy, von OBEN verankert statt zentriert, background-size auf "cover"
   -- Verlauf eigens für die neue, kürzere Box abgestimmt (die
   Desktop-Version wäre zu abrupt gewesen). Über 6 Breiten (320-768px)
   mit Playwright gegengeprüft.

2. MENÜ-KNOPF ZU UNAUFFÄLLIG (main.js + main.css, alle Seiten)
   "da soll auch menü stehen und die 3 striche" + "die kiste soll auch
   leicht eine andere farbe haben so dass sie auffällt, eine leicht blau
   tönung". Sichtbares "Menü" neben den drei Strichen ergänzt (neuer i18n-
   Schlüssel nav_toggle_label, alle 5 Sprachen) + dezente Babyblau-Tönung
   (8% Deckkraft, passend zur Markenfarbe --accent). Dabei einen
   unabhängigen, zweiten Bug gefunden und mitbehoben: durch die neue
   Knopfbreite/-höhe wurde ein Rechenfehler im geschlossenen Mobilmenü
   sichtbar -- "translateY(-110%)" reicht nur, wenn das Panel mindestens
   10x so hoch ist wie der Kopfbereich; war das nicht der Fall, ragte die
   Unterkante (der Sprachschalter) ein paar Pixel sichtbar ins Bild.
   Robusterer Ersatz: -100% + fester 200px-Puffer, unabhängig von Panel-
   und Kopfbereichshöhe. Über 3 Breiten gegengeprüft (Panel unsichtbar UND
   öffnet weiterhin normal).

3. "ÖFFNEN"-KNOPF AUF DER ZUGANGSSEITE ABGESCHNITTEN (gate.html)
   .gate-card trägt "flex: 1 1 220px" für die Desktop-Reihe (220px als
   BREITE gedacht). Sobald @media max-width:480px auf flex-direction:column
   umschaltet, gilt dieselbe Zahl als HÖHE -- die Karte wurde auf genau
   220px Höhe gequetscht. overflow:hidden setzt zusätzlich das normale
   Mindestmaß (min-height:auto) auf 0 herunter, wodurch nichts das
   Zusammenquetschen verhinderte -- der "Öffnen"-Knopf wurde unten
   abgeschnitten. Fix: flex:none in genau diesem Media-Block, Breite bleibt
   weiterhin über width:100%/max-width geregelt. An 4 Breiten x 3 Kacheln
   (Dogi/VanVan/Diene) gegengeprüft: Karten jetzt 258px statt 220px hoch,
   Knopf komplett sichtbar.

Vollständiger Regressionslauf: alle 34 Seiten bei 390px (kein Überlauf,
Menü-Knopf überall erreichbar und beschriftet), Desktop bei 1920px
unverändert (Hamburger weiterhin nur unter der bestehenden 1650px-
Schwelle sichtbar).

Cache-Busting-Version auf 20260821t erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 23:37:14 +02:00
DogFatherGitandClaude Opus 5 41faf22614 Handy: vollständige Prüfung von Inhalten, Knöpfen und allen Systemen
Nachtrag auf Nachfrage ("hast du alles geprüft oder nur die menü
leisten?") -- vorher hatte ich nur Navigation, Seitenbreite, Tippflächen
und Hoch/Querformat geprüft. Jetzt zusätzlich Bilder, Texte, Knöpfe und
die kompletten Abläufe.

Geprüft über alle 35 Seiten bei 393px:
- Bilder: kein einziges kaputtes Bild, keine fehlenden alt-Texte
- Dateien: keine 404er
- Knöpfe/Links: alle beschriftet (keine namenlosen Bedienelemente)
- Text: nichts wird abgeschnitten. Die zunächst gemeldeten "Überläufe"
  bei .btn/.card waren Fehlalarme -- sie stammen von den dekorativen
  Leucht-Ebenen (::before mit negativem inset), echter Text ragt
  nirgends heraus (einzeln gegengeprüft).

Zwei echte Funde behoben:
1. Marken-Unterzeile war mit 8,96px zu klein zum Lesen (hatte ich beim
   Handy-Fix selbst so verkleinert). Jetzt 11px -- Platz ist da, seit der
   Menü-Knopf eigenständig rechts sitzt. Über acht Breiten gegengeprüft,
   Kopfleiste bleibt überall stabil.
2. "Aktiv"-Ankreuzfelder in der Verwaltung waren 22px. Jetzt 26px, die
   ganze Beschriftungszeile ist 44px hoch und schaltet mit um.

Abläufe am Handy durchgespielt (echte Fingertipps, Fake-Backend):
- Registrierung über alle drei Schritte inkl. falschem Code
- Login mit falschem und richtigem Zugangscode
- Abmelden auf supporter.html
- Stimme einreichen inkl. Profilbild-Auswahl
- Verwaltung: Team-Mitglied anlegen, Stimme freigeben, alle Bereiche
  sichtbar, kein Überlauf

Cache-Busting-Version auf 20260821r erhöht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 18:33:52 +02:00
DogFatherGitandClaude Opus 5 6910112d97 Stimmen: nur noch die zwei Originalfiguren + eigenes Bild hochladen
Nutzer-Wunsch 21.08.2026: "benutz da bitte nur die originalen husky und
hasen. mach nur die zwei. und die auswahl wo die leute selbst ein bild
rein setzen können."

- Auswahl von acht auf zwei reduziert (DogFather-Husky, HasiDog). Die
  übrigen Bilddateien bleiben liegen, falls sie je zurücksollen -- es
  genügt, die Zeile in data-stimmen-avatare.js und die Id in
  ERLAUBTE_AVATARE wieder zu ergänzen.
- Neue Kachel "eigenes Bild" (gestrichelter Rand + Plus), die den
  Dateidialog öffnet, das Bild sofort hochlädt und als Vorschau in der
  Kachel zeigt.

Bereits freigegebene Stimmen mit einer der entfernten Figuren zeigen
wieder den Anfangsbuchstaben statt eines kaputten Bildes -- die
Auflösung unbekannter Ids liefert null, das war schon so vorgesehen.

Sicherheit des öffentlichen Uploads (bisher war Hochladen bewusst nur
der Verwaltung erlaubt):
- Gleiche multer-Härtung wie der Verwaltungs-Upload: nur JPG/PNG/WebP,
  max. 5 MB, zufälliger UUID-Dateiname (kein Originalname).
- Der Server nimmt im Avatar-Feld weiterhin NUR bekannte Ids an oder
  eine Adresse, die exakt auf den eigenen Upload-Ordner zeigt und danach
  nur aus UUID + Bildendung besteht. Gegengetestet: fremde Domains,
  "../"-Ausbruch, .svg/.html, javascript:, angehängte Skripte und http
  statt https werden alle abgelehnt.
- Missbrauchsbremse gegen Vollschreiben der Festplatte: max. 10 Uploads
  pro Stunde und IP.
- Sichtbar wird ein Bild ohnehin erst, wenn die Stimme freigegeben wird.

Mit Playwright end-to-end geprüft (10 Tests) plus 9 Sicherheitsfälle.

Cache-Busting-Version auf 20260821q erhöht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 18:23:17 +02:00
DogFatherGitandClaude Opus 5 e2bd436084 Arbeit der parallelen Session gesichert (Profilbilder für Stimmen, Diene-Zugang)
Wie beim vorherigen Mal lag das nur als Arbeitskopie auf dem Server, nicht
in git. Unverändert übernommen, bevor darauf aufgebaut wird:
- Profilbild-Auswahl für die Stimmen (data-stimmen-avatare.js neu,
  stimmen.js, i18n-stimmen.js, stimmen.html, verwaltung.html, main.css)
- Dritte Zugangs-Kachel für Diene (gate.html, server/gate.js)

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 18:17:47 +02:00
DogFatherGitandClaude Opus 5 d0613f86c1 Handy: Navigation war komplett unerreichbar — behoben, plus Tippflächen überall
Nutzer-Report 21.08.2026 mit Screenshot: "auf dem handy kann ich oben
nicht aussehen in welche seite ich will welche kategorie welche sprache
garnichts". Drei echte, per Playwright reproduzierte Fehler:

1. MENÜ-KNOPF AUSSERHALB DES BILDSCHIRMS (Hauptproblem)
   .brand stand auf flex-shrink:0, war bei 390px aber 352px breit. Mit
   Abstand + Knopf brauchte die Leiste 423px bei 367px Platz -- der
   Menü-Knopf landete bei x=396px, also komplett außerhalb. Damit war auf
   dem Handy die GESAMTE Navigation unerreichbar (keine Seiten, keine
   Kategorien, kein Sprachwechsel).
   Fix: Knopf per margin-left:auto immer an die rechte Kante; Marke darf
   unter 620px schrumpfen (inkl. min-width:0, sonst greift flex-shrink
   nicht); unter 400px entfällt die reine Deko-Unterzeile.

2. MENÜ IM QUERFORMAT NICHT ZU ÖFFNEN
   Das zugeklappte Panel wird um -110% SEINER EIGENEN Höhe verschoben. Quer
   (568x320) ist es nur 258px hoch, die Unterkante lag dadurch bei y=36px --
   also unsichtbar genau über dem Menü-Knopf (y=11..55) und hat jede
   Berührung abgefangen. Fix: pointer-events:none im geschlossenen Zustand.

3. MENÜPUNKTE AUF KURZEN BILDSCHIRMEN ZUSAMMENGEQUETSCHT
   .nav-links ist ein Flex-Container fester Höhe; passte der Inhalt nicht,
   schrumpfte Flexbox die Einträge (iPhone SE: 59px -> 29px, Knöpfe 21px).
   Fix: flex-shrink:0 auf die Kinder, der Bereich scrollt stattdessen
   (overflow-y:auto war bereits gesetzt).

Zusätzlich: Fußzeilen- und Impressum/AGB-Links auf Handys als echte
Tippziele (44px statt 17-20px) -- 18 dicht stehende Links, mit dem Finger
vorher kaum zu treffen. Menü-Trennlinien begradigt (folgten dem
Desktop-Pillenradius und sahen aus wie Schüsseln).

Ergebnis: alle 31 Seiten ohne Überlauf, Menü auf 320-768px, hoch UND quer
nutzbar, kleinster Menüpunkt 46px. Verbleibende kleine Ziele sind reine
Fließtext-Links im Satz (dürfen laut Standard klein bleiben).
Desktop per Regressionstest unverändert geprüft.

Cache-Busting-Version auf 20260821p erhöht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 18:13:03 +02:00
DogFatherGitandClaude Opus 5 5a5912636d Registrierung: E-Mail-Bestätigung per Einmalcode vor dem Zugangscode
Nutzer-Wunsch 21.08.2026: "bei der ersten registrierung sollen die eine
email bekommen mit einem einmaligen code damit wir auch wissen dass
email stimmt und danach wenn sie den code eingegeben haben sollen die
erst ihren zugangscode auswählen/eintippen können."

Damit wird eine echte Lücke geschlossen: registerSupporter() hat bisher
`email_verified = 1` gesetzt, OHNE dass irgendetwas geprüft wurde -- man
konnte sich mit einer fremden oder erfundenen Adresse registrieren und
kam sofort rein.

Neuer Ablauf in drei Schritten:
1. Name/TikTok/E-Mail -> Konto wird als UNBESTÄTIGT angelegt
   (email_verified = 0, noch kein Zugangscode). Es kommt bewusst KEIN
   Session-Token zurück -- eingeloggt ist man hier noch nicht.
2. Einmalcode aus der E-Mail eingeben -> verify-email bestätigt und
   loggt ein. Die Willkommens-Mail wandert hierher, sie ging vorher an
   eine noch ungeprüfte Adresse.
3. Erst jetzt den eigenen Zugangscode festlegen.

Serverseitig abgesichert: setSupporterAccessCode() lehnt ab, solange die
E-Mail nicht bestätigt ist -- der Schritt ist damit nicht nur im
Formular versteckt, sondern auch per Direktaufruf nicht überspringbar.

Wiederverwendet wird die bereits vorhandene Mechanik (issueAuthCode/
verifyAuthCode mit Zweck "verify_email", sendVerifyEmailCode, die Panels
#panel-code und #panel-neuer-code) -- der "Code vergessen?"-Weg nutzt
dieselbe Code-Eingabe und bleibt unverändert; eine neue Variable
codeZweck unterscheidet, welcher Endpunkt aufgerufen wird.

Mit Playwright end-to-end geprüft (14 Tests): Reihenfolge der Aufrufe,
kein Token vor der Bestätigung, falscher Code kommt nicht weiter,
Zugangscode-Feld erst im letzten Schritt, "Code vergessen?" unberührt.

Cache-Busting-Version auf 20260821o erhöht.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 17:48:08 +02:00
DogFatherGitandClaude Opus 5 5d0ea11570 Arbeit der parallelen Session in git gesichert (war nur auf dem Server)
Diese Änderungen liefen bereits live auf dem Server, lagen dort aber
ausschließlich als nicht eingecheckte Arbeitskopie — bei jedem Deploy
(stash/pull/pop) und bei jedem Serverproblem wären sie verloren gewesen.
Deshalb hier unverändert in git übernommen, bevor darauf aufgebaut wird.

Enthalten (nicht von mir gebaut, nur gesichert):
- Supporter: eigener fester Zugangscode statt Einmalcode-Login
  (Migration 0009, lib/crypto.js scrypt-Hash, routes/supporter.js,
  abonnieren.html, supporter.html, i18n-abonnieren/-supporter)
- Stimmen: Profilbilder (Migration 0010, routes/testimonials.js)
- Event-Bild-Upload: voller Pfad statt relativem (routes/events.js)
- Neue/überarbeitete Hintergrundbilder für viele Seiten
- Teilen-Funktion (streamplan.js, i18n-index/-streamplan, main.css)

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 17:35:14 +02:00
DogFatherGitandClaude Sonnet 5 d0f3edb079 bewerben.html: Überschrift-Umbruch verbessert (kein einsames letztes Wort mehr)
Nutzer-Wunsch 21.08.2026: "Weg" stand auf manchen Bildschirmbreiten
allein in einer eigenen Zeile, sah unruhig aus. Non-breaking-Space
zwischen den letzten zwei Wörtern in allen 5 Sprachen -- bricht die
Zeile jetzt nie mehr genau zwischen ihnen um.

Cache-Busting-Version auf 20260821m erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 16:51:00 +02:00
DogFatherGitandClaude Sonnet 5 76f70ffcf2 Zeitreise: Namen "Cidem" zu "Cidgem" korrigiert (Creator Cup)
Nutzer-Wunsch 21.08.2026: Tippfehler beim Namen des Kooperationspartners
beim Creator Cup korrigiert, in allen 5 Sprachen plus dem
HTML-Fallbacktext.

Cache-Busting-Version auf 20260821l erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 12:58:29 +02:00
DogFatherGitandClaude Sonnet 5 81f55d67db Team-Verwaltung Runde 2: bestehende Mitglieder importieren + Kategorien/Seitentitel editierbar
Nutzer-Wunsch 21.08.2026: "wenn ich eine änderung mache ist es auch für
jeden für die die schon da sind und die neuen" + "ich will ich titel
und namen von kategorien und seiten ändern können in der verwaltung".

Backend (braucht Filipes manuellen Deploy):
- Migration 0008: team_members bekommt intro/bioHtml/extraCta-Spalten
  -- volle Feld-Parität mit den von Hand gepflegten Profilen (Diene/
  Patrick/Bananenstift/Marina nutzen diese Felder).
- routes/team.js: neue importLegacyMember()-Funktion -- übernimmt ein
  bestehendes Profil 1:1 in die Datenbank, OHNE erneut zu übersetzen
  (die vorhandenen, von Hand geschriebenen Übersetzungen bleiben
  erhalten). Idempotent: mehrfacher Import erzeugt keine Duplikate.
- routes/site-texts.js (neu): admin-editierbare Kategorie-Namen und
  Seitentitel, generischer key->{de,...}-Override über app_settings
  (wie "Event des Jahres"), fester Schlüssel-Katalog aus
  Sicherheitsgründen. Leeres Feld setzt auf den Standardtext zurück.
- 27 Tests in isolierter Testumgebung geprüft (kein better-sqlite3
  lokal kompilierbar).

Frontend:
- window.dogiTeamZusammenfuehren() (main.js): admin-Mitglieder
  ÜBERSCHREIBEN jetzt gleichnamige statische Einträge (per slug) statt
  sie zu duplizieren -- eine Bearbeitung wirkt dadurch für alle.
- window.dogiSiteTexteLaden() + applyTranslations() erweitert um
  data-site-text-key -- Kategorie-Seitentitel (team-modis.html/
  team-scouts.html/creator.html/manager.html) sind jetzt live editierbar.
- Verwaltung: "📥 Bestehende Mitglieder importieren"-Knopf (holt VanVan/
  Diene/Funny/Miss/Marina/Ghost/Patrick/Bananenstift aus den data-*.js-
  Dateien, VanVan bewusst ausgenommen -- eigene Sonderkarte + Seite),
  erweitertes Formular (Intro/ausführliche Vorstellung/zweiter Button,
  eingeklappt unter "Erweitert"), neue Sektion "Kategorien &
  Seitentitel" (4 Karten, sofort wirksam auf Website UND Verwaltung).

Beim Testen einen echten UX-Bug gefunden und gefixt: die "Gespeichert"-
Meldung nach dem Speichern eines Mitglieds wurde von der direkt
anschließenden Formular-Zurücksetzung sofort wieder überschrieben und
war nie sichtbar.

Cache-Busting-Version auf 20260821k erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 03:47:51 +02:00
DogFatherGitandClaude Sonnet 5 7060a4a6ae Verwaltungsseite perfektioniert: Team-Verwaltung für Modis/Scouts/Creator/Manager
Nutzer-Wunsch 21.08.2026: "überall wo Modis sind oder Scouts oder
Manager, oder Creator, will ich dass ich die easy über meine
Verwaltungsseite hinzufüge und die automatisch in der Website
hinzugefügt werden ... auch mit Fotos und TikTok Link."

Backend (server-internal, braucht Filipes manuellen Deploy):
- Neue Tabelle team_members (Migration 0007) für alle vier Kategorien
  gemeinsam -- ergänzt, überschreibt NIE die von Hand gepflegten
  Einträge in data-modis.js/data-scouts.js/data-creator.js.
- routes/team.js: öffentliches Lesen (nur aktive Mitglieder, optional
  nach Kategorie gefiltert), TEAM_MANAGE-geschütztes Anlegen/Bearbeiten/
  Löschen, Foto-Upload (gleiches Muster wie "Event des Jahres"),
  automatische Übersetzung von Rolle/Bio/Zitat wie bei anderen
  admin-gepflegten Texten. Slug global eindeutig (mit automatischer
  Kollisionsauflösung), TikTok-Kurzname wird zu voller URL ergänzt.
  27 Tests in isolierter Testumgebung geprüft (kein better-sqlite3
  lokal kompilierbar).

Frontend:
- window.dogiTeamLaden() in main.js: holt admin-gepflegte Mitglieder
  einer (oder aller) Kategorien und bringt sie in exakt dieselbe Form
  wie die bestehenden data-*.js-Einträge.
- team-scouts.html/team-modis.html/creator.html hängen das Ergebnis
  einfach an ihre bestehenden Arrays an und rendern erneut -- exakt
  derselbe Look wie die schon bestehenden Profile (Foto/Avatar-Initiale,
  Rolle, Zitat, TikTok-Button). creator.html hatte bisher ein "return"
  bei leerem CREATORS-Array, wodurch admin-Creator NIE geladen worden
  wären -- gefixt. team-modis.html berücksichtigt Rang/Rang-Bezeichnung
  für die Pyramide.
- Neue Sektion "Weitere Manager" auf manager.html, komplett unsichtbar
  bis der erste Manager angelegt wird (data-manager.js neu, wie
  data-creator.js aktuell leer).
- profil.html sucht jetzt kategorieübergreifend auch in admin-gepflegten
  Profilen, inkl. korrektem Theme/Zurück-Link auch für Manager.

Verwaltung: neue Sektion "Team verwalten" (TEAM_MANAGE-Berechtigung) --
ein Formular für alle vier Kategorien mit Foto-Sofort-Upload,
TikTok-Feld, Bio/Zitat, bedingten Rang-Feldern (nur Modi), Kategorie-
Filterleiste und Bearbeiten/Löschen pro Eintrag.

Beim Testen mit Playwright einen echten Syntaxfehler gefunden und
gefixt (ASCII-Anführungszeichen statt schließendem „" in einem
Statustext), der das GESAMTE Verwaltungs-Skript und damit die komplette
Seite lahmgelegt hätte.

Cache-Busting-Version auf 20260821j erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 03:06:21 +02:00
DogFatherGitandClaude Sonnet 5 8ead1b750b KRITISCH: echten Ursprung der "rohen Übersetzungs-Schlüssel"-Bugs gefunden und behoben
Beide heutigen Meldungen ("pr_quote_open...", "ts_profil_ansehen") waren
KEIN Caching-Problem, sondern ein echter Bug in main.js: nach Klick auf
einen internen Link und dann "Zurück" (oder generell jede zweite Seite
innerhalb einer Browser-Sitzung) wurde die seiteneigene i18n-*.js-Datei
nie erneut ausgeführt -> window.I18N_PAGE blieb auf null -> jede
Übersetzung fiel auf den rohen Schlüsselnamen zurück.

Ursache: skripteUebernehmen() erkennt i18n-Dateien am Muster ".js$"
(String-Ende). Seit die Cache-Busting-Version ("?v=...") an jede
Skript-URL angehängt wird, endet der echte src-Wert aber nie mehr auf
".js", sondern auf ".js?v=...". Der Test schlug seitdem für JEDE
i18n-Datei fehl und sie wurde wie eine normale, schon geladene Datei
behandelt und beim nächsten Seitenwechsel übersprungen.

Mit Playwright reproduziert (Klick auf Profil-Kachel + Zurück-Button)
und nach dem Fix erneut verifiziert -- betraf praktisch jede Seite mit
eigenem i18n-*.js beim Navigieren per Klick, nicht nur team-scouts.html.

Cache-Busting-Version auf 20260821i erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 02:12:24 +02:00
DogFatherGitandClaude Sonnet 5 fbd11b7be4 "Was gerade läuft"-Aktionen-Teaser von der Startseite entfernt
Nutzer-Wunsch 21.08.2026: Überschrift + Button "Alle Aktionen & Projekte"
auf index.html weg. data-aktionen.js-Script-Tag (nur noch dafür gebraucht)
und die zugehörigen JS-Renderzeilen ebenfalls entfernt, dazugehörige
i18n-Keys (idx_aktionen_h2/idx_aktionen_btn) aus i18n-index.js aufgeräumt.
aktion-detail.html und data-aktionen.js selbst bleiben unangetastet.

Cache-Busting-Version auf 20260821h erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 02:04:43 +02:00
DogFatherGitandClaude Sonnet 5 ca5793e79f Patricks Profil-Abschluss um "Scout von Dogfather" ergänzt (wie Bananenstift)
Nutzer-Wunsch 21.08.2026: Patricks Bio endete nur mit "- euer Patrick",
Bananenstift hat zusätzlich eine zweite Zeile "Scout von Dogfather".
Für Konsistenz zwischen beiden Scout-Profilen in allen 5 Sprachen ergänzt.

Cache-Busting-Version auf 20260821g erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 01:53:57 +02:00
DogFatherGitandClaude Sonnet 5 c7904ccd62 TikTok-Buttons auf Patrick- und Bananenstift-Scout-Profilen ergänzt
Nutzer-Wunsch 21.08.2026: unter dem Namen/Rolle-Text je ein TikTok-Button
(@patrick180585 bzw. @bananenstift009). Beide nutzen den bereits
bestehenden social-Mechanismus in profil.html (social.tiktok -> echter
.btn-tiktok-Button), kein neuer Code nötig.

Cache-Busting-Version auf 20260821f erhöht (data-scouts.js ist .js und
damit von Cloudflares erzwungenem Edge-Cache betroffen).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 01:49:00 +02:00
DogFatherGitandClaude Sonnet 5 ac01a74d08 Zeitreise: neue Station "Erstes Fan-Treffen: Team TiliDog" (25. Juli 2026)
Nutzer-Wunsch 21.08.2026: erstes Fan-Treffen von Dogi & Tili (Team
TiliDog) in Wuppertal ergänzt -- gleichzeitig das erste persönliche
Aufeinandertreffen von DogFather und Tili. Als Meilenstein markiert und
chronologisch korrekt zwischen "Juli 2026 — Start als Manager" und
"27. Juli bis 2. August 2026 — Creator Cup" einsortiert.

Cache-Busting-Version auf 20260821e erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 01:39:47 +02:00
DogFatherGitandClaude Sonnet 5 360f19a52d Echtes Foto von Filipe in der Intro-Sektion auf streamer.html ergänzt
Nutzer-Wunsch 21.08.2026: "füge das foto was ich am ende mitschicke
neben den text im screen1". Sektion von einspaltigem Fließtext auf
grid-2 umgebaut, Foto (assets/img/streamer-filipe-portrait.jpg, aus
Pictures/Filipe, auf 1000x1500 verkleinert) rechts daneben mit
frame-gold-Rahmen für Abwechslung zur Casper-Sektion (frame-lila).

Cache-Busting-Version auf 20260821d erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 01:29:03 +02:00
DogFatherGitandClaude Sonnet 5 6106cf9f03 Modi-Gang TikTok-Button von streamer.html nach team-modis.html verschoben
Der Button gehört thematisch besser zum Modi-Team als zur Casper-Sektion
auf streamer.html (Nutzer-Wunsch 21.08.2026: "den knopf da weg bitte und
in die modie seite zu den modis hinzufügen und perfekt in die seite
anpassen"). Jetzt im Hero von team-modis.html, unter dem Lead-Text,
zentriert im bestehenden btn-row-Muster der Seite.

Cache-Busting-Version auf 20260821c erhöht.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 01:24:43 +02:00
DogFatherGitandClaude Sonnet 5 ed9b373a74 Husky-Bild auf streamer.html an Texthöhe angepasst statt fixem Mini-Deckel
Vorheriger max-height-Deckel (460px) fürs sehr hochkantige
streamer-mascot.jpg (900x2812) war zu knapp und ließ eine sichtbare
Lücke neben dem längeren Text ("die größe vom bild vom husky soll dem
text rechts nebendran angepasst werden"). Deckel auf 720px erhöht
(orientiert an der typischen Texthöhe in diesem Abschnitt), Grid-Stretch-
Ansatz ausprobiert und wegen Rückkopplung mit dem extremen
Seitenverhältnis verworfen (siehe Kommentare in main.css/streamer.html).

Cache-Busting-Version auf 20260821b erhöht (Cloudflare cached CSS/JS
sonst bis zu 4h am Edge).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 01:21:31 +02:00
DogFatherGitandClaude Opus 5 1f87b54351 Nav umbenannt/umsortiert + Stimmen-Kachel und Zitat-Karten aufgewertet
Nutzer-Wuensche 20.08.2026 (2. Runde):
- Kategorie "DogFather" -> "Filipe", Kategorie "HasiDog" -> "Dogi&Hasi".
- Unterpunkt "Streamer" (streamer.html) aus "Filipe" heraus nach
  "Dogi&Hasi" verschoben, dort GANZ NACH OBEN (ueber "HasiDog") und in
  "DogFather" umbenannt.
- Unterpunkt "HasiDog-Welt" -> "HasiDog".
- Fusszeile zieht mit: Spaltenueberschrift nutzt jetzt dieselbe
  Kategorie-Bezeichnung wie die Nav ("Filipe" / "Dogi&Hasi & Manager"),
  streamer.html steht dort ebenfalls in der Dogi&Hasi-Spalte ganz oben.
  Die internen Schluesselnamen (nav_dogfather...) bleiben bewusst
  unveraendert -- reine Bezeichner, ein Umbenennen waere nur Fehlerquelle.

- "die kachel soll noch spezieller und geiler aussehen": Einreich-Kachel
  auf stimmen.html deutlich aufgewertet -- wandernder Farbverlauf-Rahmen
  (Zwei-Ebenen-/background-position-Technik, KEIN rotierender Ring: siehe
  dokumentierte Projekt-Lektion zu Verzerrungen auf eckigen Flaechen),
  schwebende Herz-Partikel, Medaillon statt nacktem Emoji,
  Farbverlauf-Ueberschrift, aufleuchtende Eingabefelder.
- "und auch die die danach kommen ... sollen viel geiler sein": freigegebene
  Stimmen sind jetzt echte Praesentationskarten -- farbige Akzentlinie oben,
  grosses Anfuehrungszeichen als Wasserzeichen, Avatar-Medaillon mit
  Anfangsbuchstabe, TikTok-Handle als eigener Chip, sanftes Anheben beim
  Ueberfahren.

Alles augenschonend gehalten (gedeckte Toene, langsame Bewegungen,
vollstaendiger Stillstand bei prefers-reduced-motion) und per Playwright
visuell geprueft, keine JS-Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 01:02:36 +02:00
DogFatherGitandClaude Opus 5 5146cef164 TikTok-Knoepfe fuer HasiDog + Modi-Gang, Zeitreise-Reihenfolge, Bildgroesse
Nutzer-Wuensche 20.08.2026:
- hasidog.html: TikTok-Knopf direkt unter der grossen Ueberschrift,
  Account @hasidog0804 (alle 5 Sprachen uebersetzt).
- streamer.html: TikTok-Knopf unter "Casper - mein treuer Begleiter",
  Account @dogis.modi.gang (alle 5 Sprachen uebersetzt).
- zeitreise.html: die beiden letzten Karten getauscht -- der Website-Start
  (21.08.2026, konkretes Datum) steht jetzt VOR der Teddy-Kooperation
  ("Datum folgt"), damit die Zeitleiste durchgehend chronologisch bleibt.
- streamer.html Bildgroesse gefixt ("der soll bissl kleiner sein und nicht
  so riesig"): streamer-mascot.jpg ist 900x2812 px und lief mit
  aspect-ratio:auto + height:auto in voller natuerlicher Hoehe -- rund
  dreimal so hoch wie die Textspalte daneben. Neue Klasse
  .collage-photo-kompakt deckelt die Hoehe auf 460px und laesst den Rahmen
  eng am Bild sitzen (width:fit-content), die ganze Figur bleibt sichtbar.
  Regel steht bewusst NACH ".collage-photo img" -- gleiche Spezifitaet,
  die spaetere gewinnt, sonst haette width:100%/height:100% sie aufgehoben.

Alles per Playwright verifiziert (beide Knoepfe mit korrekten Links,
Bildhoehe 460px statt ~1780px, neue Zeitreise-Reihenfolge), keine JS-Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-20 23:46:04 +02:00
DogFatherGitandClaude Opus 5 399260b805 "Stimmen" verwandelt: Fans reichen selbst Testimonials ein
Nutzer-Wunsch 20.08.2026: "eine richtig geile kachel ... wo die leute mit
namen und tiktok namen mir eine nachricht schreiben können die ich in die
verwaltung kriege, und dann kann ich die ausgewählten über die
verwaltungsseite auf die website hinzufügen ... das wird mega persoenlich
zu den fans, bitte wirklich krass geil speziell."

- Neue, augenschonend gestaltete Einreich-Kachel auf stimmen.html: Name,
  TikTok-Name (optional), Nachricht -- landet NIE automatisch oeffentlich,
  sondern immer erst als Entwurf in der Verwaltung.
  Warmer Babyblau/Rosé-Farbverlauf, wandernder Lichtschein, pulsierendes
  Herz -- ersetzt die 3 ewigen "Hier steht bald..."-Platzhalterkarten.
- Neue Verwaltungs-Sektion "💬 Stimmen verwalten": Warteschlange (offene
  zuerst), Freigeben/Ablehnen/Löschen pro Eintrag.
- Freigegebene Stimmen erscheinen automatisch in einer neuen, spezielleren
  Zitat-Kartenoptik (großes Anführungszeichen, Name + TikTok-Chip) --
  Abschnitt bleibt komplett unsichtbar, solange keine einzige freigegeben
  wurde.
- Backend: neue Tabelle `testimonials` (Migration 0006), routes/
  testimonials.js (oeffentliches Einreichen + Lesen freigegebener,
  admin-Warteschlange + Status/Loeschen mit neuer TESTIMONIALS_MANAGE-
  Berechtigung). 18 automatisierte Tests gegen eine Fake-DB bestanden.
- Alles per Playwright visuell durchgespielt: leerer Zustand, Einreichen
  -> Erfolgsmeldung, freigegebene Stimmen-Anzeige, Verwaltungs-Warteschlange
  mit allen Aktionen.

Backend-Teil (server-internal/, cloudflare-worker/migrations/) noch ohne
Deploy-Zugriff -- Dogi muss ihn manuell auf dogiintern ausrollen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-20 23:37:31 +02:00
DogFatherGitandClaude Opus 5 519e209bce Zweite Live-Uhr fuer "spezielles Live-Event" + mehr Farbe im Radar
Nutzer-Wunsch 20.08.2026: "wuensch mir nur noch bissl farbe und sehr
wichtig ist dass ich auch spezielle live events da auch eintragen kann
in der verwaltungsseite so dass da eine zweite uhr erscheint wo die zeit
dann fuer dieses spezielle event laeuft."

- Neue Verwaltungs-Sektion "Spezielles Live-Event": Titel (Deutsch, wird
  automatisch uebersetzt), echtes Datum+Uhrzeit, optionaler Link, Aktiv-
  Schalter -- nur mit Titel + Zukunftsdatum aktivierbar.
- Zweite Uhr auf streamplan.html (Magenta/Violett statt Cyan/Gold, direkt
  neben der bestehenden), nur sichtbar wenn ein Event aktiviert ist und
  das Zieldatum noch nicht vorbei ist. Echter Countdown inkl. Tage (z.B.
  "2T 03:14:59"), "Jetzt"-Zeiger zeigt wie bei Uhr 1 die tatsaechliche
  Uhrzeit, der magentafarbene Fixpunkt markiert die Tageszeit des Events.
  Zieldatum wird als UTC gespeichert -- jede besuchende Person sieht den
  exakt richtigen Countdown in ihrer eigenen Zeitzone.
- "Bissl Farbe": bunter Farbverlauf (Cyan/Violett/Gold) auf dem aeusseren
  Ring statt reinem Grauton, kraeftigerer Sweep-Farbschein.
- Backend: neue routes/special-event.js (getSpecialEventPublic nur bei
  aktiv+zukuenftig, getSpecialEventAdmin fuer Entwuerfe, saveSpecialEvent
  mit Validierung), 13 automatisierte Tests gegen eine Fake-DB bestanden.
- Bugfix unterwegs gefunden (Playwright-Screenshot, wiederholtes Muster
  auf dieser Seite): .stream-radar-wrap blieb trotz [hidden]-Attribut
  sichtbar (display:block ueberschreibt die eingebaute [hidden]-Regel bei
  gleicher Spezifitaet) -- explizite Regel ergaenzt, per Playwright erneut
  verifiziert (display:none bestaetigt).

Backend-Teil (server-internal/) noch ohne Deploy-Zugriff -- Dogi muss ihn
manuell auf dogiintern ausrollen, sonst bleibt die zweite Uhr unsichtbar.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-20 23:24:17 +02:00