Files
posts/POST-6.md
T
dejanandClaude Opus 5 ce87a7fb57 Post 6: fuenfte Slide fuer den mobilen Chat, Tiefe ueber den Stapel
Zwei Nachbesserungen an Post 6: eine Slide mehr und Zeichnungen, die nicht
mehr flach aussehen.

DIE FUENFTE SLIDE KOMMT VON DER WEBSITE
Die App gibt es noch nicht, und die Website sagt das bereits. In
components/sections/ChatDemoSection.tsx steht unter der Fahne comingSoon
genau dieser Zustand: ein Handy-Mockup, verwischt, und darueber ein
Absperrband aus dem Bau -- gedreht um -13 Grad, in accent-yellow F1B729 mit
Kanten in 171106, darauf immer wieder Schutzhelm und BALD VERFUEGBAR.

Ein Zwischenstand hatte hier einen selbst erfundenen gelben Aufkleber
"In Arbeit". Das war eine zweite Bildsprache neben einer vorhandenen.
Uebernommen ist jetzt die der Website, samt Winkel, Farben und Wortlaut.

Auch der Inhalt des Schirms kommt von dort und nicht aus dem Pitch-Paket:
Heizungsprojekt Schulz, "4 Mitglieder · 2 online", die vier Nachrichten aus
seedMessages, die Blasenfarben 0D6E6E fuer eigene und FFFFFF mit Rand E9E7E5
fuer fremde, der warme Grund hsl(30 17% 95.5%). Ueberschrift und Fliesstext
ebenso: "Der Chat fuer unterwegs wird gerade gebaut."

Das Geraet selbst ist eine bewusste Abweichung. Die Website zeichnet nur
einen hellen Umriss, border 4px D1D5DB; auf einer Slide, die selbst hell ist,
faellt der in sich zusammen und sieht nach Platzhalter aus. Hier steht ein
richtiges Geraet: dunkler Korpus, heller Grat, Schirm eingelassen, Insel und
Tasten. Die Abweichung betrifft den Rahmen, nicht den Inhalt. Verwischt wird
schwaecher als dort -- auf der Website liegt das Handy gross neben Fliesstext
und darf unlesbar sein, hier ist es klein, und bei voller Staerke blieb Brei.

DIE TIEFE
Zwei Anlaeufe waren falsch. Der erste legte graue Flaechen hinter die
Elemente: das nimmt den Zeichnungen ihre Durchsichtigkeit und setzt einen
Kasten auf den Punktgrund, der dort nicht hingehoert. Wieder raus, die
Zeichnungen sind wieder durchsichtig.

Der zweite waren bessere Schatten allein. Richtig, aber zu wenig. Die
Schatten des Produkts sind in ui/theme.css gestaffelt und nicht einlagig:

  --shadow-md  0 4px 16px -2px  +  0 2px 4px -1px
  --shadow-lg  0 12px 32px -4px +  0 4px 8px -2px

Zwei Lagen, weil eine allein nicht beides kann: die enge dunkle Kante setzt
das Element auf die Flaeche, die weite helle hebt es davon ab. In SVG zwei
feDropShadow im selben Filter. Vorher stand dort einer mit dy 7.

Gebracht hat es der Stapel. post1.html hat ihn als Bildrahmen im CSS, fuer
Screenshots; hier ist er in SVG nachgebaut, mit denselben Werten:

  .sheet-mid   rotate(-2.4deg) translate(-2.2%, 3%)  scale(.975)
  .sheet-back  rotate( 3.2deg) translate( 3%,  5.5%) scale(.95)

Er gibt Tiefe, die ein Schatten allein nicht schafft, und sagt, dass hinter
der einen Ansicht weitere liegen. Die hinteren Blaetter sind leer --
Andeutung, keine Kopie. Auf Slide 1 und 2, wo ein Bildschirm zu sehen ist;
nicht auf Slide 3, wo ein Ausschnitt einer Unterhaltung steht, und nicht auf
Slide 4, die eine Ueberlagerung ist.

AUS DER QUELLE NACHGEHOLT
Beim gruendlichen Durchgang durch GeneralTeamChatPage.tsx sind drei Dinge
aufgefallen, die vorher fehlten oder falsch waren:

- Die Datumsmarke "Heute · 30.07.2026" ueber dem ersten Beitrag und die Zeile
  "Maike Berger schreibt gerade ..." ueber dem Eingabefeld. Beides gibt der
  Unterhaltung Struktur, ohne eine Flaeche zu behaupten.
