Compare commits
3
Commits
3f72d892c5
...
0c08b18dd9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c08b18dd9 | ||
|
|
ce56735077 | ||
|
|
71a7ac79a9 |
No files matched your search
@@ -0,0 +1,156 @@
|
||||
# Post 2 · Die Geschichte
|
||||
|
||||
**Erscheint Mi 12.08.2026, 12:00 Uhr.** Carousel, 6 Slides, 1080 × 1350 px.
|
||||
Zweiter Beitrag des Kontos `hivegrid.de` (nach „Vom Handwerker für Handwerker").
|
||||
|
||||
Diese Datei ist die Übergabe: alles, was zum Beitrag bekannt ist, damit man ohne
|
||||
den Gesprächsverlauf weiterarbeiten kann. Der Redaktionsplan drumherum steht in
|
||||
[`redaktionsplan/`](./redaktionsplan/).
|
||||
|
||||
---
|
||||
|
||||
## 1. Worum es geht
|
||||
|
||||
Die Herkunft, nicht die Funktionen. Warum es HiveGrid gibt: ein SHK-Betrieb in
|
||||
vierter Generation, der sein Branchenprogramm nicht wechseln konnte und deshalb
|
||||
drumherum gebaut hat.
|
||||
|
||||
**Vorlage ist der Text von der Website** (`HiveGrid-Website`,
|
||||
`app/playground/PlaygroundClient.tsx`, Abschnitt „Warum es HiveGrid gibt").
|
||||
Der vollständige Text gehört **unter** den Beitrag, nicht auf die Slides.
|
||||
|
||||
> Auf den Slides steht die Zuspitzung, in der Bildunterschrift der ganze Text.
|
||||
> Ein früherer Stand hatte die Website-Absätze wörtlich auf den Slides. Das war
|
||||
> falsch: Auf einer Slide muss eine Zeile im Vorbeiscrollen sitzen.
|
||||
|
||||
---
|
||||
|
||||
## 2. Die sechs Slides
|
||||
|
||||
| # | Schlüssel | Überschrift | Fließtext | Visualisierung |
|
||||
|---|---|---|---|---|
|
||||
| 1 | `titel` | Die Geschichte fängt **auf der Baustelle an.** | Noah Geerkens, SHK-Betrieb in vierter Generation. | `karte` |
|
||||
| 2 | `prozesse` | Nicht sinnvoll. **Nur so gewachsen.** | Die Software gibt den Takt vor. Nicht der Betrieb. | `schiene` |
|
||||
| 3 | `wechseln` | Wechseln? **Kannst du vergessen.** | Jahre an Daten und Wissen hängen drin. Am Ende dasselbe, nur woanders. | `ersetzen` |
|
||||
| 4 | `mehr` | Wir wollten nicht weg. **Wir wollten mehr.** | KI, CRM, Automatisierung. Und Tools, die miteinander reden. | `lose` |
|
||||
| 5 | `verbinden` | Dein ERP bleibt. **Der Rest kommt dazu.** | Nichts wird ersetzt. Alles wird verbunden. | `verbinden` |
|
||||
| 6 | `warteliste` | Gebaut im Betrieb. **Für den Betrieb.** | Setz dich auf die Warteliste. | `warteliste` |
|
||||
|
||||
Fett = das mit dem Marker hervorgehobene Akzentwort (`<span class="a">`).
|
||||
|
||||
**Zeilenlängen sind geprüft.** Bei 74 px und `-0.03em` passen rund 26 Zeichen in
|
||||
eine Zeile, mit Marker etwas weniger. Keine Zeile hier ist länger als 22, es
|
||||
bricht also nichts um und alle Überschriften bleiben zweizeilig. Gemessen wurde
|
||||
mit der echten Manrope (variables Latin-Subset, Gewicht 800) über die
|
||||
Vorschubbreiten, nicht geschätzt.
|
||||
|
||||
---
|
||||
|
||||
## 3. Die Visualisierungen
|
||||
|
||||
**Kein Bildmaterial außer Noahs Karte.** Alles andere ist HTML und CSS. Damit
|
||||
bleibt es beim 3-fachen Export so scharf wie die Schrift, und jede
|
||||
Visualisierung lässt sich im Canvas verschieben und in der Breite ändern wie
|
||||
jedes andere Element. Sie heißt dort **„Visualisierung"**.
|
||||
|
||||
Gebaut aus derselben Formensprache wie die Slides: chamferte Kästen, Sechsecke,
|
||||
der eine gelbe Akzent. Durchgezogene Balken heißen verbunden, gestrichelte offen.
|
||||
|
||||
| Name | Was zu sehen ist | Gedanke dahinter |
|
||||
|---|---|---|
|
||||
| `karte` | Noahs Teamkarte von der Über-uns-Seite | Ein Gesicht, kein Symbol |
|
||||
| `schiene` | Drei Schritte an einer Schiene mit der Beschriftung „seit Jahren so" | Die Schiene gibt die Reihenfolge vor, nicht der Betrieb |
|
||||
| `ersetzen` | Schwerer Bestand, durchgestrichener Pfeil, leeres Ziel | Das Kreuz liegt auf dem **Pfeil**, nicht auf dem Ziel: der Wechsel scheitert, nicht das neue System |
|
||||
| `lose` | Vier Kacheln, deren gestrichelte Stummel ins Leere laufen | KI, CRM, Automation, ERP wissen nichts voneinander |
|
||||
| `verbinden` | ERP als Sechseck in der Mitte, das Neue drumherum | Der Kern bleibt, außen kommt dazu |
|
||||
| `warteliste` | Eingabefeld, Knopf, Adresse | Der Abschluss ist ein Feld, kein Bild |
|
||||
|
||||
### Noahs Karte
|
||||
|
||||
Nachbau der Karte von der Über-uns-Seite **im aktiven Zustand**. Werte direkt aus
|
||||
`HiveGrid-Website/app/ueber-uns/TeamCards.tsx`:
|
||||
|
||||
```
|
||||
Hintergrund grayscale(.04) saturate(.74) brightness(.73)
|
||||
Person saturate(1) contrast(1.01)
|
||||
Kartengrund #0f1a2e Radius außen 38 px, innen 27 px
|
||||
Namensschild gelb, links unten, "Noah" + "CEO"
|
||||
```
|
||||
|
||||
Bilder liegen unter `assets/team/noah-bg.webp` und `noah-person.webp`.
|
||||
|
||||
> **Ohne die weichgezeichnete Ellipse des Originals.** Die hängt an
|
||||
> `backdrop-filter`, und was `html-to-image` daraus macht, ist nicht verlässlich.
|
||||
|
||||
---
|
||||
|
||||
## 4. Maße, gemessen
|
||||
|
||||
Der Inhaltsblock (Überschrift plus Fließtext) endet je nach Textlänge bei
|
||||
**y 415 bis 460**. Unten bleiben 92 px Rand. Für die Visualisierung stehen also
|
||||
rund **800 px Höhe** zur Verfügung, und die soll sie auch füllen.
|
||||
|
||||
| Slide | Visualisierung: oben | Höhe | Luft zum Text | Abstand nach unten |
|
||||
|---|---|---|---|---|
|
||||
| 1 | 499 | 775 | 84 | 76 |
|
||||
| 2 | 548 | 682 | 133 | 120 |
|
||||
| 3 | 566 | 664 | 106 | 120 |
|
||||
| 4 | 502 | 700 | 70 | 120 |
|
||||
| 5 | 470 | 732 | 83 | 120 |
|
||||
| 6 | 603 | 466 | 188 | 281 |
|
||||
|
||||
Slide 6 ist bewusst kleiner und steht dafür mittig in der freien Fläche. Ein
|
||||
Formularfeld auf 700 px aufzublasen sieht aufgeblasen aus.
|
||||
|
||||
**Wie nachmessen:** Eine Kopie von `post2.html` anlegen, vor `</body>` ein
|
||||
Skript hängen, das `getBoundingClientRect` der Elemente in `document.title`
|
||||
schreibt, und mit
|
||||
`Google\ Chrome --headless --dump-dom` auslesen. Auf `.holder .slide` warten,
|
||||
die Seite baut asynchron auf.
|
||||
|
||||
---
|
||||
|
||||
## 5. Stand der Dinge
|
||||
|
||||
**Fertig:** Alle sechs Slides sind gebaut, die Texte auf Slide-Länge, die
|
||||
Visualisierungen füllen das Format, Noahs Karte sitzt.
|
||||
|
||||
**Offen:**
|
||||
|
||||
1. **Die Bildunterschrift.** Noahs vollständiger Text von der Website, plus
|
||||
Hashtags. Vorgaben aus dem Redaktionsplan: Haken in den ersten 125 Zeichen,
|
||||
300 bis 800 Zeichen gesamt, 5 bis 10 Hashtags ganz unten, Suchwörter
|
||||
zusätzlich im Fließtext. Die Bildunterschrift von Post 1 steht als Muster im
|
||||
Gesprächsverlauf und folgt genau diesem Aufbau.
|
||||
2. **Export und Kontrolle.** Über `Datei → Alle Slides als ZIP`, 3-fach.
|
||||
Danach jede Slide ansehen: der Export hat schon zweimal Bilder verschluckt,
|
||||
die Prüfung meldet das inzwischen, aber ein Blick schadet nicht.
|
||||
3. **Mitgestalter.** Falls Noahs Betriebsprofil mit drauf soll, **beim Posten**
|
||||
einladen. Nachträglich geht es zwar, aber der Beitrag erscheint dann erst
|
||||
nach der Annahme bei dessen Followern und die Ausspielung ist vorbei.
|
||||
|
||||
---
|
||||
|
||||
## 6. Fallen, die schon zugeschnappt sind
|
||||
|
||||
- **Der offene Tab überschreibt die Datei.** `state/post2.json` gewinnt nur
|
||||
**beim Laden**. Wer die Datei von außen ändert und dann im offenen Tab klickt,
|
||||
bekommt den alten Stand zurückgeschrieben. Also erst neu laden, dann klicken.
|
||||
Änderungen, die sicher ankommen müssen, gehören in den Ladepfad (`migrateState`).
|
||||
- **Probier-Verschiebungen bleiben im Stand.** Slide 1 war unten abgeschnitten,
|
||||
weil die Karte auf 700 px vergrößert und 250 px nach unten geschoben war. Wenn
|
||||
eine Vorgabe im Code nicht wirkt, zuerst `edits` im Stand prüfen.
|
||||
- **Der Server verschluckt Fehler.** Ein Filter in `log_message` ist über
|
||||
`HTTPStatus` gestolpert und hat den Thread mitgerissen; die Seite blieb dann
|
||||
ohne Meldung bei „Lade Screens ..." stehen. Behoben, aber wenn die Seite
|
||||
wieder hängt: zuerst `serve.py` neu starten und in die Ausgabe schauen.
|
||||
- **Texte von der Website gehören nicht auf Slides.** Siehe oben.
|
||||
|
||||
---
|
||||
|
||||
## 7. Was danach kommt
|
||||
|
||||
Der Redaktionsplan sieht als nächsten Beitrag **Fr 14.08. „Verbinden statt
|
||||
ersetzen"** vor, ein Einzelbild mit der Kernaussage. Der Satz „Verbinden statt
|
||||
ersetzen" ist dafür reserviert und taucht deshalb in keiner Bildunterschrift
|
||||
vorher wörtlich auf.
|
||||
@@ -18,9 +18,13 @@ Downloads landen direkt in `~/Downloads`, ohne Browser-Dialog.
|
||||
|
||||
## Projekte
|
||||
|
||||
| Projekt | Datei | Inhalt |
|
||||
|---|---|---|
|
||||
| Post 1 · Lösung | `post1.html` | Carousel, Anzahl frei |
|
||||
| Projekt | Datei | Inhalt | Übergabe |
|
||||
|---|---|---|---|
|
||||
| Post 1 · Lösung | `post1.html` | Carousel, Anzahl frei | |
|
||||
| Post 2 · Die Geschichte | `post2.html` | Carousel, 6 Slides, erscheint 12.08. | [`POST-2.md`](./POST-2.md) |
|
||||
|
||||
Der Redaktionsplan für alle weiteren Beiträge liegt in
|
||||
[`redaktionsplan/`](./redaktionsplan/), gebaut mit `python3 redaktionsplan/bauen.py`.
|
||||
|
||||
### Slides anlegen und wegnehmen
|
||||
|
||||
|
||||
+137
-111
@@ -362,125 +362,147 @@
|
||||
Bild. Gebaut aus derselben Formensprache wie die Slides: chamferte
|
||||
Kaesten, Sechsecke, der eine gelbe Akzent. Alles HTML, damit es beim
|
||||
3-fachen Export genauso scharf bleibt wie die Schrift und sich im Canvas
|
||||
verschieben laesst wie jedes andere Element. */
|
||||
verschieben laesst wie jedes andere Element.
|
||||
Die Maße sind gemessen, nicht geschaetzt: der Inhaltsblock endet bei
|
||||
y 415 bis 460, unten bleiben 92 px Rand. Rund 800 px Hoehe stehen also
|
||||
zur Verfuegung, und die soll eine Visualisierung auch fuellen. */
|
||||
.vis {
|
||||
position: absolute; z-index: 1;
|
||||
left: var(--vis-left, 92px);
|
||||
bottom: var(--vis-bottom, 96px);
|
||||
width: var(--vis-w, 900px);
|
||||
width: var(--vis-w, 896px);
|
||||
color: var(--head-color);
|
||||
}
|
||||
.vis-kasten {
|
||||
position: relative; padding: 22px 26px;
|
||||
position: relative; padding: 30px 34px;
|
||||
background: var(--frame-bg);
|
||||
display: flex; flex-direction: column; justify-content: center;
|
||||
clip-path: polygon(
|
||||
18px 0, calc(100% - 18px) 0, 100% 18px, 100% calc(100% - 18px),
|
||||
calc(100% - 18px) 100%, 18px 100%, 0 calc(100% - 18px), 0 18px
|
||||
);
|
||||
}
|
||||
.vis-titel { font-size: 38px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
|
||||
.vis-zeile { margin-top: 8px; font-size: 24px; font-weight: 500; line-height: 1.35; color: var(--body-color); }
|
||||
.vis-marke { background: var(--accent-yellow); color: #3E2C0A; }
|
||||
.vis-marke .vis-zeile { color: #6B4E12; }
|
||||
|
||||
/* Slide 2: die drei Schritte haengen an einer Schiene. Sie stehen nicht
|
||||
dort, weil es sinnvoll waere, sondern weil die Schiene es vorgibt. */
|
||||
.vis-schiene { display: flex; align-items: stretch; gap: 40px; }
|
||||
.vis-schiene .rail {
|
||||
flex: none; width: 74px; position: relative;
|
||||
background: var(--shape-fill);
|
||||
clip-path: polygon(
|
||||
14px 0, 60px 0, 74px 14px, 74px calc(100% - 14px),
|
||||
60px 100%, 14px 100%, 0 calc(100% - 14px), 0 14px
|
||||
);
|
||||
}
|
||||
.vis-schiene .rail span {
|
||||
position: absolute; left: 50%; top: 50%; white-space: nowrap;
|
||||
transform: translate(-50%, -50%) rotate(-90deg);
|
||||
color: #fff; font-size: 21px; font-weight: 700; letter-spacing: .13em;
|
||||
text-transform: uppercase; opacity: .82;
|
||||
}
|
||||
.vis-schiene .stufen { flex: 1; display: flex; flex-direction: column; }
|
||||
.vis-schiene .vis-kasten { min-height: 190px; }
|
||||
.vis-schiene .verbund {
|
||||
width: 8px; height: 56px; margin-left: 58px; background: var(--shape-line);
|
||||
}
|
||||
|
||||
/* Slide 3: der Bestand ist schwer, das Ziel leer. Das Kreuz liegt auf dem
|
||||
Pfeil, nicht auf dem Ziel: der Wechsel scheitert, nicht das System. */
|
||||
.vis-ersetzen { display: flex; align-items: stretch; gap: 30px; }
|
||||
.vis-ersetzen .schwer { flex: 1.25; display: grid; gap: 14px; }
|
||||
.vis-ersetzen .schwer .vis-kasten { min-height: 212px; }
|
||||
.vis-ersetzen .leer {
|
||||
flex: 1; padding: 30px; border: 8px dashed var(--shape-line);
|
||||
display: flex; align-items: center; justify-content: center; text-align: center;
|
||||
color: var(--body-color); font-size: 26px; font-weight: 600; line-height: 1.35;
|
||||
}
|
||||
.vis-ersetzen .pfeil {
|
||||
flex: none; align-self: center; position: relative;
|
||||
width: 104px; height: 8px; background: var(--shape-line);
|
||||
}
|
||||
.vis-ersetzen .pfeil::after {
|
||||
content: ""; position: absolute; right: -2px; top: -14px;
|
||||
border: 18px solid transparent; border-left-color: var(--shape-line);
|
||||
}
|
||||
.vis-kreuz {
|
||||
position: absolute; left: 50%; top: 50%; width: 92px; height: 92px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.vis-kreuz i {
|
||||
position: absolute; left: 0; top: 42px; width: 100%; height: 10px;
|
||||
background: var(--accent-yellow);
|
||||
}
|
||||
.vis-kreuz i:first-child { transform: rotate(45deg); }
|
||||
.vis-kreuz i:last-child { transform: rotate(-45deg); }
|
||||
|
||||
/* Slide 4: vier Kacheln, die nichts voneinander wissen. Die gestrichelten
|
||||
Stummel laufen ins Leere. */
|
||||
.vis-lose { display: grid; grid-template-columns: repeat(2, 1fr); gap: 32px 96px; }
|
||||
.vis-lose .feld { position: relative; }
|
||||
.vis-lose .feld .vis-kasten { min-height: 320px; }
|
||||
.vis-lose .stummel {
|
||||
position: absolute; top: 50%; width: 72px; height: 0;
|
||||
border-top: 8px dashed var(--shape-line);
|
||||
}
|
||||
.vis-lose .feld:nth-child(odd) .stummel { right: -84px; }
|
||||
.vis-lose .feld:nth-child(even) .stummel { left: -84px; }
|
||||
|
||||
/* Slide 5: das ERP bleibt in der Mitte, das Neue haengt drumherum. */
|
||||
.vis-verbinden { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
|
||||
.vis-verbinden .saeule { display: grid; gap: 24px; }
|
||||
.vis-verbinden .saeule .vis-kasten { min-height: 340px; }
|
||||
.vis-verbinden .mitte { position: relative; width: 452px; padding: 0 30px; }
|
||||
.vis-nabe {
|
||||
position: relative; width: 392px; height: 340px; margin: 0 auto;
|
||||
background: var(--shape-fill);
|
||||
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
|
||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||
color: #fff; text-align: center;
|
||||
}
|
||||
.vis-nabe b { font-size: 34px; font-weight: 800; letter-spacing: -0.02em; }
|
||||
.vis-nabe small { margin-top: 6px; font-size: 21px; font-weight: 600; opacity: .74; }
|
||||
.vis-verbinden .quer { position: absolute; top: 50%; width: 30px; height: 8px; background: var(--shape-line); }
|
||||
.vis-verbinden .quer.li { left: 0; }
|
||||
.vis-verbinden .quer.re { right: 0; }
|
||||
|
||||
/* Slide 6: der Abschluss ist ein Feld, kein Bild. */
|
||||
.vis-warteliste {
|
||||
border: 6px solid var(--shape-line); padding: 54px 48px; text-align: center;
|
||||
clip-path: polygon(
|
||||
22px 0, calc(100% - 22px) 0, 100% 22px, 100% calc(100% - 22px),
|
||||
calc(100% - 22px) 100%, 22px 100%, 0 calc(100% - 22px), 0 22px
|
||||
);
|
||||
}
|
||||
.vis-warteliste .oben {
|
||||
font-size: 21px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
|
||||
color: var(--body-color);
|
||||
}
|
||||
.vis-warteliste .feldzeile { display: flex; align-items: stretch; gap: 18px; margin-top: 26px; }
|
||||
.vis-warteliste .eingabe {
|
||||
flex: 1; padding: 30px 32px; text-align: left;
|
||||
font-size: 30px; font-weight: 500; color: var(--body-color);
|
||||
background: var(--frame-bg);
|
||||
clip-path: polygon(
|
||||
16px 0, calc(100% - 16px) 0, 100% 16px, 100% calc(100% - 16px),
|
||||
calc(100% - 16px) 100%, 16px 100%, 0 calc(100% - 16px), 0 16px
|
||||
);
|
||||
}
|
||||
.vis-titel { font-size: 27px; font-weight: 700; letter-spacing: -0.01em; }
|
||||
.vis-zeile { margin-top: 6px; font-size: 21px; font-weight: 500; color: var(--body-color); }
|
||||
.vis-marke { background: var(--accent-yellow); color: #3E2C0A; }
|
||||
.vis-marke .vis-zeile { color: #6B4E12; }
|
||||
|
||||
/* Verbindungen: 6 px starke Balken in der Rahmenfarbe. Durchgezogen heisst
|
||||
verbunden, gestrichelt heisst offen. */
|
||||
.vis-linie { position: absolute; height: 6px; background: var(--shape-line); }
|
||||
.vis-linie.senk { width: 6px; height: auto; }
|
||||
.vis-offen { border-top: 6px dashed var(--shape-line); background: none; height: 0; }
|
||||
|
||||
/* Slide 2: drei Schritte fest auf einer Schiene. Sie sitzen nicht dort,
|
||||
weil es sinnvoll waere, sondern weil die Schiene es vorgibt. */
|
||||
.vis-schiene { display: flex; align-items: stretch; gap: 0; }
|
||||
.vis-schiene .vis-kasten { flex: 1; }
|
||||
.vis-schiene .verbund { flex: none; width: 54px; align-self: center; height: 6px; background: var(--shape-line); }
|
||||
.vis-riegel {
|
||||
margin-top: 26px; height: 14px; background: var(--shape-fill); opacity: .28;
|
||||
clip-path: polygon(7px 0, calc(100% - 7px) 0, 100% 7px, 100% 100%, 0 100%, 0 7px);
|
||||
}
|
||||
|
||||
/* Slide 3: der Bestand ist schwer, der Wechsel daneben leer. Das Kreuz
|
||||
liegt auf dem Pfeil, nicht auf dem Ziel. */
|
||||
.vis-ersetzen { display: flex; align-items: center; gap: 34px; }
|
||||
.vis-ersetzen .schwer { flex: 1.35; }
|
||||
.vis-ersetzen .leer {
|
||||
flex: 1; padding: 22px 26px; min-height: 168px;
|
||||
border: 6px dashed var(--shape-line);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
color: var(--body-color); font-size: 21px; font-weight: 600;
|
||||
}
|
||||
.vis-ersetzen .pfeil { flex: none; position: relative; width: 96px; height: 6px; background: var(--shape-line); }
|
||||
.vis-ersetzen .pfeil::after {
|
||||
content: ""; position: absolute; right: -2px; top: -11px;
|
||||
border: 14px solid transparent; border-left-color: var(--shape-line);
|
||||
}
|
||||
.vis-kreuz {
|
||||
position: absolute; left: 50%; top: 50%; width: 74px; height: 74px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.vis-kreuz i {
|
||||
position: absolute; left: 0; top: 34px; width: 100%; height: 8px;
|
||||
background: var(--accent-yellow);
|
||||
}
|
||||
.vis-kreuz i:first-child { transform: rotate(45deg); }
|
||||
.vis-kreuz i:last-child { transform: rotate(-45deg); }
|
||||
.vis-stapel { display: grid; gap: 10px; }
|
||||
|
||||
/* Slide 4: vier Kacheln, die nichts voneinander wissen. Die gestrichelten
|
||||
Stummel laufen ins Leere. */
|
||||
.vis-lose { display: grid; grid-template-columns: repeat(2, 1fr); gap: 30px 74px; }
|
||||
.vis-lose .feld { position: relative; }
|
||||
.vis-lose .stummel {
|
||||
position: absolute; top: 50%; width: 54px; height: 0;
|
||||
border-top: 6px dashed var(--shape-line);
|
||||
}
|
||||
.vis-lose .feld:nth-child(odd) .stummel { right: -60px; }
|
||||
.vis-lose .feld:nth-child(even) .stummel { left: -60px; }
|
||||
|
||||
/* Slide 5: das ERP bleibt in der Mitte, HiveGrid liegt als Sechseck
|
||||
drumherum und haelt die drei Neuen daran. */
|
||||
.vis-verbinden { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 0; }
|
||||
.vis-verbinden .saeule { display: grid; gap: 20px; }
|
||||
.vis-verbinden .mitte { position: relative; width: 300px; padding: 0 26px; }
|
||||
.vis-nabe {
|
||||
position: relative; width: 248px; height: 215px; margin: 0 auto;
|
||||
background: var(--shape-fill);
|
||||
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
|
||||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||||
color: var(--text-white);
|
||||
}
|
||||
.slide[data-variant="hell"] .vis-nabe { color: #fff; }
|
||||
.vis-nabe b { font-size: 25px; font-weight: 800; letter-spacing: -0.01em; }
|
||||
.vis-nabe small { margin-top: 4px; font-size: 17px; font-weight: 600; opacity: .72; }
|
||||
.vis-verbinden .quer { position: absolute; top: 50%; width: 26px; height: 6px; background: var(--shape-line); }
|
||||
.vis-verbinden .quer.li { left: 0; }
|
||||
.vis-verbinden .quer.re { right: 0; }
|
||||
|
||||
/* Slide 6: der Abschluss ist ein Feld, kein Bild. */
|
||||
.vis-warteliste { text-align: center; }
|
||||
.vis-warteliste .feldzeile {
|
||||
display: flex; align-items: stretch; gap: 14px; margin-top: 22px;
|
||||
}
|
||||
.vis-warteliste .eingabe {
|
||||
flex: 1; padding: 20px 24px; text-align: left;
|
||||
font-size: 22px; font-weight: 500; color: var(--body-color);
|
||||
border: 3px solid var(--shape-line);
|
||||
clip-path: polygon(
|
||||
14px 0, calc(100% - 14px) 0, 100% 14px, 100% calc(100% - 14px),
|
||||
calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px), 0 14px
|
||||
);
|
||||
}
|
||||
.vis-warteliste .knopf {
|
||||
flex: none; padding: 20px 32px; font-size: 22px; font-weight: 800;
|
||||
flex: none; display: flex; align-items: center; padding: 30px 40px;
|
||||
font-size: 30px; font-weight: 800;
|
||||
background: var(--accent-yellow); color: #3E2C0A;
|
||||
clip-path: polygon(
|
||||
14px 0, calc(100% - 14px) 0, 100% 14px, 100% calc(100% - 14px),
|
||||
calc(100% - 14px) 100%, 14px 100%, 0 calc(100% - 14px), 0 14px
|
||||
16px 0, calc(100% - 16px) 0, 100% 16px, 100% calc(100% - 16px),
|
||||
calc(100% - 16px) 100%, 16px 100%, 0 calc(100% - 16px), 0 16px
|
||||
);
|
||||
}
|
||||
.vis-warteliste .adresse {
|
||||
margin-top: 18px; font-size: 21px; font-weight: 700; letter-spacing: .02em;
|
||||
color: var(--body-color);
|
||||
margin-top: 30px; font-size: 30px; font-weight: 800; letter-spacing: -0.01em;
|
||||
color: var(--head-color);
|
||||
}
|
||||
|
||||
/* ─── Teamkarte ──────────────────────────────────────────────────────────
|
||||
@@ -1189,7 +1211,7 @@
|
||||
eyebrow: "Titel",
|
||||
head: 'Die Geschichte fängt<br><span class="a">auf der Baustelle an.</span>',
|
||||
body: "Noah Geerkens, SHK-Betrieb in vierter Generation.",
|
||||
vis: "karte", visW: 520, visLeft: 280, visBottom: 130,
|
||||
vis: "karte", visW: 620, visLeft: 230, visBottom: 76,
|
||||
},
|
||||
{
|
||||
key: "prozesse", type: "feature",
|
||||
@@ -1197,7 +1219,7 @@
|
||||
eyebrow: "Prozesse",
|
||||
head: 'Nicht sinnvoll.<br><span class="a">Nur so gewachsen.</span>',
|
||||
body: "Die Software gibt den Takt vor. Nicht der Betrieb.",
|
||||
vis: "schiene", visW: 900, visLeft: 92, visBottom: 210,
|
||||
vis: "schiene", visW: 896, visLeft: 92, visBottom: 120,
|
||||
},
|
||||
{
|
||||
key: "wechseln", type: "feature",
|
||||
@@ -1205,7 +1227,7 @@
|
||||
eyebrow: "Wechseln",
|
||||
head: 'Wechseln?<br><span class="a">Kannst du vergessen.</span>',
|
||||
body: "Jahre an Daten und Wissen hängen drin. Am Ende dasselbe, nur woanders.",
|
||||
vis: "ersetzen", visW: 900, visLeft: 92, visBottom: 190,
|
||||
vis: "ersetzen", visW: 896, visLeft: 92, visBottom: 120,
|
||||
},
|
||||
{
|
||||
key: "mehr", type: "feature",
|
||||
@@ -1213,7 +1235,7 @@
|
||||
eyebrow: "Mehr",
|
||||
head: 'Wir wollten nicht weg.<br><span class="a">Wir wollten mehr.</span>',
|
||||
body: "KI, CRM, Automatisierung. Und Tools, die miteinander reden.",
|
||||
vis: "lose", visW: 900, visLeft: 92, visBottom: 200,
|
||||
vis: "lose", visW: 896, visLeft: 92, visBottom: 120,
|
||||
},
|
||||
{
|
||||
key: "verbinden", type: "feature",
|
||||
@@ -1221,7 +1243,7 @@
|
||||
eyebrow: "Verbinden",
|
||||
head: 'Dein ERP bleibt.<br><span class="a">Der Rest kommt dazu.</span>',
|
||||
body: "Nichts wird ersetzt. Alles wird verbunden.",
|
||||
vis: "verbinden", visW: 880, visLeft: 100, visBottom: 170,
|
||||
vis: "verbinden", visW: 896, visLeft: 92, visBottom: 120,
|
||||
},
|
||||
{
|
||||
key: "warteliste", type: "feature",
|
||||
@@ -1229,7 +1251,7 @@
|
||||
eyebrow: "Warteliste",
|
||||
head: 'Gebaut im Betrieb.<br><span class="a">Für den Betrieb.</span>',
|
||||
body: "Setz dich auf die Warteliste.",
|
||||
vis: "warteliste", visW: 820, visLeft: 130, visBottom: 220,
|
||||
vis: "warteliste", visW: 820, visLeft: 130, visBottom: 281,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1289,10 +1311,13 @@
|
||||
|
||||
schiene: () =>
|
||||
'<div class="vis-schiene">' +
|
||||
kasten("Anfrage", "so wie immer") + '<div class="verbund"></div>' +
|
||||
kasten("Angebot", "so wie immer") + '<div class="verbund"></div>' +
|
||||
kasten("Rechnung", "so wie immer") +
|
||||
'</div><div class="vis-riegel"></div>',
|
||||
'<div class="rail"><span>seit Jahren so</span></div>' +
|
||||
'<div class="stufen">' +
|
||||
kasten("Anfrage", "abtippen") + '<div class="verbund"></div>' +
|
||||
kasten("Angebot", "noch mal abtippen") + '<div class="verbund"></div>' +
|
||||
kasten("Rechnung", "und noch mal") +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
|
||||
ersetzen: () =>
|
||||
'<div class="vis-ersetzen">' +
|
||||
@@ -1321,11 +1346,12 @@
|
||||
'<div class="vis-nabe"><b>Dein ERP</b><small>bleibt, wo es ist</small></div>' +
|
||||
'<span class="quer re"></span>' +
|
||||
'</div>' +
|
||||
'<div class="saeule">' + kasten("Automation") + kasten("Chat", "", true) + '</div>' +
|
||||
'<div class="saeule">' + kasten("Automation") + kasten("Chat") + '</div>' +
|
||||
'</div>',
|
||||
|
||||
warteliste: () =>
|
||||
'<div class="vis-warteliste">' +
|
||||
'<div class="oben">Frühzugang</div>' +
|
||||
'<div class="feldzeile">' +
|
||||
'<div class="eingabe">deine@firma.de</div>' +
|
||||
'<div class="knopf">Auf die Warteliste</div>' +
|
||||
|
||||
@@ -218,9 +218,16 @@ class Handler(http.server.SimpleHTTPRequestHandler):
|
||||
super().end_headers()
|
||||
|
||||
def log_message(self, fmt, *args):
|
||||
first = args[0] if args else ""
|
||||
# args[0] ist normalerweise die Anfragezeile, bei send_error aber ein
|
||||
# HTTPStatus. Ohne str() flog hier ein TypeError, der den Handler-Thread
|
||||
# abbrach: der Browser wartete dann ewig auf eine Antwort, die nie kam,
|
||||
# und die Seite blieb bei "Lade Screens ..." stehen.
|
||||
first = str(args[0]) if args else ""
|
||||
if "POST /save" in first or "DELETE" in first:
|
||||
super().log_message(fmt, *args)
|
||||
elif not first.startswith(("GET", "POST", "HEAD")):
|
||||
# Fehler und Warnungen gehoeren gesehen, sonst sucht man lange.
|
||||
super().log_message(fmt, *args)
|
||||
|
||||
|
||||
class Server(socketserver.ThreadingTCPServer):
|
||||
|
||||
+5
-21
@@ -2,7 +2,7 @@
|
||||
"bgState": [
|
||||
{
|
||||
"bg": "raster",
|
||||
"int": "dezent"
|
||||
"int": "kraeftig"
|
||||
},
|
||||
{
|
||||
"bg": "raster",
|
||||
@@ -53,30 +53,14 @@
|
||||
}
|
||||
],
|
||||
"edits": [
|
||||
{
|
||||
"vis": {
|
||||
"dx": -100,
|
||||
"dy": 250,
|
||||
"size": 700
|
||||
}
|
||||
},
|
||||
{
|
||||
"vis": {
|
||||
"dx": -7,
|
||||
"dy": -19
|
||||
}
|
||||
},
|
||||
{
|
||||
"vis": {
|
||||
"dx": 19,
|
||||
"dy": -27
|
||||
}
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
],
|
||||
"frameStyle": "chamfer",
|
||||
"frameStyle": "rund",
|
||||
"layoutState": [
|
||||
"standard",
|
||||
"standard",
|
||||
|
||||
Reference in new issue
Block a user