Post 2: die Geschichte, mit gebauten Visualisierungen
Sechs Slides von der Baustelle bis zur Warteliste. Statt Screenshots traegt jede Slide eine Visualisierung des Stichworts aus ihrem Text: drei Schritte fest auf einer Schiene, der schwere Bestand mit dem durchgestrichenen Pfeil, vier lose Kacheln deren Verbindungen ins Leere laufen, das ERP als Sechseck mit den Neuen daran, ein Feld mit Knopf. Alles HTML, kein Bildmaterial ausser Noahs Karte. Damit bleibt es beim 3-fachen Export so scharf wie die Schrift, und jede Visualisierung laesst sich im Canvas verschieben und in der Breite aendern wie jedes andere Element. Das Kreuz auf der Wechsel-Slide liegt auf dem Pfeil, nicht auf dem Ziel: der Wechsel scheitert, nicht das neue System. Die Karte ist der aktive Zustand von der Ueber-uns-Seite, Werte aus TeamCards.tsx. Ohne die weichgezeichnete Ellipse des Originals: die haengt an backdrop-filter, und was der Export daraus macht, ist nicht verlaesslich. Die Texte sind bewusst NICHT die von der Website. Dort stehen ganze Absaetze, auf einer Slide muss eine Zeile im Vorbeiscrollen sitzen; der volle Text kommt unter den Beitrag. Aus den gemessenen Breiten folgt: bei 74 px und -0,03em passen rund 26 Zeichen in eine Zeile. Keine hier ist laenger als 22. Der Stand von post2 ist neu geschrieben, er zeigte noch auf die Slides von Post 1. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
276cced03c
commit
bd06f77a60
5 files changed
+392
-243
No files matched your search
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1074.12 930.23">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #f1b729;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Ebene_2" data-name="Ebene 2">
|
||||
<polygon class="cls-1" points="1074.12 465.12 939.87 232.54 537.06 465.12 805.59 465.12 671.34 697.66 402.78 697.66 268.53 465.12 402.78 232.54 939.87 232.54 832.69 46.91 805.59 0 268.53 0 0 465.12 268.53 930.23 805.59 930.23 1074.12 465.12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 532 B |
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
+348
-119
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>HiveGrid Post 2 (Carousel)</title>
|
||||
<title>PostGrid Post 2</title>
|
||||
<link rel="stylesheet" href="./assets/fonts/manrope.css">
|
||||
<style>
|
||||
/* ─── HiveGrid design tokens (mirrored from app/globals.css) ─────────────
|
||||
@@ -249,7 +249,10 @@
|
||||
Klar abgesetzt von der Sidebar: eigener Grund, eigener Scroll, eigener
|
||||
Zoom. Was hier passiert, lässt die Bedienleiste unberührt. */
|
||||
.stage {
|
||||
flex: 1; position: relative; height: 100vh; overflow: hidden;
|
||||
/* Nicht 100vh: darueber sitzt die Menueleiste. Mit voller
|
||||
Fensterhoehe rutscht die Fussleiste samt Zoom und Merkzettel
|
||||
unter den unteren Rand. */
|
||||
flex: 1; position: relative; height: 100%; overflow: hidden;
|
||||
background-color: #101116;
|
||||
background-image: radial-gradient(circle, #282B35 1.6px, transparent 1.6px);
|
||||
background-size: 24px 24px;
|
||||
@@ -353,6 +356,166 @@
|
||||
opacity: calc(var(--pat-strength) * var(--int-mul, 1));
|
||||
}
|
||||
|
||||
|
||||
/* ─── Visualisierungen ───────────────────────────────────────────────────
|
||||
Post 2 zeigt keine Screenshots, sondern das Stichwort aus dem Text als
|
||||
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. */
|
||||
.vis {
|
||||
position: absolute; z-index: 1;
|
||||
left: var(--vis-left, 92px);
|
||||
bottom: var(--vis-bottom, 96px);
|
||||
width: var(--vis-w, 900px);
|
||||
color: var(--head-color);
|
||||
}
|
||||
.vis-kasten {
|
||||
position: relative; padding: 22px 26px;
|
||||
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;
|
||||
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
|
||||
);
|
||||
}
|
||||
.vis-warteliste .adresse {
|
||||
margin-top: 18px; font-size: 21px; font-weight: 700; letter-spacing: .02em;
|
||||
color: var(--body-color);
|
||||
}
|
||||
|
||||
/* ─── Teamkarte ──────────────────────────────────────────────────────────
|
||||
Nachbau der Karte von der Ueber-uns-Seite im aktiven Zustand: Hintergrund
|
||||
entsaettigt und abgedunkelt, die Person in voller Farbe, das gelbe
|
||||
Namensschild sichtbar. Werte aus TeamCards.tsx uebernommen.
|
||||
Ohne die weichgezeichnete Ellipse aus dem Original: die haengt an
|
||||
backdrop-filter, und was der Export daraus macht, ist nicht verlaesslich. */
|
||||
.karte {
|
||||
position: relative; aspect-ratio: 4/5; overflow: hidden;
|
||||
border-radius: 38px; background: #0f1a2e; isolation: isolate;
|
||||
}
|
||||
.karte-grund {
|
||||
position: absolute; inset: 4.2%; z-index: 1; overflow: hidden;
|
||||
border-radius: 27px; background: #2b2d2a;
|
||||
filter: grayscale(.04) saturate(.74) brightness(.73);
|
||||
}
|
||||
.karte-grund img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
|
||||
.karte-wash {
|
||||
position: absolute; inset: 0;
|
||||
background: linear-gradient(180deg, rgba(15,26,46,.01), rgba(15,26,46,.12));
|
||||
}
|
||||
.karte-person {
|
||||
position: absolute; inset: 0; z-index: 4;
|
||||
width: 100%; height: 100%; object-fit: cover;
|
||||
filter: saturate(1) contrast(1.01);
|
||||
}
|
||||
.karte-name {
|
||||
position: absolute; left: 6%; bottom: 5.7%; z-index: 5;
|
||||
display: flex; align-items: baseline; gap: 13px;
|
||||
padding: 13px 17px; background: var(--accent-yellow); color: #101010;
|
||||
}
|
||||
.karte-name span { font-size: 27px; font-weight: 700; letter-spacing: -.03em; line-height: 1.15; }
|
||||
.karte-name small { font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; }
|
||||
|
||||
/* ─── Bearbeitung im Canvas ───────────────────────────────────────────────
|
||||
Verschieben läuft über --ex/--ey, also über transform statt über den
|
||||
Textfluss: So verschiebt ein Element nie seine Nachbarn und lässt sich
|
||||
@@ -755,7 +918,7 @@
|
||||
<body>
|
||||
|
||||
<div class="menubar" id="menubar">
|
||||
<span class="marke">HiveGrid</span>
|
||||
<span class="marke">PostGrid</span>
|
||||
|
||||
<div class="menu" data-menu="projekt">
|
||||
<button type="button">Projekt</button>
|
||||
@@ -786,9 +949,6 @@
|
||||
<button type="button" data-tun="undo">Rückgängig<span class="kurz">⌘Z</span></button>
|
||||
<button type="button" data-tun="redo">Wiederherstellen<span class="kurz">⇧⌘Z</span></button>
|
||||
<hr>
|
||||
<button type="button" data-opt="editmodes:e:an">Bearbeiten an<span class="kurz">E</span></button>
|
||||
<button type="button" data-opt="editmodes:e:aus">Bearbeiten aus</button>
|
||||
<hr>
|
||||
<button type="button" data-klick="reset-one">Element auf Standard</button>
|
||||
<button type="button" data-klick="reset-all">Alles auf Standard</button>
|
||||
</div>
|
||||
@@ -809,6 +969,8 @@
|
||||
<div class="menu" data-menu="ansicht">
|
||||
<button type="button">Ansicht</button>
|
||||
<div class="liste">
|
||||
<button type="button" data-tun="vorschau">Vorschau<span class="kurz">P</span></button>
|
||||
<hr>
|
||||
<button type="button" data-opt="views:w:streifen">Streifen<span class="kurz">W</span></button>
|
||||
<button type="button" data-opt="views:w:einzeln">Einzeln</button>
|
||||
<hr>
|
||||
@@ -860,29 +1022,31 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="layout-nur-diese-slide">
|
||||
<summary>Layout (nur diese Slide)</summary>
|
||||
<!-- Nicht mehr in der Seitenleiste: Layout und Perspektive sind
|
||||
post-spezifisch, Vorschau steht oben unter Ansicht, der Tag ist
|
||||
ausgeblendet. Die Schalter bleiben trotzdem im Dokument, weil die
|
||||
Menueleiste, die Tastenkuerzel und die Abgleich-Funktionen sie
|
||||
betaetigen. Sonst gaebe es zwei Wahrheiten ueber denselben Zustand. -->
|
||||
<div hidden>
|
||||
<div class="opts" id="layouts"></div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="tag-optisch-ausger-ckt">
|
||||
<summary>Tag optisch ausgerückt</summary>
|
||||
<div class="opts" id="tagouts">
|
||||
<button data-o="an" aria-pressed="true">An</button>
|
||||
<button data-o="aus" aria-pressed="false">Aus</button>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="bearbeiten">
|
||||
<summary>Bearbeiten</summary>
|
||||
<div class="opts" id="editmodes">
|
||||
<button data-e="an" aria-pressed="false">An</button>
|
||||
<button data-e="aus" aria-pressed="true">Aus</button>
|
||||
<div class="opts" id="vorschau">
|
||||
<button data-p="aus" aria-pressed="true">Aus</button>
|
||||
<button data-p="an" aria-pressed="false">An</button>
|
||||
</div>
|
||||
<div class="hint" style="margin-top:8px">Ein angeklicktes Element öffnet
|
||||
sein eigenes Feld rechts.</div>
|
||||
<button class="btn secondary" id="reset-all" style="width:100%;margin-top:8px">Alles auf Standard</button>
|
||||
</details>
|
||||
<div class="opts" id="ints">
|
||||
<button data-i="dezent" aria-pressed="true">Dezent</button>
|
||||
<button data-i="kraeftig" aria-pressed="false">Kräftig</button>
|
||||
</div>
|
||||
<div class="opts" id="tilts">
|
||||
<button data-t="an" aria-pressed="true">Gekippt</button>
|
||||
<button data-t="aus" aria-pressed="false">Gerade</button>
|
||||
</div>
|
||||
<button id="reset-all">Alles auf Standard</button>
|
||||
</div>
|
||||
|
||||
<details class="std">
|
||||
<summary>Standardwerte</summary>
|
||||
@@ -897,14 +1061,6 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="intensit-t">
|
||||
<summary>Intensität</summary>
|
||||
<div class="opts" id="ints">
|
||||
<button data-i="dezent" aria-pressed="true">Dezent</button>
|
||||
<button data-i="kraeftig" aria-pressed="false">Kräftig</button>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="bildrahmen">
|
||||
<summary>Bildrahmen</summary>
|
||||
<div class="opts three" id="frames">
|
||||
@@ -915,14 +1071,6 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="mockup-perspektive">
|
||||
<summary>Mockup-Perspektive</summary>
|
||||
<div class="opts" id="tilts">
|
||||
<button data-t="an" aria-pressed="true">Gekippt</button>
|
||||
<button data-t="aus" aria-pressed="false">Gerade</button>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="renderqualit-t">
|
||||
<summary>Renderqualität</summary>
|
||||
<div class="opts three" id="quality">
|
||||
@@ -932,12 +1080,13 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<div class="group">
|
||||
<label>Download</label>
|
||||
<div class="row" style="margin-bottom:8px">
|
||||
<button id="dl-png" disabled>Diese Slide</button>
|
||||
</div>
|
||||
<button id="dl-all" class="btn secondary" style="width:100%" disabled>Alle 5 Slides als ZIP</button>
|
||||
<!-- Der Export steht oben unter Datei. Die Knoepfe bleiben trotzdem im
|
||||
Dokument: die Menueleiste betaetigt sie, und sie tragen den Zustand
|
||||
"noch nicht bereit", solange die Schrift nicht geladen ist. Ohne sie
|
||||
muesste beides doppelt gefuehrt werden. -->
|
||||
<div hidden>
|
||||
<button id="dl-png" disabled>Diese Slide</button>
|
||||
<button id="dl-all" disabled>Alle Slides als ZIP</button>
|
||||
</div>
|
||||
|
||||
<details class="group" style="margin-bottom:0" data-grp="tastatur">
|
||||
@@ -945,10 +1094,10 @@
|
||||
<div class="keys">
|
||||
<kbd>←</kbd><kbd>→</kbd> Slide · <kbd>V</kbd> Variante<br>
|
||||
<kbd>L</kbd> Layout · <kbd>I</kbd> Intensität<br>
|
||||
<kbd>W</kbd> Ansicht · <kbd>G</kbd> Tag<br>
|
||||
<kbd>W</kbd> Ansicht<br>
|
||||
<kbd>R</kbd> Bildrahmen<br>
|
||||
<kbd>T</kbd> Perspektive<br>
|
||||
<kbd>E</kbd> Bearbeiten · Pfeile verschieben (<kbd>⇧</kbd> = 10 px)<br>
|
||||
<kbd>P</kbd> Vorschau · Pfeile verschieben (<kbd>⇧</kbd> = 10 px)<br>
|
||||
<kbd>+</kbd> <kbd>−</kbd> <kbd>0</kbd> Zoom · ⌘/Strg + Rad<br>
|
||||
<kbd>Leer</kbd> + ziehen verschiebt die Fläche<br>
|
||||
<kbd>⌘/Strg</kbd>+<kbd>Z</kbd> Rückgängig (<kbd>⇧</kbd> = wiederherstellen)<br>
|
||||
@@ -1017,82 +1166,70 @@
|
||||
Website say exactly the same thing; the headlines are new and short,
|
||||
because a full sentence does not work as a carousel hook.
|
||||
img-scale/x/y frame each capture on its telling region. */
|
||||
/* ─── Die Geschichte ──────────────────────────────────────────────────────
|
||||
Post 2 erzaehlt die Herkunft, nicht die Funktionen. Statt Screenshots
|
||||
traegt jede Slide eine gebaute Visualisierung: der Text nennt ein
|
||||
Stichwort, das Bild zeigt es. Alle sind aus derselben Formensprache wie
|
||||
die Slides selbst gebaut, also chamferte Kaesten, Sechsecke und der eine
|
||||
gelbe Akzent. Kein Bildmaterial ausser Noahs Karte. */
|
||||
/* ─── Die Geschichte ──────────────────────────────────────────────────────
|
||||
Post 2 erzaehlt die Herkunft, nicht die Funktionen. Statt Screenshots
|
||||
traegt jede Slide eine gebaute Visualisierung: der Text nennt ein
|
||||
Stichwort, das Bild zeigt es.
|
||||
|
||||
Die Texte sind NICHT die von der Website. Dort stehen ganze Absaetze, hier
|
||||
muss eine Zeile im Vorbeiscrollen sitzen. Der volle Text kommt unter den
|
||||
Beitrag, die Slide traegt nur die Zuspitzung. Faustregel aus den
|
||||
gemessenen Breiten: bei 74 px und -0,03em passen rund 26 Zeichen in eine
|
||||
Zeile, mit Marker etwas weniger. Keine Zeile hier ist laenger als 22. */
|
||||
const VORLAGEN = [
|
||||
{
|
||||
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: "Laptop · Board" }],
|
||||
head: 'Vom <span class="a">Handwerker</span><br>f\u00fcr Handwerker',
|
||||
sub: "Die Software, die deine Branchenprogramme nicht ersetzt, sondern verbindet.",
|
||||
key: "titel", type: "feature",
|
||||
layouts: [{ id: "standard", label: "Standard" }],
|
||||
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,
|
||||
},
|
||||
{
|
||||
key: "workflow-engine", type: "feature",
|
||||
key: "prozesse", type: "feature",
|
||||
layouts: [{ id: "standard", label: "Standard" }],
|
||||
eyebrow: "Automation & KI",
|
||||
head: '<span class="a">Wenn-dann</span><br>statt Handarbeit.',
|
||||
body: "Auslöser wählen, Aktionen dranhängen, fertig. Alles automatisch und ohne eine Zeile Code.",
|
||||
img: "./assets/screens/workflow.png",
|
||||
mockW: 940, mockAR: 2.366,
|
||||
imgScale: 1, imgX: "0%", imgY: "0%",
|
||||
// Die Bausteinliste ragt über den Ablauf hinaus: sie zeigt, woraus er entsteht.
|
||||
media2: {
|
||||
img: "./assets/screens/workflow-bausteine.png",
|
||||
w: 340, ar: 0.8326, left: 700, bottom: 96, z: 2, rot: 0,
|
||||
},
|
||||
// Der Zettel liegt bewusst schief und leicht über der linken Blattkante:
|
||||
// er gehört zum Ablauf, ist aber sichtbar von Hand dazugelegt.
|
||||
note: {
|
||||
text: "Eigene Notizen direkt am Ablauf hinterlegen.",
|
||||
w: 320, left: 44, bottom: 150, z: 3, rot: -3,
|
||||
},
|
||||
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,
|
||||
},
|
||||
{
|
||||
key: "projektmanagement", type: "feature",
|
||||
key: "wechseln", type: "feature",
|
||||
layouts: [{ id: "standard", label: "Standard" }],
|
||||
eyebrow: "Vertrieb",
|
||||
head: 'Du siehst auf einen Blick,<br><span class="a">wo alle Auftr\u00e4ge stehen.</span>',
|
||||
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
|
||||
// 0 bis 0,5. Das Rahmenverhältnis ist die halbierte Bildbreite.
|
||||
mockW: 580, mockAR: 0.8855,
|
||||
imgScale: 2, imgX: "0%", imgY: "0%",
|
||||
// Detailspalte eines Projekts vor dem Board: zeigt, was hinter einer
|
||||
// Karte steckt, ohne das Board zu verdecken.
|
||||
media2: {
|
||||
img: "./assets/screens/pipelines-detail.png",
|
||||
w: 300, ar: 0.781, left: 500, bottom: 52, z: 2, rot: -2,
|
||||
},
|
||||
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,
|
||||
},
|
||||
{
|
||||
key: "chat", type: "feature",
|
||||
key: "mehr", type: "feature",
|
||||
layouts: [{ id: "standard", label: "Standard" }],
|
||||
eyebrow: "Chat",
|
||||
// Zweizeilig, aber knapp: Zeile 2 misst mit Marker 880 px bei 896
|
||||
// verfuegbaren. Ein laengeres Wort bricht sofort um.
|
||||
head: 'Projekte bekommen<br>automatisch <span class="a">ihren Kanal.</span>',
|
||||
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",
|
||||
w: 300, ar: 0.866, left: 120, bottom: 55, z: 2, rot: -3,
|
||||
},
|
||||
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,
|
||||
},
|
||||
{
|
||||
key: "form-builder", type: "feature",
|
||||
key: "verbinden", type: "feature",
|
||||
layouts: [{ id: "standard", label: "Standard" }],
|
||||
eyebrow: "Formulare",
|
||||
head: 'Formulare selbst bauen.<br><span class="a">Per Drag-and-drop.</span>',
|
||||
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",
|
||||
mockW: 540, mockAR: 0.75, mockLeft: 270,
|
||||
imgScale: 3.8, imgX: "-36.9%", imgY: "-10%",
|
||||
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,
|
||||
},
|
||||
{
|
||||
key: "warteliste", type: "feature",
|
||||
layouts: [{ id: "standard", label: "Standard" }],
|
||||
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,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1130,6 +1267,73 @@
|
||||
{ pfad: "./assets/screens/form-builder.png", name: "Form Builder" },
|
||||
];
|
||||
|
||||
/* ─── Visualisierungen ───────────────────────────────────────────────────
|
||||
Jede Slide nennt ueber "vis" ihr Bild. Gebaut wird es hier aus HTML, nicht
|
||||
aus einer Aufnahme: so bleibt es beim Export scharf und laesst sich wie
|
||||
jedes andere Element im Canvas verschieben. */
|
||||
const kasten = (titel, zeile, marke) =>
|
||||
'<div class="vis-kasten' + (marke ? " vis-marke" : "") + '">' +
|
||||
'<div class="vis-titel">' + titel + '</div>' +
|
||||
(zeile ? '<div class="vis-zeile">' + zeile + '</div>' : '') +
|
||||
'</div>';
|
||||
|
||||
const VIS = {
|
||||
karte: () =>
|
||||
'<div class="karte">' +
|
||||
'<div class="karte-grund"><img alt="" src="' + assets["./assets/team/noah-bg.webp"] + '">' +
|
||||
'<span class="karte-wash"></span></div>' +
|
||||
'<img class="karte-person" alt="Noah Geerkens" src="' +
|
||||
assets["./assets/team/noah-person.webp"] + '">' +
|
||||
'<div class="karte-name"><span>Noah</span><small>CEO</small></div>' +
|
||||
'</div>',
|
||||
|
||||
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>',
|
||||
|
||||
ersetzen: () =>
|
||||
'<div class="vis-ersetzen">' +
|
||||
'<div class="schwer vis-stapel">' +
|
||||
kasten("Stammdaten", "seit Jahren gepflegt") +
|
||||
kasten("Aufträge", "die ganze Historie") +
|
||||
kasten("Buchhaltung", "und die Leute, die es kennen") +
|
||||
'</div>' +
|
||||
'<div class="pfeil"><div class="vis-kreuz"><i></i><i></i></div></div>' +
|
||||
'<div class="leer">alles noch mal von vorn</div>' +
|
||||
'</div>',
|
||||
|
||||
lose: () =>
|
||||
'<div class="vis-lose">' +
|
||||
'<div class="feld">' + kasten("KI", "fehlt") + '<span class="stummel"></span></div>' +
|
||||
'<div class="feld">' + kasten("CRM", "fehlt") + '<span class="stummel"></span></div>' +
|
||||
'<div class="feld">' + kasten("Automation", "fehlt") + '<span class="stummel"></span></div>' +
|
||||
'<div class="feld">' + kasten("ERP", "läuft, redet aber mit niemandem") + '<span class="stummel"></span></div>' +
|
||||
'</div>',
|
||||
|
||||
verbinden: () =>
|
||||
'<div class="vis-verbinden">' +
|
||||
'<div class="saeule">' + kasten("KI") + kasten("CRM") + '</div>' +
|
||||
'<div class="mitte">' +
|
||||
'<span class="quer li"></span>' +
|
||||
'<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>',
|
||||
|
||||
warteliste: () =>
|
||||
'<div class="vis-warteliste">' +
|
||||
'<div class="feldzeile">' +
|
||||
'<div class="eingabe">deine@firma.de</div>' +
|
||||
'<div class="knopf">Auf die Warteliste</div>' +
|
||||
'</div>' +
|
||||
'<div class="adresse">hivegrid.de</div>' +
|
||||
'</div>',
|
||||
};
|
||||
|
||||
/* ─── Das Deck ────────────────────────────────────────────────────────────
|
||||
Welche Slides der Post hat, steht nicht mehr fest. Jeder Eintrag ist
|
||||
entweder eine mitgelieferte Vorlage (ref) oder eine selbst angelegte, und
|
||||
@@ -1191,6 +1395,7 @@
|
||||
"screen-logo": { label: "Logo im Screen", size: 430, prop: "width" },
|
||||
"laptop": { label: "Laptop", size: 960, prop: "width" },
|
||||
"szene": { label: "Laptop · Board", size: 880, prop: "width" },
|
||||
"vis": { label: "Visualisierung", size: null, 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" },
|
||||
@@ -1205,6 +1410,7 @@
|
||||
if (key === "mock") return SLIDES[i].mockW || 1090;
|
||||
if (key === "mock-2") return (SLIDES[i].media2 || {}).w || 400;
|
||||
if (key === "note") return (SLIDES[i].note || {}).w || 320;
|
||||
if (key === "vis") return SLIDES[i].visW || 900;
|
||||
return (STANDARD[key] || {}).size;
|
||||
}
|
||||
|
||||
@@ -1222,7 +1428,8 @@
|
||||
let edits = SLIDES.map(() => ({}));
|
||||
|
||||
let picked = null; // { slide, key }
|
||||
let editMode = "aus";
|
||||
// Bearbeiten ist immer an. "aus" heisst Vorschau: alles festgelegt.
|
||||
let editMode = "an";
|
||||
|
||||
let current = 0;
|
||||
let variant = "dunkel", tilt = "an", superSample = 2, view = "streifen", tagOut = "an", frameStyle = "chamfer";
|
||||
@@ -1731,6 +1938,16 @@
|
||||
content.className = "content";
|
||||
page.appendChild(content);
|
||||
|
||||
if (sl.vis && VIS[sl.vis]) {
|
||||
const v = document.createElement("div");
|
||||
v.className = "vis vis-" + sl.vis;
|
||||
v.style.cssText =
|
||||
"--vis-w:" + (sl.visW || 900) + "px;--vis-left:" + (sl.visLeft || 92) +
|
||||
"px;--vis-bottom:" + (sl.visBottom || 96) + "px";
|
||||
v.innerHTML = VIS[sl.vis]();
|
||||
page.appendChild(v);
|
||||
}
|
||||
|
||||
if (sl.type === "feature" && assets[sl.img]) {
|
||||
const mock = document.createElement("div");
|
||||
mock.className = "mock";
|
||||
@@ -1882,7 +2099,9 @@
|
||||
.concat(SLIDES.filter(s => s.img).map(s => s.img))
|
||||
.concat(SLIDES.filter(s => s.back).map(s => s.back.img))
|
||||
.concat(SLIDES.filter(s => s.media2).map(s => s.media2.img));
|
||||
paths.push("./assets/screens/pipelines.png", "./assets/screens/chat-tablet.png");
|
||||
// Noahs Karte von der Ueber-uns-Seite. Zwei Bilder, weil die Karte die
|
||||
// Person freigestellt vor ihren eigenen Hintergrund legt.
|
||||
paths.push("./assets/team/noah-bg.webp", "./assets/team/noah-person.webp");
|
||||
/* Alle Screens, nicht nur die gerade benutzten: eine selbst angelegte
|
||||
Slide kann jeden davon waehlen, und ein Bild, das erst beim Auswaehlen
|
||||
geladen wuerde, fehlt im Export. */
|
||||
@@ -3115,18 +3334,24 @@
|
||||
})();
|
||||
|
||||
document.getElementById("forget").addEventListener("click", forgetProject);
|
||||
document.getElementById("editmodes").addEventListener("click", e => {
|
||||
document.getElementById("vorschau").addEventListener("click", e => {
|
||||
const b = e.target.closest("button");
|
||||
if (!b) return;
|
||||
editMode = b.dataset.e;
|
||||
press("editmodes", "e", editMode);
|
||||
setVorschau(b.dataset.p === "an");
|
||||
});
|
||||
|
||||
/* In der Vorschau ist alles festgelegt: keine Auswahl, kein Ziehen, keine
|
||||
Rahmen. Blaettern und Zoomen bleiben, das ist der Sinn der Sache. */
|
||||
function setVorschau(an) {
|
||||
editMode = an ? "aus" : "an";
|
||||
press("vorschau", "p", an ? "an" : "aus");
|
||||
deck.querySelectorAll(".slide").forEach(el => { el.dataset.editmode = editMode; });
|
||||
if (editMode === "aus") {
|
||||
if (an) {
|
||||
picked = null;
|
||||
deck.querySelectorAll("[data-edit]").forEach(n => n.classList.remove("picked"));
|
||||
syncEditPanel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ─── Angleichen über alle Slides ────────────────────────────────────────
|
||||
Das gewählte Element ist die Vorlage, alle gleichnamigen auf den anderen
|
||||
@@ -3286,7 +3511,7 @@
|
||||
const menues = [...bar.querySelectorAll(".menu")];
|
||||
const zu = () => menues.forEach(m => delete m.dataset.offen);
|
||||
|
||||
const AKTION = { undo, redo };
|
||||
const AKTION = { undo, redo, vorschau: () => setVorschau(editMode === "an") };
|
||||
|
||||
// Haken und graue Eintraege erst beim Oeffnen setzen: vorher weiss die
|
||||
// Leiste nicht, was gerade gilt.
|
||||
@@ -3299,6 +3524,11 @@
|
||||
b.insertAdjacentHTML("afterbegin",
|
||||
'<span class="haken">' + (an ? "✓" : "") + "</span>");
|
||||
});
|
||||
m.querySelectorAll('button[data-tun="vorschau"]').forEach(b => {
|
||||
b.querySelector(".haken")?.remove();
|
||||
b.insertAdjacentHTML("afterbegin",
|
||||
'<span class="haken">' + (editMode === "aus" ? "✓" : "") + "</span>");
|
||||
});
|
||||
m.querySelectorAll("button[data-klick]").forEach(b => {
|
||||
const q = document.getElementById(b.dataset.klick);
|
||||
b.disabled = !q || q.disabled;
|
||||
@@ -3545,13 +3775,12 @@
|
||||
else if (e.key === "-") { setZoom((zoom || autoFit()) / 1.25); }
|
||||
else if (e.key === "0") { zoom = null; fitStrip(); }
|
||||
else if (k === "w") { view = view === "streifen" ? "einzeln" : "streifen"; deck.dataset.view = view; press("views", "w", view); zoom = null; show(current); }
|
||||
else if (k === "e") { document.querySelector('#editmodes button[data-e="' + (editMode === "an" ? "aus" : "an") + '"]').click(); }
|
||||
else if (k === "p") { setVorschau(editMode === "an"); }
|
||||
else if (k === "r") {
|
||||
const cyc = ["chamfer", "rund", "stapel", "aus"];
|
||||
frameStyle = cyc[(cyc.indexOf(frameStyle) + 1) % cyc.length];
|
||||
press("frames", "f", frameStyle); applyAll(); saveState();
|
||||
}
|
||||
else if (k === "g") { tagOut = tagOut === "an" ? "aus" : "an"; press("tagouts", "o", tagOut); applyAll(); saveState(); }
|
||||
else if (k === "d") guard(downloadOne)();
|
||||
else if (k === "a") guard(downloadAll)();
|
||||
});
|
||||
|
||||
+31
-124
@@ -14,7 +14,11 @@
|
||||
},
|
||||
{
|
||||
"bg": "raster",
|
||||
"int": "kraeftig"
|
||||
"int": "dezent"
|
||||
},
|
||||
{
|
||||
"bg": "raster",
|
||||
"int": "dezent"
|
||||
},
|
||||
{
|
||||
"bg": "raster",
|
||||
@@ -28,159 +32,62 @@
|
||||
"werte": {}
|
||||
},
|
||||
{
|
||||
"ref": "workflow-engine",
|
||||
"ref": "prozesse",
|
||||
"werte": {}
|
||||
},
|
||||
{
|
||||
"ref": "projektmanagement",
|
||||
"ref": "wechseln",
|
||||
"werte": {}
|
||||
},
|
||||
{
|
||||
"ref": "chat",
|
||||
"ref": "mehr",
|
||||
"werte": {}
|
||||
},
|
||||
{
|
||||
"ref": "form-builder",
|
||||
"ref": "verbinden",
|
||||
"werte": {}
|
||||
},
|
||||
{
|
||||
"ref": "warteliste",
|
||||
"werte": {}
|
||||
}
|
||||
],
|
||||
"edits": [
|
||||
{
|
||||
"laptop": {
|
||||
"dx": -15,
|
||||
"dy": -39,
|
||||
"size": 827
|
||||
},
|
||||
"logo-full": {
|
||||
"dx": -40,
|
||||
"dy": 597
|
||||
},
|
||||
"szene": {
|
||||
"dx": 129,
|
||||
"dy": -286,
|
||||
"size": 1816
|
||||
},
|
||||
"wabe-claim": {
|
||||
"dx": 1214,
|
||||
"dy": -1110
|
||||
},
|
||||
"wabe-logo": {
|
||||
"dx": 215,
|
||||
"dy": 831
|
||||
},
|
||||
"wabe-tagline": {
|
||||
"dx": 141,
|
||||
"dy": -33,
|
||||
"size": 88
|
||||
"vis": {
|
||||
"dx": -100,
|
||||
"dy": 250,
|
||||
"size": 700
|
||||
}
|
||||
},
|
||||
{
|
||||
"badge": {
|
||||
"dx": 311,
|
||||
"dy": -77
|
||||
},
|
||||
"body": {
|
||||
"dx": 2,
|
||||
"dy": -55
|
||||
},
|
||||
"headline": {
|
||||
"dx": 0,
|
||||
"dy": -109
|
||||
},
|
||||
"mock": {
|
||||
"dx": -38,
|
||||
"dy": -383,
|
||||
"size": 965
|
||||
},
|
||||
"mock-2": {
|
||||
"dx": -75,
|
||||
"dy": 1,
|
||||
"size": 354
|
||||
},
|
||||
"note": {
|
||||
"dx": 150,
|
||||
"dy": -244,
|
||||
"size": 320
|
||||
"vis": {
|
||||
"dx": -7,
|
||||
"dy": -19
|
||||
}
|
||||
},
|
||||
{
|
||||
"badge": {
|
||||
"dx": -42,
|
||||
"dy": -68
|
||||
},
|
||||
"body": {
|
||||
"dx": 2,
|
||||
"dy": -55
|
||||
},
|
||||
"headline": {
|
||||
"dx": 0,
|
||||
"dy": -109
|
||||
},
|
||||
"mock": {
|
||||
"dx": 107,
|
||||
"dy": 1,
|
||||
"size": 706
|
||||
},
|
||||
"mock-2": {
|
||||
"dx": 159,
|
||||
"dy": 8,
|
||||
"size": 360
|
||||
"vis": {
|
||||
"dx": 19,
|
||||
"dy": -27
|
||||
}
|
||||
},
|
||||
{
|
||||
"badge": {
|
||||
"dx": -42,
|
||||
"dy": -68
|
||||
},
|
||||
"body": {
|
||||
"dx": 2,
|
||||
"dy": -55
|
||||
},
|
||||
"headline": {
|
||||
"dx": 0,
|
||||
"dy": -109
|
||||
},
|
||||
"mock": {
|
||||
"dx": -20,
|
||||
"dy": -222,
|
||||
"size": 931
|
||||
},
|
||||
"mock-2": {
|
||||
"dx": -69,
|
||||
"dy": -139
|
||||
}
|
||||
},
|
||||
{
|
||||
"badge": {
|
||||
"dx": -42,
|
||||
"dy": -68
|
||||
},
|
||||
"body": {
|
||||
"dx": 2,
|
||||
"dy": -55
|
||||
},
|
||||
"headline": {
|
||||
"dx": 0,
|
||||
"dy": -109
|
||||
},
|
||||
"mock": {
|
||||
"dx": -24,
|
||||
"dy": -8,
|
||||
"size": 584
|
||||
}
|
||||
}
|
||||
{},
|
||||
{},
|
||||
{}
|
||||
],
|
||||
"frameStyle": "rund",
|
||||
"frameStyle": "chamfer",
|
||||
"layoutState": [
|
||||
"szene",
|
||||
"standard",
|
||||
"standard",
|
||||
"standard",
|
||||
"standard",
|
||||
"standard",
|
||||
"standard"
|
||||
],
|
||||
"superSample": 3,
|
||||
"superSample": 2,
|
||||
"tagOut": "an",
|
||||
"tilt": "aus",
|
||||
"tilt": "an",
|
||||
"v": 6,
|
||||
"variant": "hell",
|
||||
"view": "streifen"
|
||||
|
||||
Reference in new issue
Block a user