- Der offene Kanal ist grau hinterlegt mit Rand und shadow-sm, nicht violett.
- Die Blase muss so breit sein, wie ihr Anhang es braucht. Vorher richtete
  sie sich nur nach dem Fliesstext, und "Materialliste pruefen · faellig
  31.07.2026" wurde abgeschnitten -- an einer Stelle, an der der Titel die
  Aussage traegt.

ZWEI FALLEN
Gedrehte Blaetter ragen aus dem Kasten. Das hinterste steht um 3,2 Grad
gedreht und um 3 und 5,5 Prozent verschoben; seine Ecken lagen bis zu 24 px
ausserhalb der 92-px-Schutzzone. Der Ueberstand wird jetzt gerechnet:
stapelRand() schickt die vier Ecken durch dieselbe Kette wie das Blatt.

getBBox() kennt keine Beschneidung. Das Absperrband war erst auf die 175 %
der Website gezogen und am Geraet abgeschnitten -- im Bild richtig, in der
Messung ein Ueberstand von 146 px, den es nicht gab. Es ist jetzt nur so
lang, wie es bei -13 Grad quer ueber das Geraet sein muss.

GEPRUEFT
Raender 93 / 227 / 110 / 140 / 350, Luft 116 / 79 / 190 / 141 / 77 px, alle
Ueberschriften innerhalb der Schutzzone, 214 CSS-Regeln, Konsole ohne Fehler,
fuenf PNGs aus dem echten Ausgabeweg bei 2160 x 2700. Downloads blieb leer,
der Projektstand unveraendert.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 17:24:45 +02:00

