diff --git a/assets/mockups/macbook-board.png b/assets/mockups/macbook-board.png
new file mode 100644
index 0000000..41e754b
Binary files /dev/null and b/assets/mockups/macbook-board.png differ
diff --git a/assets/mockups/macbook-szene.png b/assets/mockups/macbook-szene.png
deleted file mode 100644
index 2e6b96d..0000000
Binary files a/assets/mockups/macbook-szene.png and /dev/null differ
diff --git a/post1.html b/post1.html
index 148fa7a..aaf847b 100644
--- a/post1.html
+++ b/post1.html
@@ -651,70 +651,13 @@
width: 430px; height: auto;
}
- /* ─── Szenen-Mockup ──────────────────────────────────────────────────────
- Macbook Air + iPad Pro in Perspektive (Pixeden-PSD, Hintergrund entfernt,
- beide Displays ausgeknockt). Anders als beim frontalen Laptop reicht kein
- Rechteck: die Displayflächen sind Vierecke. Die Screens werden deshalb
- per matrix3d hineinprojiziert. Die Matrizen wurden aus den Eckpunkten der
- Smart-Objekte im PSD gerechnet und bilden Design-Pixel auf Bildpixel des
- 5742 px breiten Originals ab; --sk skaliert von dort auf die Breite in
- der Slide und wird beim Anwenden der Größe gesetzt. */
- .szene { position: relative; width: 980px; }
- .szene-dev { width: 100%; display: block; position: relative; z-index: 2; }
- .szene-screen {
- position: absolute; top: 0; left: 0; z-index: 1;
- overflow: hidden; background: #fff;
- transform-origin: 0 0;
- }
- .szene-mb {
- width: 3456px; height: 2234px;
- transform: scale(var(--sk, .1707))
- matrix3d(0.853327,-0.145151,0,-0.000016242,
- -0.025684,1.027061,0,-0.000007324,
- 0,0,1,0, 1614.15,493.94,0,1);
- }
- /* Das iPad-Viereck stammt aus der Glasflaeche, nicht aus dem Smart-Object
- des PSD: das sass zu hoch und liess unten einen dreimal so breiten
- schwarzen Streifen stehen. Die Glasecken sind ueber Ausgleichsgeraden auf
- den vier Kanten bestimmt und geschnitten, nicht ueber Extrempunkte: die
- lagen auf den Rundungen und ergaben ein zu kleines, schiefes Viereck.
- Glas 1514 x 2240 mit Eckradius 95, davon 38 px Rand nach innen, also
- Display 1438 x 2164 mit Radius 57. Der Radius ist konzentrisch, aussen
- minus Randbreite, damit der schwarze Rand ueberall gleich breit bleibt. */
- .szene-ip {
- width: 1438px; height: 2164px;
- border-radius: 57px; overflow: hidden;
- transform: scale(var(--sk, .1707))
- matrix3d(0.852061,-0.170328,0,-0.000024605,
- 0.005789,0.984772,0,0.000001055,
- 0,0,1,0, 4244.78,536.57,0,1);
- }
- /* Die Aufnahme fuellt das Display randlos, wie auf einem echten Bildschirm.
- Vorher stand sie als kleineres Rechteck an per Hand gemessenen
- Prozentwerten darin (Breite 78,877 %, Versatz 2,715 % / 14,645 %,
- abgeleitet aus einem angenommenen "groessten vollstaendig sichtbaren
- Rechteck" von 2726 x 1682 bei 74/154). Zwei Fehler steckten darin:
- Die Konstanten stammten nicht aus der Glasflaeche des Mockups, deshalb
- blieben 656 px rechts und 470 px unten leer waehrend die Werkzeugleiste
- des Boards oben unter der Deckelblende verschwand. Und Prozentwerte in
- translate() beziehen sich auf die Bildkante, nicht auf das Display —
- Vorschau und Export loesten sie unterschiedlich auf, die Luecke war im
- Export groesser als im Canvas.
- object-fit uebernimmt das jetzt: kein Versatz, der auseinanderlaufen
- koennte, und die Blende beschneidet von selbst. */
- .szene-screen > img {
- position: absolute; top: 0; left: 0;
- width: 100%; height: 100%;
- object-fit: cover; object-position: center;
- transform-origin: top left;
- }
- /* Der Hintergrundton bleibt als Rueckfall stehen, falls eine Aufnahme
- einmal nicht ankommt — dann faellt es als Flaeche auf, nicht als Loch. */
- .szene-mb { background: #F5F4F4; }
- .szene-ip { background: #FAFAFA; }
- /* Das Board wird beim Fuellen seitlich beschnitten. Was wegfaellt, soll
- rechts wegfallen: dort steht ohnehin das iPad davor. */
- .szene-mb > img { object-position: left center; }
+ /* ─── Laptop mit Board ───────────────────────────────────────────────────
+ Fertiges Mockup: der Screen ist Teil des Bildes. Kein ausgeknocktes
+ Display, keine Projektion per matrix3d, kein zweiter Screenshot dahinter.
+ Damit fallen auch die gemessenen Vierecke und Eckradien weg, die das
+ vorherige Szenen-Mockup gebraucht hat. */
+ .szene { position: relative; width: 720px; }
+ .szene-dev { width: 100%; height: auto; display: block; }
.laptop-missing {
width: 940px; padding: 80px 40px; text-align: center;
@@ -1027,15 +970,15 @@
const SLIDES = [
{
key: "titel", type: "title",
- layouts: [{ id: "klassisch", label: "Klassisch" }, { id: "wabe", label: "Wabe" }, { id: "laptop", label: "Laptop" }, { id: "laptop-logo", label: "Laptop · Logo" }, { id: "laptop-blur", label: "Laptop · Blur" }, { id: "laptop-footer", label: "Laptop · Logo unten" }, { id: "szene", label: "Szene" }],
+ layouts: [{ id: "klassisch", label: "Klassisch" }, { id: "wabe", label: "Wabe" }, { id: "laptop", label: "Laptop" }, { id: "laptop-logo", label: "Laptop · Logo" }, { id: "laptop-blur", label: "Laptop · Blur" }, { id: "laptop-footer", label: "Laptop · Logo unten" }, { id: "szene", label: "Laptop · Board" }],
head: 'Vom Handwerker
f\u00fcr Handwerker',
sub: "Die Software, die deine Branchenprogramme nicht ersetzt, sondern verbindet.",
},
{
key: "projektmanagement", type: "feature",
layouts: [{ id: "standard", label: "Standard" }],
- eyebrow: "Projektmanagement",
- head: 'Du siehst auf einen Blick,
wo jeder Auftrag steht.',
+ eyebrow: "Vertrieb",
+ head: 'Du siehst auf einen Blick,
wo alle Auftr\u00e4ge stehen.',
body: "Projekte, Kunden, Angebote, F\u00f6rderantr\u00e4ge. Kein Suchen, kein Nachfragen, kein Zettelchaos.",
img: "./assets/screens/pipelines.png",
// Nur die linke Bildhälfte: Zoom 2 bei Versatz 0 zeigt exakt den Anteil
@@ -1052,7 +995,7 @@
{
key: "workflow-engine", type: "feature",
layouts: [{ id: "standard", label: "Standard" }],
- eyebrow: "Workflow-Engine",
+ eyebrow: "Automation & KI",
head: 'Wenn-dann
statt Handarbeit.',
body: "Auslöser wählen, Aktionen dranhängen, fertig. Alles automatisch und ohne eine Zeile Code.",
img: "./assets/screens/workflow.png",
@@ -1073,15 +1016,18 @@
{
key: "chat", type: "feature",
layouts: [{ id: "standard", label: "Standard" }],
- eyebrow: "Team-Chat",
- // "automatisch seinen Kanal." misst mit Marker 933 px bei 896
- // verfuegbaren und bricht deshalb in eine dritte Zeile. "von selbst"
- // sagt dasselbe und bleibt mit 846 px in der Zeile.
- head: 'Jedes Projekt bekommt
von selbst seinen Kanal.',
+ eyebrow: "Chat",
+ // Zweizeilig, aber knapp: Zeile 2 misst mit Marker 880 px bei 896
+ // verfuegbaren. Ein laengeres Wort bricht sofort um.
+ head: 'Projekte bekommen
automatisch ihren Kanal.',
body: "Foto von der Baustelle rein, alle sehen's sofort. Aus jeder Nachricht wird mit einem Klick eine Aufgabe.",
img: "./assets/screens/chat.png",
mockW: 1030, mockAR: 1.703,
imgScale: 1, imgX: "0%", imgY: "0%",
+ // Das hinterste Blatt zeigt sonst den Form Builder bei 3,8-fachem Zoom:
+ // unscharf, und die Kopieren- und Papierkorb-Symbole gehören zu einem
+ // anderen Feature. Stattdessen der Chat im Hochformat, ungezoomt.
+ back: { img: "./assets/screens/chat-tablet.png", imgScale: 1, imgX: "0%", imgY: "0%" },
// Das Anhang-Menü zeigt, was aus einer Nachricht alles werden kann.
media2: {
img: "./assets/screens/chat-menue.png",
@@ -1091,7 +1037,7 @@
{
key: "form-builder", type: "feature",
layouts: [{ id: "standard", label: "Standard" }],
- eyebrow: "Form Builder",
+ eyebrow: "Formulare",
head: 'Formulare selbst bauen.
Per Drag-and-drop.',
body: "Von der Kontaktanfrage bis zum Aufmaß mit Unterschrift vor Ort. Teil sie per Link oder QR-Code, jede Einsendung wird automatisch zu Lead, Kontakt oder Auftrag.",
img: "./assets/screens/form-builder.png",
@@ -1115,7 +1061,7 @@
"logo-full": { label: "Logo", size: 560, prop: "width" },
"screen-logo": { label: "Logo im Screen", size: 430, prop: "width" },
"laptop": { label: "Laptop", size: 960, prop: "width" },
- "szene": { label: "Szene", size: 980, prop: "width" },
+ "szene": { label: "Laptop · Board", size: 720, prop: "width" },
"mock": { label: "Bild", size: null, prop: "width" },
"mock-2": { label: "Zweites Bild", size: null, prop: "width" },
"note": { label: "Notizzettel", size: null, prop: "width" },
@@ -1158,7 +1104,7 @@
const STORE = "hivegrid.projekt." + PROJECT;
const STATE_URL = "./state/" + PROJECT + ".json";
- const STATE_V = 2;
+ const STATE_V = 3;
function currentState() {
return {
@@ -1175,16 +1121,25 @@
der seinen Stand im Speicher und schreibt jede Änderung an der Datei beim
nächsten Klick wieder zu. Im Ladepfad kann er das nicht. */
function migrateState(d) {
- if (!d || (d.v || 1) >= 2) return false;
- const feat = SLIDES.map((s, i) => (s.type === "feature" ? i : -1)).filter(i => i >= 0);
- const ref = feat.length && Array.isArray(d.edits) ? (d.edits[feat[0]] || {}).badge : null;
- if (ref) {
- for (const i of feat.slice(1)) {
- const e = d.edits[i] || (d.edits[i] = {});
- e.badge = Object.assign({}, e.badge, { dx: ref.dx || 0, dy: ref.dy || 0 });
+ if (!d || (d.v || 1) >= STATE_V) return false;
+ const alt = d.v || 1;
+ if (alt < 2) {
+ const feat = SLIDES.map((s, i) => (s.type === "feature" ? i : -1)).filter(i => i >= 0);
+ const ref = feat.length && Array.isArray(d.edits) ? (d.edits[feat[0]] || {}).badge : null;
+ if (ref) {
+ for (const i of feat.slice(1)) {
+ const e = d.edits[i] || (d.edits[i] = {});
+ e.badge = Object.assign({}, e.badge, { dx: ref.dx || 0, dy: ref.dy || 0 });
+ }
}
}
- d.v = 2;
+ // Stand 3: Das Titel-Mockup ist ein anderes Bild mit anderem Format
+ // geworden. Breite und Versatz von vorher passen dazu nicht mehr und
+ // wuerden das Geraet ueber die Slide hinaus schieben.
+ if (alt < 3 && Array.isArray(d.edits)) {
+ for (const e of d.edits) { if (e) delete e.szene; }
+ }
+ d.v = STATE_V;
return true;
}
@@ -1426,16 +1381,10 @@
}
const logo = variant === "dunkel" ? assets["./assets/brand/logo-white.svg"] : assets["./assets/brand/logo.svg"];
if (layoutState[i] === "szene") {
- const dev = assets["./assets/mockups/macbook-szene.png"]
- ? '
Vom Handwerker
für Handwerker