diff --git a/README.md b/README.md index 6601bfb..366fd2a 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ pixelweise schieben (`⇧` = 10 px) und über `A−`/`A+` in der Größe ändern assets/ ├── brand/ Wortmarke hell/dunkel, G-Marke (SVG + PNG), Wabe, Geerkens ├── partner/ DATEV, KWP, Google Calendar, Google Drive, MS Outlook, MS Teams -├── mockups/ Geräte-Mockups (Display ausgeknockt, Screenshot liegt dahinter) +├── mockups/ Geräte-Mockups (Displays ausgeknockt, Screenshot liegt dahinter) ├── screens/ Software-Screenshots └── fonts/ Manrope 400–800, lokal vendor/ html-to-image, JSZip diff --git a/assets/mockups/macbook-szene.png b/assets/mockups/macbook-szene.png new file mode 100644 index 0000000..2e6b96d Binary files /dev/null and b/assets/mockups/macbook-szene.png differ diff --git a/post1.html b/post1.html index e8b2295..55a52a3 100644 --- a/post1.html +++ b/post1.html @@ -348,7 +348,7 @@ Textfluss: So verschiebt ein Element nie seine Nachbarn und lässt sich jederzeit exakt auf 0 zurücksetzen. Elemente mit eigener Transformation komponieren die Offsets in ihre bestehende Regel hinein. */ - [data-edit] { transform: translate(var(--ex, 0px), var(--ey, 0px)); } + [data-edit] { transform: translate(var(--ex, 0px), var(--ey, 0px)) rotate(var(--rot, 0deg)); } .slide[data-editmode="an"] [data-edit] { cursor: grab; } .slide[data-editmode="an"] [data-edit]:hover { outline: 3px dashed rgba(241,183,41,.75); outline-offset: 6px; } @@ -419,14 +419,14 @@ ); /* Rahmenform ist umschaltbar. Bei "rund" muss clip-path weichen, sonst gewinnt der Schnitt gegen border-radius; bei "aus" fällt auch Polsterung - und Fläche weg, der Schatten bleibt als einzige Tiefe. */ - /* clip-path also clips box-shadow, so depth has to come from a filter — - documented caveat in lib/chamfer.ts. */ - filter: drop-shadow(0 34px 60px rgba(0,0,0,.30)); + und Fläche weg. + Kein Schatten: die Gestaltung arbeitet flächig, Tiefe entsteht über + Überlappung und Rahmenfarbe, nicht über Weichzeichnung. */ } .slide[data-tilt="an"] .mock { transform: translate(var(--ex, 0px), var(--ey, 0px)) - perspective(2600px) rotateY(-7deg) rotateX(2.5deg) rotate(-1.2deg); + perspective(2600px) rotateY(-7deg) rotateX(2.5deg) + rotate(calc(-1.2deg + var(--rot, 0deg))); } .mock-inner { @@ -439,6 +439,57 @@ ); } + /* Ein zweites Bild pro Slide. Es ist bewusst wieder ein .mock, damit alle + Rahmenformen, Schatten und Perspektiven ohne Sonderregeln greifen; nur + Position, Größe und Stapelebene kommen von aussen. */ + .mock-2 { + z-index: var(--m2-z, 2); + bottom: var(--m2-bottom, 96px); + } + .slide[data-frame="stapel"] .mock-2 .sheet-back, + .slide[data-frame="stapel"] .mock-2 .sheet-mid { display: none; } + + /* ─── Notizzettel ──────────────────────────────────────────────────────── + Nachbau der StickyNote aus dem Pitch-Projekt + (ui/components/StickyNote/StickyNote.tsx), Variante "purple". Farbwerte + und Aufbau sind von dort übernommen, die Maße hochskaliert: die Vorlage + ist 200 px breit bei 14 px Text, hier liegt sie auf einem 1080er Blatt. + Bewusst echtes HTML statt Screenshot, damit die Kanten beim Export + genauso scharf sind wie die Schrift und der Text austauschbar bleibt. */ + .note { + position: absolute; z-index: var(--note-z, 3); + left: var(--note-left, 60px); + bottom: var(--note-bottom, 150px); + width: var(--note-w, 320px); + border-radius: 10px; overflow: hidden; + font-family: Manrope, sans-serif; + } + .note-head { + height: 50px; background: #ce93d8; + display: flex; align-items: center; justify-content: flex-end; + padding-right: 12px; + } + .note-head svg { width: 26px; height: 26px; display: block; } + .note-body { + background: #f3e5f5; color: #424242; + padding: 18px 20px 26px; min-height: 168px; + font-size: 23px; font-weight: 400; line-height: 1.5; + } + /* Der Anfasser unten rechts: zwei ineinanderliegende Ecken, wie im Original + zwei Spans mit border-b/border-r in zwei Deckkraften. */ + .note-grip { position: absolute; right: 9px; bottom: 9px; } + .note-grip i { + position: absolute; right: 0; bottom: 0; display: block; + border-right: 2px solid rgba(66,66,66,.45); + border-bottom: 2px solid rgba(66,66,66,.45); + } + .note-grip i:first-child { width: 17px; height: 17px; } + .note-grip i:last-child { + width: 10px; height: 10px; + border-right-color: rgba(66,66,66,.65); + border-bottom-color: rgba(66,66,66,.65); + } + .slide[data-frame="rund"] .mock { clip-path: none; border-radius: 30px; } .slide[data-frame="rund"] .mock-inner { clip-path: none; border-radius: 20px; } @@ -448,30 +499,29 @@ .slide[data-frame="aus"] .mock-inner { clip-path: none; border-radius: 0; } /* ─── Stapel ───────────────────────────────────────────────────────────── - Zwei versetzte Blätter hinter dem Screenshot. Der Rahmen selbst fällt weg, - jedes Blatt trägt seinen eigenen Schatten: box-shadow statt drop-shadow, - weil ohne clip-path nichts mehr beschnitten wird und jede Karte einzeln - abheben soll. */ + Zwei versetzte Blätter hinter dem Screenshot. Der Rahmen selbst fällt weg. + Getrennt werden die Blätter nicht durch Schatten, sondern durch den + Versatz und eine Haarlinie: auf der hellen Variante läge sonst Weiss auf + Weiss und der Stapel wäre nicht mehr zu erkennen. */ .sheet-back, .sheet-mid { display: none; position: absolute; inset: 0; z-index: 0; background: #fff; border-radius: 22px; overflow: hidden; + border: 1px solid rgba(48,49,61,.18); } .slide[data-frame="stapel"] .mock { - clip-path: none; padding: 0; background: none; filter: none; + clip-path: none; padding: 0; background: none; } .slide[data-frame="stapel"] .mock-inner { clip-path: none; border-radius: 22px; z-index: 2; - box-shadow: 0 34px 64px rgba(0,0,0,.30), 0 3px 10px rgba(0,0,0,.14); + border: 1px solid rgba(48,49,61,.18); } .slide[data-frame="stapel"] .sheet-mid { display: block; z-index: 1; transform: rotate(-2.4deg) translate(-2.2%, 3%) scale(.975); - box-shadow: 0 22px 44px rgba(0,0,0,.20); } .slide[data-frame="stapel"] .sheet-back { display: block; transform: rotate(3.2deg) translate(3%, 5.5%) scale(.95); - box-shadow: 0 18px 38px rgba(0,0,0,.16); } /* Das hinterste Blatt zeigt bewusst einen anderen Screen: der Stapel soll nach mehreren Ansichten aussehen, nicht nach einer Kopie. */ @@ -480,15 +530,6 @@ transform-origin: top left; } - /* Schatten global abschaltbar. Zwei Techniken im Spiel: drop-shadow für die - chamferten Rahmen (clip-path würde box-shadow wegschneiden) und box-shadow - für den Stapel. Beide müssen mit. */ - .slide[data-shadow="aus"] .mock, - .slide[data-shadow="aus"] .laptop, - .slide[data-shadow="aus"] .hex-frame { filter: none; } - .slide[data-shadow="aus"] .mock-inner, - .slide[data-shadow="aus"] .sheet-mid, - .slide[data-shadow="aus"] .sheet-back { box-shadow: none; } /* Screens are ~2000px wide landscape captures; showing them whole makes the UI text unreadable at this size, so each one is zoomed onto its telling region via the per-slide vars below. */ @@ -505,7 +546,6 @@ .hex-frame { padding: 15px; background: var(--frame-bg); clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); - filter: drop-shadow(0 26px 48px rgba(0,0,0,.26)); } .hex-shot { position: relative; overflow: hidden; @@ -516,14 +556,14 @@ .hex-shot img { position: absolute; top: 0; left: 0; width: 100%; transform-origin: top left; - transform: scale(1.75) translate(-21%, -4%); + transform: scale(1.533) translate(-17.4%, 0%); } /* Laptop mockup. The display was knocked out of the PNG, so the screenshot sits BEHIND the device and the notch plus the rounded corners stay on top, the way a real mockup reads. Rect measured from the file: 739 x 489 of 1050 x 700. */ - .laptop { position: relative; width: 960px; filter: drop-shadow(0 28px 50px rgba(0,0,0,.30)); } + .laptop { position: relative; width: 960px; } .laptop-frame { width: 100%; display: block; position: relative; z-index: 2; } .laptop-screen { position: absolute; z-index: 1; overflow: hidden; @@ -535,7 +575,7 @@ .laptop-screen > img.laptop-shot { position: absolute; top: 0; left: 0; width: 100%; transform-origin: top left; - transform: scale(1) translate(0%, 0%); + transform: scale(1.566) translate(-18.1%, 0%); } /* Blurred variant: just enough softening to seat the wordmark, the app stays readable underneath. Slightly overscaled so the blur never pulls the empty @@ -554,6 +594,59 @@ 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); + } + .szene-screen > img { + position: absolute; top: 0; left: 0; width: 100%; + transform-origin: top left; + } + /* Beide Aufnahmen liegen originalgetreu auf ihrem Display, ohne Zoom. + Sie sind flacher als der Bildschirm, es bleibt also Flaeche frei; die + traegt mit #FAFAFA den Hintergrundton der Anwendung und ist deshalb nicht + als Rand zu erkennen. + Das Board rueckt 5,15 % nach unten: das Smart-Object des PSD ragt oben + hinter die Blende des Deckels, ohne Versatz verschwindet die Kopfzeile. + Der Chat steht mittig, sein Display verdeckt nichts. */ + .szene-mb, .szene-ip { background: #FAFAFA; } + .szene-mb > img { transform: translate(0, 5.15%); } + .szene-ip > img { transform: translate(0, 16.49%); } + .laptop-missing { width: 940px; padding: 80px 40px; text-align: center; border: 3px dashed var(--shape-line); color: var(--body-color); @@ -591,7 +684,8 @@ .page.title[data-layout="laptop"] .content, .page.title[data-layout="laptop-logo"] .content, .page.title[data-layout="laptop-blur"] .content, - .page.title[data-layout="laptop-footer"] .content { + .page.title[data-layout="laptop-footer"] .content, + .page.title[data-layout="szene"] .content { padding: 92px 96px; justify-content: space-between; } .logo-full { width: 560px; height: auto; display: block; margin-bottom: 74px; } @@ -657,7 +751,7 @@