260 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Post 6 · Team-Chat
Fünfter Beitrag der Produktreihe, Termin **Mi 26.08.** laut Redaktionsplan
(von Mo 24.08. verschoben). Stichwort dort: „Ein Kanal pro Projekt, Foto rein,
Aufgabe raus."
Hell, Theme `modern`, Punktgrund, Text zentriert — dieselbe Anlage wie Post 4
und 5. Datei `post6.html`, Stand in `state/post6.json`, erreichbar über das
Projektmenü jeder Seite und über `uebersicht.html`.
**Fünf Slides.** DSGVO und deutsche Server hätten einen sechsten Punkt
ergeben, dafür gibt es aber keinen Bildschirm. Der steht in der
Bildunterschrift, wo eine Aussage ohne Bild hingehört.
---
## 1. Die vier Slides
| # | Tag | Überschrift | Was zu sehen ist |
|---|---|---|---|
| 1 | Team-Chat | Büro und Baustelle, **endlich im selben Chat.** | Kanalliste und Verlauf nebeneinander, mit Filterzeile und Eingabefeld |
| 2 | Die Kanäle | Ein Kanal **pro Projekt.** | Die Chatliste groß: Projektkanäle, Direktnachrichten, Gruppe |
| 3 | Die Aufgabe | Foto rein, **Aufgabe raus.** | Baustellenfotos, die Aufgabe daraus, die Bestätigung im Projekt |
| 4 | Das Pluszeichen | Nicht nur **Text.** | Das Menü hinter dem Plus im Eingabefeld |
| 5 | Bald verfügbar | Der Chat für unterwegs **wird gerade gebaut.** | Das Handy-Mockup der Website, verwischt, mit Absperrband |
**Slide 3 ist der Kern.** Der Redaktionsplan verlangt „Foto rein, Aufgabe
raus", und genau das liegt im Werkzeug als Abfolge vor: Tobias schickt die
Baustellenfotos, darauf folgt eine Nachricht mit angehängter Aufgabe, darauf
eine Systemzeile „Aufgabe „Materialliste prüfen" im Projekt erstellt". Die
letzte Zeile macht den Unterschied: die Aufgabe liegt danach im Projekt und
nicht nur im Verlauf.
Slide 1 trägt den ganzen Chat, weil sie im Profilraster eine Kachel von rund
150 px ist. Dort ist kein Wort lesbar; was ankommt, sind zwei Spalten mit
Blasen.
---
## 2. Die Bildunterschrift
```
Im Handwerk läuft die halbe Baustelle über WhatsApp. Das Foto von letzter Woche findet trotzdem keiner wieder.
In HiveGrid hat jedes Projekt seinen eigenen Kanal, mit Projektnummer. Daneben stehen Direktnachrichten und Gruppen, aber eben nicht alles in einem Verlauf.
Ein Foto von der Baustelle geht rein, alle sehen es sofort. Aus „mach das mal“ wird mit einem Klick eine echte Aufgabe: mit Frist, mit Namen, im Projekt.
Dokument, Sprachnachricht, Kontakt, Termin. Was sonst im Chat-Verlauf verschwindet, hängt hier am Projekt.
Kundendaten gehören nicht in eine WhatsApp-Gruppe. Bei HiveGrid liegen sie verschlüsselt auf deutschen Servern.
#handwerk #shk #handwerksbetrieb #digitalisierungimhandwerk #teamchat #baustelle #kommunikation #hivegrid
```
| Vorgabe | Ist |
|---|---|
| Haken in den ersten 125 Zeichen | erster Absatz, 110 |
| 300 bis 800 Zeichen | 644 |
| 5 bis 10 Hashtags, unten abgesetzt | 8 |
| Suchwörter zusätzlich im Fließtext | Handwerk, Baustelle, Projekt, Kanal, Aufgabe, Chat, Kontakt, Termin |
Der letzte Absatz steht **wörtlich** so als Merkmal „DSGVO-konform" in
`lib/produkt-daten.ts` der Website. „Aus „mach das mal" wird mit einem Klick
eine echte Aufgabe" ebenfalls, als Merkmal „Aufgaben-Integration".
---
## 3. Woher die Angaben kommen
Quelle ist `components/general/GeneralTeamChatPage.tsx` aus dem Pitch-Paket
(*fertig bombo · Kundentermin 30.07.2026*).
| Was | Woher |
|---|---|
| Alle acht Kanäle: Titel, Vorschau, Zeit, Zuordnung, Nadel, Ungelesen | `CHATS`, wörtlich |
| Der Verlauf: Autoren, Texte, Zeiten, Anhänge | `INITIAL_MESSAGES.waermepumpe`, wörtlich |
| Aufbau einer Listenzeile (drei Zeilen) | die Zeilen 170 bis 172 der Quelle |
| Aufbau einer Nachricht, Anhangkarte, Systemzeile | `MessageBubble` und `AttachmentCard` |
| Sinnbild je Kanalsorte (Koffer, Personen, Kürzel) | `ChatAvatar` |
| Kopfzeile „P-2026-0042 · 8 Mitglieder · aktiv" | `ChatHeader` |
| Filterzeile Alle / Projekte / Direkt / Ungelesen | der Typ `ChatFilter` |
| Das Menü hinter dem Plus, samt Trenner | `Composer` |
| Eingabefeld „Nachricht schreiben …" | derselbe Ort |
| Farben, Ränder, Plättchentöne | `ui/theme.css` |
| Alle Symbole | `@subframe/core`, Pfade aus dem Paket kopiert |
| „Büro und Baustelle, endlich im selben Chat." | Überschrift in `lib/produkt-daten.ts` |
**Vom Chat gibt es nur eine Fassung.** Anders als bei der Pipeline, die mit
Board, Liste, Detail und Schablone vier eigene SHK-Bildschirme hat, liegt der
Chat allein unter `/allgemein/team-chat`. Die Inhalte darin sind trotzdem aus
dem Gewerk: Wärmepumpe Müller, Montagetermin, Baustellenfotos.
---
## 4. Wo bewusst abgewichen wird
**Slide 1 zeigt drei von sechs Nachrichten, Slide 2 fünf von acht Kanälen.**
Was nicht ins Bild passt, fällt weg; ein Chat und eine Liste scrollen beide.
Slide 2 behält alle drei Sorten: Projektkanal, Direktnachricht, Gruppe.
**Die Bildergalerie ist eine Anhangkarte, kein Bild.** Im Werkzeug zeigt
`GalleryPreview` zwei Fotos, geladen von Unsplash. Fremde Fotos in einen
Beitrag zu setzen, der von der eigenen Baustelle spricht, wäre eine Behauptung
über Material, das wir nicht haben. Stattdessen steht dort die Karte
„2 Baustellenfotos · Galerie · heute" — der Text ist der der Quelle.
---
## 5. Stand der Dinge
| | |
|---|---|
| Slides | 5 |
| Format | 1080 × 1350, Ausgabe zweifach: 2160 × 2700 |
| Luft zwischen Text und Zeichnung | 116 / 79 / 190 / 141 / 77 px (Grenze 40) |
| Zeichnung ragt über die Seite | nein, alle innerhalb der 92-px-Schutzzone |
| Breiteste Überschriftzeile | 818 px von 896 |
| Stylesheet vollständig | 214 Regeln, `[data-edit]` vorhanden |
| Konsole | keine Fehler |
| Ausgabeweg | geprüft, `01-chat-hell.png` bis `05-handy-hell.png` |
Geprüft wird mit den Hilfsskripten aus dem Sitzungsordner: `pruef.mjs` misst
über `getBBox()` die tatsächlich gezeichnete Fläche je Slide und die Breite
jeder Überschriftzeile, zählt die Regeln im Stylesheet und liest die Konsole
mit; `schuss.mjs` rendert einzelne Slides; `export.mjs` fährt den echten
Ausgabeweg und fängt `/save` ab.
---
## 5a. Slide 5 kommt von der Website, nicht von mir
**Das Gerät ist eine bewusste Abweichung.** Die Website zeichnet nur einen
hellen Umriss (`border: 4px solid #D1D5DB`). Auf einer Slide, die selbst hell
ist, fällt der in sich zusammen und sieht nach Platzhalter aus. Hier steht
deshalb ein richtiges Gerät: dunkler Korpus, heller Grat, Schirm eingelassen,
Tasten an der Seite. Die Abweichung betrifft den Rahmen, nicht den Inhalt. Der
Schirm wird auch schwächer verwischt als dort: auf der Website liegt das Handy
groß neben Fließtext und darf unlesbar sein, hier ist es klein, und bei voller
Stärke blieb nur Brei.
**Die App gibt es noch nicht, und die Website sagt das bereits.** In
`components/sections/ChatDemoSection.tsx` steht unter der Fahne `comingSoon`
genau dieser Zustand: ein Handy-Mockup, das mit `blur(3px) saturate(0.92)`
verwischt wird, und darüber ein **Absperrband** aus dem Bau, gedreht um
**-13°**, in `--accent-yellow` `#F1B729` mit Kanten in `#171106`, darauf immer
wieder Schutzhelm und **BALD VERFÜGBAR**.
Ein Zwischenstand hatte hier einen selbst erfundenen gelben Aufkleber
„In Arbeit". Das war eine eigene Bildsprache neben einer vorhandenen.
Übernommen ist jetzt die der Website, samt Winkel, Farben und Wortlaut.
Auch der Inhalt des Schirms kommt von dort und **nicht** aus dem Pitch-Paket:
Heizungsprojekt Schulz, „4 Mitglieder · 2 online", die vier Nachrichten aus
`seedMessages`, die Blasenfarben `#0D6E6E` für eigene und `#FFFFFF` mit Rand
`#E9E7E5` für fremde, der warme Grund `hsl(30 17% 95.5%)`. Auf der Website
steht dieses Handy für den mobilen Chat, also zeigt es hier dasselbe.
Überschrift und Fließtext sind ebenfalls die der Website: „Der Chat für
unterwegs wird gerade gebaut." und „Die mobile App legen wir gerade auf die
Baustelle. Am Desktop bist du schon voll dabei, die Version fürs Handy folgt
in Kürze." Der Em-Dash der Vorlage ist durch ein Komma ersetzt, `rules.md` §4.
---
## 5b. Woher die Tiefe kommt
Zwei Anläufe waren falsch, bevor es saß.
**Erster Versuch: graue Flächen hinter die Elemente.** Das nimmt den
Zeichnungen ihre Durchsichtigkeit und setzt einen Kasten auf den Punktgrund,
der dort nicht hingehört. Wieder raus.
**Zweiter Versuch: nur bessere Schatten.** Richtig, aber zu wenig. Die
Schatten des Produkts sind in `ui/theme.css` **gestaffelt** und nicht
einlagig, und das war tatsächlich ein Fehler im ersten Nachbau:
```
--shadow-sm 0 1px 2px rgb(0 0 0 / .08)
--shadow-md 0 4px 16px -2px + 0 2px 4px -1px
--shadow-lg 0 12px 32px -4px + 0 4px 8px -2px
```
Zwei Lagen, weil eine allein nicht beides kann: die enge dunkle Kante setzt
das Element auf die Fläche, die weite helle hebt es davon ab. In SVG zwei
`feDropShadow` im selben Filter. Vorher stand dort einer mit `dy 7` und
`stdDeviation 10`.
**Was es gebracht hat: der Stapel.** `post1.html` hat ihn als Bildrahmen
`stapel` im CSS, für Screenshots. Hier ist er in SVG nachgebaut, mit genau
denselben Werten, damit die Reihe zusammenpasst:
```
.sheet-mid rotate(-2.4deg) translate(-2.2%, 3%) scale(.975)
.sheet-back rotate( 3.2deg) translate( 3%, 5.5%) scale(.95)
```
Er trägt zwei Aufgaben: er gibt Tiefe, die ein Schatten allein nicht schafft,
und er sagt, dass hinter der einen Ansicht weitere liegen. Die hinteren
Blätter sind deshalb **leer** — Andeutung, keine Kopie.
Auf Slide 1 und 2 liegt er, weil dort ein Bildschirm zu sehen ist. Auf Slide 3
nicht: ein Ausschnitt aus einer Unterhaltung ist kein Blatt, dort tragen die
Blasen ihre eigene Erhebung. Slide 4 ist eine Überlagerung und trägt
`--shadow-overlay`.
Dazu zwei Dinge aus der Quelle, die der Unterhaltung Struktur geben, ohne eine
Fläche zu behaupten: die Datumsmarke **Heute · 30.07.2026** über dem ersten
Beitrag und die Zeile **„Maike Berger schreibt gerade …"** über dem
Eingabefeld. Beides steht so in `GeneralTeamChatPage.tsx`.
Nebenbei richtiggestellt: **der offene Kanal ist grau hinterlegt, nicht
violett.** Im Original steht dort `bg-surface-neutral-primary` mit Rand und
`shadow-sm`.
---
## 6. Fünf Fallen aus diesem Bau
**Die Listenzeile hat drei Zeilen, nicht zwei.** Der erste Anlauf setzte Titel
und Vorschau untereinander und schob Nadel und Ungelesen-Punkt rechts neben
die Vorschau. Dort stießen sie an den Text — und die Zuordnung fehlte ganz.
Im Original steht sie als dritte Zeile: `P-2026-0042` links, die Nadel rechts.
Das war nicht nur ein Layoutfehler: der Fließtext behauptete „Jeder Kanal hängt
an seiner Projektnummer", und die Nummer war nirgends zu sehen.
**Eine feste Obergrenze für die Blasenbreite hat ein Zitat gekürzt.** Für die
Titelslide musste sie klein sein, damit die Unterhaltung neben die Liste passt.
Auf Slide 3 stand deshalb „Materialliste prüfen · fälli…" statt
„… · fällig 31.07.2026". Die Grenze hängt jetzt an der Spalte, in der die Blase
steht.
**Beinahe hätte ich ein Zitat ohne Grund gekürzt.** Die Website-Überschrift
lautet „Büro und Baustelle, endlich im selben Chat." Ich hatte das „endlich"
gestrichen mit der Begründung, die Zeile laufe sonst über die Schutzzone, und
diese Begründung sogar mit einer Zahl versehen, die ich nicht gemessen hatte.
Nachgemessen sind es 818 px von 896 erlaubten: sie passt. Das Wort ist wieder
drin. Dafür gibt es jetzt `breite.mjs`, das eine Formulierung misst, bevor sie
in die Datei kommt.
**Gedrehte Blätter ragen aus dem Kasten.** Der Stapel dreht das hinterste
Blatt um 3,2° und verschiebt es um 3 % und 5,5 % der eigenen Größe. Die Ecken
stehen damit über das vordere Blatt hinaus, und die Zeichnung lag bis zu 24 px
außerhalb der 92-px-Schutzzone. Der Überstand wird jetzt gerechnet statt
geschätzt: `stapelRand()` schickt die vier Ecken durch dieselbe Kette wie das
Blatt und nimmt den größten Wert. `stapelKasten()` macht den Kasten
entsprechend größer.
**`getBBox()` kennt keine Beschneidung.** Das Absperrband war zuerst auf die
175 % der Website gezogen und per `clip-path` am Gerät abgeschnitten. Im Bild
stimmte das, die Randmessung meldete aber einen Überstand von 146 px, den es
gar nicht gab: `getBBox()` liefert die Geometrie, nicht das Sichtbare. Das
Band ist jetzt nur so lang, wie es bei -13° quer über das Gerät sein muss,
also `B / cos(13°)` plus Zugabe. Messung und Bild sagen wieder dasselbe.
**Das Prüfskript nahm eine leere Slide auf.** `schuss.mjs` stellte für eine
einzelne Slide ein Fenster von 1400 px. Im durchgehenden Blatt liegt Seite 3
aber bei x = 2160, und `captureBeyondViewport` fing das nicht zuverlässig ab.
Die Bühne steht jetzt immer auf 7000 px.