Show the portfolio on devices and tone down the AI wording

- Mappe: each design now sits in a CSS laptop frame with a phone view
  beside it. Maison Verte and Tanzhaus Kranich play a short muted
  scroll loop (565/728 KB, H.264), started only while in view and not
  at all with prefers-reduced-motion. Atelier Rosenhain is a short
  one-pager, so it keeps its still.
- Hero: the Google result mock-up is replaced by a laptop + phone
  showing two of the designs. customImage still overrides it.
- Admin schema follows: hero.visual laptop/phone, mappe mobileImage
  and video; the Google-card fields are gone.
- "KI" now appears once, honestly, in the About paragraph. Replaced in
  the meta description, hero lead, highlight II, services lead and
  card 02, process step 03, the About quote and the footer. The
  section title now reads "Individuell, sorgfältig, technisch solide."

Em dashes in the prototypes were replaced in the browser before
recording, so none show up in the videos.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lara 2026-10-05 09:41:28 +02:00
parent b3a3680d76
commit 85c63cd714
10 changed files with 179 additions and 129 deletions

View file

@ -50,25 +50,16 @@ module.exports = [
{ key: 'ctaLabel', label: 'Button-Text', type: 'text' }, { key: 'ctaLabel', label: 'Button-Text', type: 'text' },
{ {
key: 'visual', key: 'visual',
label: 'Google-Vorschau (rechts neben dem Hero-Text)', label: 'Geräte-Ansicht (rechts neben dem Hero-Text)',
type: 'group', type: 'group',
itemFields: [ itemFields: [
{ {
key: 'customImage', key: 'customImage',
label: 'Eigenes Bild statt der Vorschau (leer = eingebaute Vorschau anzeigen)', label: 'Eigenes Bild statt Laptop und Handy (leer = Geräte anzeigen)',
type: 'image', type: 'image',
}, },
{ key: 'label', label: 'Beschriftung oben', type: 'text' }, { key: 'laptop', label: 'Bild im Laptop (Querformat 16:9)', type: 'image' },
{ key: 'todayTag', label: 'Karte 1 – Tag-Label', type: 'text' }, { key: 'phone', label: 'Bild im Handy (Hochformat)', type: 'image' },
{ key: 'todayUrl', label: 'Karte 1 – URL-Zeile', type: 'text' },
{ key: 'todayTitle', label: 'Karte 1 – Titel', type: 'text' },
{ key: 'todayDesc', label: 'Karte 1 – Beschreibung', type: 'textarea' },
{ key: 'dividerText', label: 'Trenntext zwischen den Karten', type: 'text' },
{ key: 'possibleTag', label: 'Karte 2 – Tag-Label', type: 'text' },
{ key: 'possibleUrl', label: 'Karte 2 – URL-Zeile', type: 'text' },
{ key: 'possibleTitle', label: 'Karte 2 – Titel', type: 'text' },
{ key: 'possibleDesc', label: 'Karte 2 – Beschreibung', type: 'richtext' },
{ key: 'possibleMeta', label: 'Karte 2 – Bewertungszeile', type: 'text' },
], ],
}, },
], ],
@ -179,6 +170,8 @@ module.exports = [
itemLabel: 'Arbeit', itemLabel: 'Arbeit',
itemFields: [ itemFields: [
{ key: 'image', label: 'Bildschirmfoto', type: 'image' }, { key: 'image', label: 'Bildschirmfoto', type: 'image' },
{ key: 'mobileImage', label: 'Handy-Ansicht (Hochformat, leer = kein Handy)', type: 'image' },
{ key: 'video', label: 'Video im Laptop (Pfad zu einer .mp4, leer = Standbild)', type: 'text' },
{ key: 'kategorie', label: 'Kategorie', type: 'text' }, { key: 'kategorie', label: 'Kategorie', type: 'text' },
{ key: 'titel', label: 'Titel / Name', type: 'text' }, { key: 'titel', label: 'Titel / Name', type: 'text' },
{ key: 'text', label: 'Text', type: 'textarea' }, { key: 'text', label: 'Text', type: 'textarea' },

View file

@ -1,6 +1,6 @@
{ {
"meta": { "meta": {
"description": "Larpaso entwickelt individuelle Websites für Kunden – mit KI-gestützter Entwicklung als Schwerpunkt." "description": "Larpaso entwickelt individuelle Websites für Betriebe und Unternehmen: sorgfältig gestaltet, technisch solide, zu planbaren Kosten."
}, },
"nav": { "nav": {
"logo": "/logo.svg", "logo": "/logo.svg",
@ -34,26 +34,17 @@
"titleBefore": "Websites, die zu Ihrem ", "titleBefore": "Websites, die zu Ihrem ",
"titleEmphasis": "Unternehmen", "titleEmphasis": "Unternehmen",
"titleAfter": " passen.", "titleAfter": " passen.",
"lead": "<strong>Gebaut mit KI-gestützter Entwicklung.</strong> larpaso entwickelt individuelle Websites für Kunden aus unterschiedlichen Branchen. Durch den gezielten Einsatz von KI in der Entwicklung liefern wir hochwertige Ergebnisse in kürzerer Zeit, <em>ohne Kompromisse bei Qualität und Individualität.</em>", "lead": "<strong>Durchdacht gestaltet, sauber umgesetzt.</strong> larpaso entwickelt individuelle Websites für Kunden aus unterschiedlichen Branchen. Mit einem klaren Ablauf und kurzen Wegen liefern wir hochwertige Ergebnisse in überschaubarer Zeit, <em>ohne Kompromisse bei Qualität und Individualität.</em>",
"ctaLabel": "Projekt anfragen", "ctaLabel": "Projekt anfragen",
"visual": { "visual": {
"customImage": "", "customImage": "",
"label": "Beispiel: Ihr Betrieb bei Google", "laptop": "/mappe/atelier-rosenhain.webp",
"todayTag": "Heute", "phone": "/mappe/maison-verte-mobil.webp"
"todayUrl": "ihr-betrieb.de › home",
"todayTitle": "Ihr Betrieb – Startseite",
"todayDesc": "Herzlich willkommen auf unserer Homepage. Wir freuen uns über Ihren Besuch …",
"dividerText": "Dieselbe Firma, andere Zeile",
"possibleTag": "Möglich",
"possibleUrl": "ihr-betrieb.de",
"possibleTitle": "Ihr Betrieb in [Ort] – Termine, Preise, Anfahrt",
"possibleDesc": "Geöffnet Mo–Fr 9–18 Uhr. <strong>Termin in zwei Klicks</strong>, Preise stehen auf der Seite, Anfahrt und Parkplätze erklärt.",
"possibleMeta": "★★★★★ [Zahl] Bewertungen · Jetzt geöffnet"
} }
}, },
"warum": { "warum": {
"eyebrow": "02 · Was uns unterscheidet", "eyebrow": "02 · Was uns unterscheidet",
"title": "Individuell, KI-gestützt, technisch solide.", "title": "Individuell, sorgfältig, technisch solide.",
"lead": "larpaso entwickelt individuelle Websites für Kunden, die sich von der Stange nicht zufriedengeben wollen.", "lead": "larpaso entwickelt individuelle Websites für Kunden, die sich von der Stange nicht zufriedengeben wollen.",
"readability": { "readability": {
"customImage": "", "customImage": "",
@ -126,8 +117,8 @@
}, },
{ {
"num": "II", "num": "II",
"title": "KI-gestützte Entwicklung", "title": "Klarer Ablauf, planbare Kosten",
"text": "Wir setzen moderne KI-Werkzeuge im Entwicklungsprozess ein, um schneller, gründlicher und zu planbaren Kosten zu liefern." "text": "Feste Schritte, ein verbindlicher Preis und feste Ansprechpartner von Anfang bis Ende. Sie wissen jederzeit, woran Sie sind."
}, },
{ {
"num": "III", "num": "III",
@ -138,7 +129,7 @@
"leistungen": { "leistungen": {
"eyebrow": "03 · Was Sie bekommen", "eyebrow": "03 · Was Sie bekommen",
"title": "Was wir für Sie tun können", "title": "Was wir für Sie tun können",
"lead": "Von der ersten Idee bis zur laufenden Betreuung: larpaso begleitet Ihr Website-Projekt mit individueller Entwicklung und dem gezielten Einsatz von KI-Werkzeugen.", "lead": "Von der ersten Idee bis zur laufenden Betreuung: larpaso begleitet Ihr Website-Projekt aus einer Hand, mit individueller Gestaltung und sauberer Technik.",
"items": [ "items": [
{ {
"num": "01", "num": "01",
@ -147,8 +138,8 @@
}, },
{ {
"num": "02", "num": "02",
"title": "KI-gestützte Entwicklung", "title": "Gestaltung & Texte",
"text": "Wir nutzen moderne KI-Werkzeuge gezielt im Entwicklungsprozess, um Umsetzungszeiten zu verkürzen und gleichzeitig Code-Qualität und Sorgfalt hochzuhalten." "text": "Farben, Schrift und Bildsprache passend zu Ihrem Betrieb, dazu Texte, die Ihre Kunden verstehen. Alles aus einer Hand, abgestimmt auf Ihre Zielgruppe."
}, },
{ {
"num": "03", "num": "03",
@ -187,21 +178,27 @@
"titel": "Maison Verte", "titel": "Maison Verte",
"text": "Sand und Salbei. Der Stundenplan steht als Tabelle auf der Seite, nicht als Download, und die Preise auch. Für ein Studio, das ruhig wirken soll, ohne dabei alt auszusehen.", "text": "Sand und Salbei. Der Stundenplan steht als Tabelle auf der Seite, nicht als Download, und die Preise auch. Für ein Studio, das ruhig wirken soll, ohne dabei alt auszusehen.",
"nameHidden": false, "nameHidden": false,
"image": "/mappe/maison-verte.webp" "image": "/mappe/maison-verte.webp",
"mobileImage": "/mappe/maison-verte-mobil.webp",
"video": "/mappe/maison-verte.mp4"
}, },
{ {
"kategorie": "Konzeptarbeit · Tanzschule", "kategorie": "Konzeptarbeit · Tanzschule",
"titel": "Tanzhaus Kranich", "titel": "Tanzhaus Kranich",
"text": "Dieselbe Seite zweimal, einmal kühl und einmal warm. Wir wollten wissen, was Farbe wirklich anrichtet. Der Unterschied war größer, als wir dachten. Seitdem schlagen wir Ihnen am Ende eine Fassung vor und nicht drei.", "text": "Dieselbe Seite zweimal, einmal kühl und einmal warm. Wir wollten wissen, was Farbe wirklich anrichtet. Der Unterschied war größer, als wir dachten. Seitdem schlagen wir Ihnen am Ende eine Fassung vor und nicht drei.",
"nameHidden": false, "nameHidden": false,
"image": "/mappe/tanzhaus-kranich.webp" "image": "/mappe/tanzhaus-kranich.webp",
"mobileImage": "/mappe/tanzhaus-kranich-mobil.webp",
"video": "/mappe/tanzhaus-kranich.mp4"
}, },
{ {
"kategorie": "Konzeptarbeit · Kosmetikstudio", "kategorie": "Konzeptarbeit · Kosmetikstudio",
"titel": "Atelier Rosenhain", "titel": "Atelier Rosenhain",
"text": "Weich, warm, und trotzdem kein Pastellrosa. Jede Behandlung mit Dauer und Preis, Termin direkt aus der Liste heraus. Damit niemand erst anrufen muss, um zu erfahren, was etwas kostet.", "text": "Weich, warm, und trotzdem kein Pastellrosa. Jede Behandlung mit Dauer und Preis, Termin direkt aus der Liste heraus. Damit niemand erst anrufen muss, um zu erfahren, was etwas kostet.",
"nameHidden": false, "nameHidden": false,
"image": "/mappe/atelier-rosenhain.webp" "image": "/mappe/atelier-rosenhain.webp",
"mobileImage": "/mappe/atelier-rosenhain-mobil.webp",
"video": ""
} }
] ]
}, },
@ -224,7 +221,7 @@
{ {
"num": "03", "num": "03",
"title": "Entwicklung", "title": "Entwicklung",
"text": "Umsetzung mit modernen Werkzeugen — inklusive KI-gestützter Entwicklung für mehr Tempo.", "text": "Umsetzung mit modernen Werkzeugen, sauber programmiert und auf allen Geräten getestet.",
"dauer": "2–3 Tage" "dauer": "2–3 Tage"
}, },
{ {
@ -238,7 +235,7 @@
"about": { "about": {
"eyebrow": "06 · Über uns", "eyebrow": "06 · Über uns",
"title": "Wir sind larpaso.", "title": "Wir sind larpaso.",
"quote": "KI als Werkzeug, nicht als Ausrede.", "quote": "Zuhören, mitdenken, sorgfältig arbeiten.",
"paragraphs": [ "paragraphs": [
"Technik ändert sich schnell. Und mit ihr, was Kundinnen und Kunden von einem Betrieb erwarten: eine Seite, die auf dem Handy funktioniert, klar sagt, worum es geht, und nicht nach gestern aussieht. Was heute auffällt, ist in zwei Jahren Standard. Wir bauen Websites für Menschen, die da mithalten wollen, ohne sich selbst in Technik einarbeiten zu müssen.", "Technik ändert sich schnell. Und mit ihr, was Kundinnen und Kunden von einem Betrieb erwarten: eine Seite, die auf dem Handy funktioniert, klar sagt, worum es geht, und nicht nach gestern aussieht. Was heute auffällt, ist in zwei Jahren Standard. Wir bauen Websites für Menschen, die da mithalten wollen, ohne sich selbst in Technik einarbeiten zu müssen.",
"Dabei helfen uns KI-Werkzeuge. Sie nehmen uns Routine ab, damit wir Zeit haben für das, worauf es ankommt: zuhören, mitdenken, sorgfältig arbeiten. So bleiben individuelle Lösungen in überschaubarer Zeit und zu planbaren Kosten möglich, weder Massenware noch Luxusgut." "Dabei helfen uns KI-Werkzeuge. Sie nehmen uns Routine ab, damit wir Zeit haben für das, worauf es ankommt: zuhören, mitdenken, sorgfältig arbeiten. So bleiben individuelle Lösungen in überschaubarer Zeit und zu planbaren Kosten möglich, weder Massenware noch Luxusgut."

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

View file

@ -0,0 +1,140 @@
---
/**
* Laptop mit optional angelehntem Handy, für Mappe und Hero.
* Ein Video im Laptop spielt nur, solange es sichtbar ist (Skript unten),
* und bei "Bewegung reduzieren" gar nicht - dann bleibt das Standbild.
*/
interface Props {
screen: string;
video?: string;
phone?: string;
alt?: string;
eager?: boolean;
}
const { screen, video, phone, alt = '', eager = false } = Astro.props;
const loading = eager ? 'eager' : 'lazy';
---
<div class:list={['devices', { 'has-phone': phone }]}>
<div class="laptop">
<div class="laptop-lid">
<div class="laptop-screen">
{video ? (
<video muted loop playsinline preload="none" poster={screen} data-autoplay aria-label={alt || undefined}>
<source src={video} type="video/mp4" />
</video>
) : (
<img src={screen} alt={alt} loading={loading} />
)}
</div>
</div>
<div class="laptop-base"></div>
</div>
{phone && (
<div class="phone" aria-hidden="true">
<div class="phone-screen">
<img src={phone} alt="" loading={loading} />
</div>
</div>
)}
</div>
<script>
const videos = document.querySelectorAll<HTMLVideoElement>('video[data-autoplay]');
const still = window.matchMedia('(prefers-reduced-motion: reduce)');
if (videos.length && !still.matches && 'IntersectionObserver' in window) {
const io = new IntersectionObserver(
(entries) => {
for (const { target, isIntersecting } of entries) {
const v = target as HTMLVideoElement;
if (isIntersecting) v.play().catch(() => {});
else v.pause();
}
},
{ threshold: 0.35 },
);
videos.forEach((v) => io.observe(v));
}
</script>
<style>
.devices {
position: relative;
}
.devices.has-phone {
padding: 0 9% 7% 0;
}
.laptop-lid {
background: #1f1c19;
border-radius: clamp(8px, 1.4vw, 16px) clamp(8px, 1.4vw, 16px) 3px 3px;
padding: 2.4% 2.4% 3%;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.08) inset;
}
.laptop-screen {
aspect-ratio: 16 / 9;
overflow: hidden;
border-radius: 2px;
background: #fff;
}
.laptop-screen img,
.laptop-screen video {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
object-position: top;
}
.laptop-base {
position: relative;
width: 112%;
margin-left: -6%;
height: clamp(7px, 1.1vw, 14px);
background: linear-gradient(#ddd8cf, #b9b2a6);
border-radius: 0 0 50% 50% / 0 0 100% 100%;
box-shadow: 0 18px 30px -18px rgba(31, 28, 25, 0.55);
}
.laptop-base::before {
content: '';
position: absolute;
left: 50%;
top: 0;
width: 14%;
height: 45%;
transform: translateX(-50%);
background: #a39b8e;
border-radius: 0 0 6px 6px;
}
.phone {
position: absolute;
right: 0;
bottom: 0;
width: 23%;
background: #1f1c19;
padding: 1.1%;
border-radius: clamp(14px, 2.4vw, 30px);
box-shadow: 0 20px 40px -16px rgba(31, 28, 25, 0.6);
}
.phone-screen {
aspect-ratio: 390 / 844;
overflow: hidden;
border-radius: clamp(10px, 1.8vw, 24px);
background: #fff;
}
.phone-screen img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
object-position: top;
}
</style>

View file

@ -8,7 +8,7 @@ const footer = site.footer;
<footer class="footer"> <footer class="footer">
<div class="container footer-bottom"> <div class="container footer-bottom">
<p> <p>
&copy; {year} larpaso · Individuelle Websites, KI-gestützt entwickelt · Lara &copy; {year} larpaso · Individuelle Websites, sorgfältig entwickelt · Lara
{' '}{footer.laraNachname || <span class="placeholder">[Nachname]</span>} und Pascal{' '} {' '}{footer.laraNachname || <span class="placeholder">[Nachname]</span>} und Pascal{' '}
{footer.pascalNachname || <span class="placeholder">[Nachname]</span>} {footer.pascalNachname || <span class="placeholder">[Nachname]</span>}
</p> </p>

View file

@ -1,5 +1,6 @@
--- ---
import Layout from '../layouts/Layout.astro'; import Layout from '../layouts/Layout.astro';
import Devices from '../components/Devices.astro';
import { site, rich } from '../lib/content'; import { site, rich } from '../lib/content';
const { hero, warum, preis, highlights, leistungen, mappe, ablauf, about, faq, kontakt } = site; const { hero, warum, preis, highlights, leistungen, mappe, ablauf, about, faq, kontakt } = site;
@ -22,23 +23,7 @@ const { hero, warum, preis, highlights, leistungen, mappe, ablauf, about, faq, k
{hero.visual.customImage ? ( {hero.visual.customImage ? (
<img class="hero-visual-image" src={hero.visual.customImage} alt="" loading="lazy" /> <img class="hero-visual-image" src={hero.visual.customImage} alt="" loading="lazy" />
) : ( ) : (
<> <Devices screen={hero.visual.laptop} phone={hero.visual.phone} eager />
<p class="hero-visual-label">{hero.visual.label}</p>
<div class="search-card">
<span class="search-tag">{hero.visual.todayTag}</span>
<p class="search-url">{hero.visual.todayUrl}</p>
<p class="search-title">{hero.visual.todayTitle}</p>
<p class="search-desc">{hero.visual.todayDesc}</p>
</div>
<p class="hero-visual-divider">{hero.visual.dividerText}</p>
<div class="search-card search-card-accent">
<span class="search-tag search-tag-accent">{hero.visual.possibleTag}</span>
<p class="search-url">{hero.visual.possibleUrl}</p>
<p class="search-title">{hero.visual.possibleTitle}</p>
<p class="search-desc" set:html={rich(hero.visual.possibleDesc)} />
<p class="search-meta">{hero.visual.possibleMeta}</p>
</div>
</>
)} )}
</div> </div>
</div> </div>
@ -152,8 +137,13 @@ const { hero, warum, preis, highlights, leistungen, mappe, ablauf, about, faq, k
{mappe.items.map((item) => ( {mappe.items.map((item) => (
<article class="mappe-item"> <article class="mappe-item">
{item.image ? ( {item.image ? (
<div class="mappe-shot mappe-shot-image"> <div class="mappe-devices">
<img src={item.image} alt={item.titel || item.kategorie} loading="lazy" /> <Devices
screen={item.image}
video={item.video}
phone={item.mobileImage}
alt={item.titel || item.kategorie}
/>
</div> </div>
) : ( ) : (
<div class="mappe-shot"> <div class="mappe-shot">
@ -366,75 +356,12 @@ const { hero, warum, preis, highlights, leistungen, mappe, ablauf, about, faq, k
margin-top: var(--space-6); margin-top: var(--space-6);
} }
.hero-visual-label {
font-size: var(--font-size-sm);
color: var(--color-text-muted);
margin-bottom: var(--space-3);
}
.hero-visual-image { .hero-visual-image {
width: 100%; width: 100%;
border-radius: var(--radius-md); border-radius: var(--radius-md);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
} }
.search-card {
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
padding: var(--space-5);
position: relative;
}
.search-card-accent {
border-color: var(--color-accent);
}
.search-tag {
position: absolute;
top: var(--space-4);
right: var(--space-4);
font-size: 0.7rem;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--color-text-muted);
}
.search-tag-accent {
background: var(--color-accent);
color: var(--color-primary-contrast);
padding: 0.15rem 0.5rem;
border-radius: var(--radius-sm);
}
.search-url {
font-size: var(--font-size-sm);
color: var(--color-text-muted);
margin: 0 0 var(--space-1) 0;
}
.search-title {
color: var(--color-google-blue);
font-size: var(--font-size-md);
margin: 0 0 var(--space-2) 0;
}
.search-desc,
.search-meta {
font-size: var(--font-size-sm);
color: var(--color-text-muted);
margin: 0;
}
.hero-visual-divider {
text-align: center;
font-size: 0.75rem;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-text-muted);
margin: var(--space-4) 0;
}
/* Preis */ /* Preis */
.price-grid { .price-grid {
display: grid; display: grid;
@ -639,15 +566,8 @@ const { hero, warum, preis, highlights, leistungen, mappe, ablauf, about, faq, k
overflow: hidden; overflow: hidden;
} }
.mappe-shot-image { .mappe-devices {
border: none; margin-bottom: var(--space-5);
padding: 0;
}
.mappe-shot-image img {
width: 100%;
height: 100%;
object-fit: cover;
} }
.mappe-kategorie { .mappe-kategorie {