diff --git a/post2.html b/post2.html index 97039dc..3305493 100644 --- a/post2.html +++ b/post2.html @@ -375,83 +375,12 @@ } .vis svg { display: block; width: 100%; height: auto; } - .vis-kasten { - 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; } + /* Hier stand das Layout-CSS der alten Visualisierungen. Alle sechs sind + inzwischen gezeichnet, das SVG fuellt seinen Container selbst. Die Regeln + haben dreimal zugeschlagen, weil die Klasse weiter am Container haengt: + .vis-verbinden mit display:grid schob das SVG in eine Rasterzelle, + .vis-lose mit zwei Spalten auf ein Drittel Breite. Es darf hier kein + Layout-CSS mehr auftauchen. Gebraucht werden nur .vis und .vis svg. /* Slide 5 ist gezeichnet und braucht kein eigenes Layout mehr: das SVG fuellt den Container. Das alte Raster stand hier noch und hat die @@ -1250,12 +1179,6 @@ 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) => - '
' + - '
' + titel + '
' + - (zeile ? '
' + zeile + '
' : '') + - '
'; - /* ─── Skizzen-Primitive ───────────────────────────────────────────────────── Handzeichnung aus gesetztem Zufall. Der Keim ist fest: der Export rendert bei fehlgeschlagener Pruefung bis zu fuenfmal neu, und jeder Durchgang muss @@ -1734,6 +1657,157 @@ '" xmlns="http://www.w3.org/2000/svg">' + raus + ''; } + /* ─── Slide 3: wechseln kannst du vergessen ────────────────────────────── + Der Fliesstext hat zwei Haelften, und beide brauchen ein Bild: "Jahre an + Daten und Wissen haengen drin" wird zu Wurzeln im Boden, "am Ende + dasselbe, nur woanders" zu demselben Kasten noch einmal, nur gestrichelt. + Dazwischen eine gerissene Leine. + + Das Kreuz der alten Fassung lag auf dem Pfeil und nicht auf dem Ziel, aus + gutem Grund: nicht das neue System scheitert, sondern der Wechsel. Das + bleibt so. Aus dem Kreuz ist eine gerissene Leine geworden und aus dem + leeren Ziel ein gleiches, denn leer war die falsche Aussage. */ + function wurzeln(x, w, oben, tief) { + let raus = ""; + const n = 8; + for (let i = 0; i < n; i++) { + const t = (i + 0.5) / n; + const sx = x + w * (0.07 + 0.86 * t); + const laenge = tief * (0.5 + rnd() * 0.5); + const drift = (t - 0.5) * 165 + zit(26); + raus += zug(glatt([[sx, oben], + [sx + drift * 0.18 + zit(9), oben + laenge * 0.3], + [sx + drift * 0.62 + zit(11), oben + laenge * 0.66], + [sx + drift, oben + laenge]], false), + { w: 3.1 - Math.abs(t - 0.5) * 1.7 }); + const az = oben + laenge * 0.5, ax = sx + drift * 0.28; + const seite = t < 0.5 ? -1 : 1; + raus += zug(glatt([[ax, az], + [ax + seite * 20 + zit(7), az + laenge * 0.2], + [ax + seite * 33 + zit(9), az + laenge * 0.33]], false), { w: 1.8 }); + } + return raus; + } + + /* Erdreich: ungleich lange Schraegstriche. Die gleichmaessige Schraffur aus + schraff() sah nach technischer Zeichnung aus, nicht nach Boden. */ + function erdreich(x1, x2, y) { + let d = ""; + for (let x = x1; x < x2; x += 13 + rnd() * 6) { + const l = 11 + rnd() * 13; + d += strich(x, y + 2, x - l * 0.55, y + 2 + l, { j: .8, b: .8 }); + } + return d; + } + + function visWechseln() { + keim(20260815); + const W = 896, H = 730, GRAU = "#A9AFB7"; + const BY = 100, BH = 360, BW = 320, LX = 30, RX = 555; + const zeilen = ["Stammdaten", "Aufträge", "Historie", "Wissen im Kopf"]; + const mitte = BY + BH / 2; + + const inhalt = (x, farbe) => zeilen.map((z, i) => + '' + z + '').join(""); + const striche = x => zeilen.map((z, i) => + strich(x + 28, BY + 87 + i * 66, x + 48, BY + 87 + i * 66, { j: .8, b: .8 })).join(""); + + let raus = ""; + + // Der Bestand: schwerer Strich, doppelte Unterkante. + raus += zug(rechteck(LX, BY, BW, BH, { ue: 4.5 }), { w: 3.8 }); + raus += zug(strich(LX + 6, BY + BH + 6, LX + BW - 6, BY + BH + 6, { ue: 2 }), { w: 3 }); + raus += zug(striche(LX), { w: 2.6 }); + + /* Die Erdoberflaeche liegt dicht unter dem Kasten, nicht am unteren Rand. + Im ersten Wurf lag sie 120 px tiefer, dadurch endeten die Wurzeln in der + Luft und sahen aus wie Beine. Sie muessen die Linie kreuzen, sonst + stecken sie nicht drin. */ + const boden = BY + BH + 18; + raus += zug(strich(0, boden, 500, boden, { ue: 4 }), { w: 3 }); + raus += zug(erdreich(6, 494, boden), { w: 1.9, op: .45 }); + raus += wurzeln(LX, BW, BY + BH + 6, 142); + + /* Die Leine reisst, und der Akzent sitzt genau dort, wo die Aussage sitzt. + Entscheidend ist, dass beide Enden nach unten haengen und die Fasern in + dieselbe Richtung weiter ausfransen. Im ersten Wurf zeigten sie + aufeinander zu: das ergab zwei Pfeilspitzen, also die gegenteilige + Aussage. Eine gerissene Leine faellt, sie zielt nicht. */ + const endL = [418, mitte + 62], endR = [496, mitte + 48]; + raus += zug(glatt([[LX + BW, mitte - 8], [388, mitte + 2], [412, mitte + 28], + endL], false), { f: GELB, w: 4.4 }); + raus += zug(glatt([[RX, mitte - 8], [528, mitte + 0], [502, mitte + 22], + endR], false), { f: GELB, w: 4.4 }); + let fransen = ""; + [endL, endR].forEach(e => { + [-0.42, -0.05, 0.36].forEach(o => { + fransen += strich(e[0], e[1] - 4, + e[0] + Math.sin(o) * 26, e[1] + Math.cos(o) * 26, { j: .9, b: 1.1 }); + }); + }); + raus += zug(fransen, { f: GELB, w: 2.8 }); + + // Dasselbe noch einmal, nur woanders: gleiche Groesse, gleiche Zeilen. + raus += zug(rechteck(RX, BY, BW, BH, { ue: 3 }), { w: 3, op: .6, strichel: "14 13", f: GRAU }); + raus += zug(striche(RX), { w: 2.4, f: GRAU }); + raus += inhalt(LX, TINTE) + inhalt(RX, GRAU); + + return '' + raus + ''; + } + + /* ─── Slide 4: wir wollten mehr ────────────────────────────────────────── + Die alte Fassung zeigte vier Kaesten mit "fehlt". Das ist der Mangel, die + Slide handelt aber vom Wunsch. Also ein Blatt mit einer Liste. + + Die Punkte nennen nicht noch einmal KI, CRM und Automatisierung, das steht + schon im Fliesstext darueber. Sie sagen dasselbe in den Worten eines + Betriebs. Die Kaestchen bleiben leer: erfuellt wird der Wunsch erst auf + Slide 5, und genau davon lebt der Uebergang. + + Gelb tragen die Kaestchen. Es ist der einzige Akzent hier und bleibt damit + bei seiner Rolle aus den anderen Slides: Struktur, keine Verzierung. */ + function visMehr() { + keim(20260816); + const W = 896, H = 730; + const LX = 60, RX = 800, OY = 70, UY = 650, KNICK = 58; + + const wuensche = [ + "Angebot schreibt sich selbst", + "Kunde sieht seinen Stand", + "Nichts doppelt eintippen", + "Alles redet miteinander", + ]; + + // Blatt mit abgeknickter Ecke unten rechts. + const blatt = strich(LX, OY, RX, OY, { ue: 4 }) + + strich(RX, OY, RX, UY - KNICK, { ue: 3 }) + + strich(RX, UY - KNICK, RX - KNICK, UY, { ue: 2 }) + + strich(RX - KNICK, UY, LX, UY, { ue: 4 }) + + strich(LX, UY, LX, OY, { ue: 4 }); + const knick = glatt([[RX, UY - KNICK], [RX - KNICK + 8, UY - KNICK + 12], + [RX - KNICK, UY]], false); + + let raus = zug(blatt, { w: 3.4 }) + zug(knick, { w: 2.6, op: .75 }); + + wuensche.forEach((t, i) => { + const y = 180 + i * 120; + raus += zug(strich(LX + 60, y + 26, RX - 60, y + 26, { j: 1, b: 1 }), { w: 2, op: .22 }); + raus += zug(rechteck(LX + 60, y - 30, 38, 38, { ue: 3 }), { f: GELB, w: 3.4 }); + raus += '' + + t + ''; + }); + + /* Leicht schief aufs Blatt gelegt. Genau senkrecht wirkt gesetzt, und ein + Zettel liegt nie gerade. */ + return '' + + '' + raus + ''; + } + /* ─── Slide 6: was nach der Anmeldung passiert ─────────────────────────── Uebernahme der Sektion "So geht\'s weiter" von der Website, in derselben Handschrift wie Slide 5. Drei Schritte an einer Leitung, Wabe statt Kreis, @@ -1841,24 +1915,9 @@ schiene: () => visProzesse(), - ersetzen: () => - '
' + - '
' + - kasten("Stammdaten", "seit Jahren gepflegt") + - kasten("Aufträge", "die ganze Historie") + - kasten("Buchhaltung", "und die Leute, die es kennen") + - '
' + - '
' + - '
alles noch mal von vorn
' + - '
', + ersetzen: () => visWechseln(), - lose: () => - '
' + - '
' + kasten("KI", "fehlt") + '
' + - '
' + kasten("CRM", "fehlt") + '
' + - '
' + kasten("Automation", "fehlt") + '
' + - '
' + kasten("ERP", "läuft, redet aber mit niemandem") + '
' + - '
', + lose: () => visMehr(), verbinden: () => visVerbinden(),