Redesign Der Eine. PDP from mockup, reusing existing site patterns
Sections rebuilt to match der-eine.png (hero, tagline banner, brand-story + feature icons, lifestyle photo, final CTA bar with trust badges), but each piece is built from patterns that already exist elsewhere on the site rather than one-off layouts: - Focus.tsx (feature icons) mirrors todo-cards/HowItWorks.tsx's exact icon-top/title/desc card shape and typography - Why.tsx (brand story) mirrors todo-cards/Focus.tsx's photo+text layout - Pricing.tsx's trust-badge row reuses getCartTrustBadges() (real, already-vetted copy) with /cart's own markup, not invented text - Banner.tsx reuses --font-caveat and /icon-separator-right.svg (both already used in Divider.tsx) instead of introducing new assets Photos: product.image/gallery repointed (via direct DB write, see reference_payload_direct_db_access) to two new Payload media docs cropped directly from the mockup — the previous gallery was mismatched supplier stock photos of a different-colored pen. Lifestyle.tsx's desk photo is a static /public asset (page decoration showing the pen next to another product, not a photo of the pen alone, so it doesn't belong in Products.gallery).
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
|
||||
// A full-bleed yellow tagline strip between Hero and the "Warum" section —
|
||||
// no equivalent banner/CTA-strip component exists elsewhere on the site
|
||||
// (checked), so the container itself is new, but reuses two real sitewide
|
||||
// building blocks instead of inventing them: the --font-caveat handwritten
|
||||
// typeface (Divider.tsx/About.tsx) and /icon-separator-right.svg (also
|
||||
// Divider.tsx's own "Leichtigkeit" sparkle icon), rotated to point down-right.
|
||||
export function Banner() {
|
||||
return (
|
||||
<section className="w-full bg-brand py-8 sm:py-10 px-[var(--layout-padding-x)]">
|
||||
<Reveal className="max-w-[75rem] mx-auto flex items-center gap-4 sm:gap-6">
|
||||
<div className="relative shrink-0 size-8" style={{ rotate: "45deg" }}>
|
||||
<Image alt="" src="/icon-separator-right.svg" fill sizes="32px" />
|
||||
</div>
|
||||
<p
|
||||
className="text-h3 sm:text-h-section text-text-primary leading-tight"
|
||||
style={{ fontFamily: "var(--font-caveat)" }}
|
||||
>
|
||||
Ein guter Stift.
|
||||
<br />
|
||||
Mehr muss er nicht sein.
|
||||
</p>
|
||||
</Reveal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,62 +1,69 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
import { getProductBySlug } from "../../lib/payload";
|
||||
import { Reveal, RevealGroup, RevealItem } from "../../components/Reveal";
|
||||
|
||||
// Distinct from Hero.tsx's own (shorter) feature bullets — this is the
|
||||
// "Was kann er?" section's full four-item breakdown (build, engraving,
|
||||
// size, use case), each with its own one-line explanation rather than a
|
||||
// bare phrase.
|
||||
// Simple stroke-only line icons — no matching /public asset existed for
|
||||
// these concepts (checked: pencil/pen/sparkle/shield), so these are drawn
|
||||
// fresh rather than upscaling a raster crop from the mockup, same reasoning
|
||||
// as Hero.tsx's own IconCheck (crisp at any size, recolorable).
|
||||
function IconPencil() {
|
||||
return (
|
||||
<svg width="40" height="40" viewBox="0 0 28 28" fill="none" strokeWidth="1.5" stroke="#1a1a1a" strokeLinecap="round" strokeLinejoin="round" className="h-10 w-auto">
|
||||
<path d="M18.5 4.5l5 5L9 24H4v-5L18.5 4.5z" />
|
||||
<path d="M15.5 7.5l5 5" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function IconPen() {
|
||||
return (
|
||||
<svg width="40" height="40" viewBox="0 0 28 28" fill="none" strokeWidth="1.5" stroke="#1a1a1a" strokeLinecap="round" strokeLinejoin="round" className="h-10 w-auto">
|
||||
<path d="M6 22l3-1 13-13-2-2L7 19l-1 3z" />
|
||||
<path d="M17 8l3 3" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function IconSparkle() {
|
||||
return (
|
||||
<svg width="40" height="40" viewBox="0 0 28 28" fill="none" strokeWidth="1.5" stroke="#1a1a1a" strokeLinecap="round" strokeLinejoin="round" className="h-10 w-auto">
|
||||
<path d="M14 3v8M14 17v8M3 14h8M17 14h8M6.5 6.5l5.5 5.5M16 16l5.5 5.5M21.5 6.5L16 12M12 16l-5.5 5.5" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function IconShield() {
|
||||
return (
|
||||
<svg width="40" height="40" viewBox="0 0 28 28" fill="none" strokeWidth="1.5" stroke="#1a1a1a" strokeLinecap="round" strokeLinejoin="round" className="h-10 w-auto">
|
||||
<path d="M14 3l9 3.5v6c0 6-4 10-9 12.5-5-2.5-9-6.5-9-12.5v-6L14 3z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
// This page's single feature enumeration (Hero has no bullet list anymore).
|
||||
// Same card shape as todo-cards/components/HowItWorks.tsx — icon on top,
|
||||
// centered, RevealGroup/RevealItem stagger, identical title/description
|
||||
// typography (font-semibold text-body / text-body-sm text-text-primary) —
|
||||
// reused here instead of a one-off layout, for visual consistency with the
|
||||
// rest of the site. 4 cards instead of HowItWorks' 3 numbered steps, no
|
||||
// connecting arrows (these are independent facts, not a sequence).
|
||||
const items = [
|
||||
{ title: "Metallgehäuse", desc: "Robust, wertig und angenehm in der Hand." },
|
||||
{ title: "Lasergravur", desc: "„Der Eine.“ auf der einen Seite. „einfach produktiv.“ auf der anderen." },
|
||||
{ title: "Kompakt", desc: "Passt ans Notizbuch, auf den Schreibtisch oder in die Tasche." },
|
||||
{ title: "Für jeden Tag", desc: "Für Notizen, Gedanken, Listen und alles, was du lieber aufschreibst, bevor du es wieder vergisst." },
|
||||
{ icon: IconPencil, title: "Metallgehäuse", desc: "Robust, wertig und angenehm in der Hand." },
|
||||
{ icon: IconPen, title: "Schwarze Mine", desc: "Klassische Kugelschreibermine für ein sauberes Schriftbild." },
|
||||
{ icon: IconSparkle, title: "Lasergravur", desc: "„Der Eine.“ und „einfach produktiv.“" },
|
||||
{ icon: IconShield, title: "Passt überall rein", desc: "Kompakt und leicht – für Tasche, Etui, Notizbuch." },
|
||||
];
|
||||
|
||||
// Unlike todo-cards/components/Focus.tsx, this product has no dedicated
|
||||
// lifestyle photo — only 3 supplier catalog macro shots exist, all
|
||||
// 338×338px (no larger source, confirmed against the Payload media API).
|
||||
// Uses gallery[1] (the chrome-rings close-up) — deliberately a different
|
||||
// frame than Hero's gallery (which opens on `image`, id 85) and Pricing's
|
||||
// own photo (product.image again, but cropped/treated differently there),
|
||||
// so the same handful of source photos don't read as one repeated image
|
||||
// across the page. Contained square tile, not object-cover, for the same
|
||||
// "don't blow up a 338px source" reasoning as Hero's gallery cap.
|
||||
export async function Focus() {
|
||||
const product = await getProductBySlug("stift-kugelschreiber");
|
||||
if (!product) return null;
|
||||
const photo = product.gallery[1] ?? product.image;
|
||||
|
||||
export function Focus() {
|
||||
return (
|
||||
<section className="w-full bg-bg-base flex flex-col lg:flex-row gap-10 lg:gap-16 items-center py-12 md:py-16 px-[var(--layout-padding-x)]">
|
||||
<Reveal className="group relative w-full max-w-[20rem] lg:shrink-0 aspect-square rounded-md overflow-hidden bg-bg-muted p-10">
|
||||
<Image
|
||||
src={photo}
|
||||
alt={product.name}
|
||||
fill
|
||||
sizes="320px"
|
||||
className="object-contain transition-transform duration-500 group-hover:scale-105"
|
||||
/>
|
||||
</Reveal>
|
||||
<Reveal className="flex flex-col gap-6 items-start flex-1 min-w-0 w-full" delay={0.1}>
|
||||
<p
|
||||
className="font-semibold text-h-emphasis text-text-primary"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
>
|
||||
Was kann er?
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Schreiben. Und das ziemlich gut. Metallgehäuse, angenehmes Gewicht und eine klassische Kugelschreibermine — kein besonderes Produktivitäts-Gadget, sondern einfach ein guter Stift, den du gern zur Hand nimmst.
|
||||
</p>
|
||||
<ul className="grid grid-cols-1 sm:grid-cols-2 gap-4 w-full">
|
||||
{items.map((item) => (
|
||||
<li key={item.title} className="flex flex-col gap-1 items-start">
|
||||
<span className="font-semibold text-body text-text-primary">{item.title}</span>
|
||||
<span className="text-body-sm text-text-muted">{item.desc}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Reveal>
|
||||
<section className="w-full bg-bg-base py-12 sm:py-16 px-[var(--layout-padding-x)]">
|
||||
<RevealGroup className="grid grid-cols-2 sm:flex sm:flex-row gap-8 items-start justify-center max-w-[75rem] mx-auto">
|
||||
{items.map(({ icon: Icon, title, desc }) => (
|
||||
<RevealItem key={title} className="flex flex-col gap-4 items-center text-center flex-1 max-w-xs">
|
||||
<Icon />
|
||||
<p className="font-semibold text-body text-text-primary">{title}</p>
|
||||
<p className="text-body-sm text-text-primary text-center">{desc}</p>
|
||||
</RevealItem>
|
||||
))}
|
||||
</RevealGroup>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,23 +6,10 @@ import { getProductBySlug, getShippingSettings, getDefaultTaxRatePercent, getKle
|
||||
import { formatPrice, discountPercent } from "../../lib/format";
|
||||
import { effectiveTaxRate } from "../../lib/cartTotals";
|
||||
|
||||
// The one bullet list on this page — after feedback that three separate
|
||||
// lists across Hero/Focus/Pricing was too much, this is the single place
|
||||
// features get enumerated, everywhere else stays prose. A subset of the
|
||||
// "Was kann er?" section's four cards (Focus.tsx) — "Für jeden Tag" is a
|
||||
// use case, not a build fact, so it's covered by the body copy instead.
|
||||
const features = ["Massives Metallgehäuse", "Lasergravur: „Der Eine.“ & „einfach produktiv.“", "Kompakt genug für jede Tasche"];
|
||||
|
||||
// Same fix/reasoning as TodoKartenHero.tsx's IconCheck — icon-check.svg's
|
||||
// fill can't be recolored from outside the SVG when loaded via <img
|
||||
// src>/next/image, so this stays an inline stroke path per page.
|
||||
function IconCheck() {
|
||||
return (
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" className="size-5 shrink-0 mt-1">
|
||||
<path d="M4 10.5l4.5 4.5L16 5.5" stroke="#f6a701" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
// No feature bullet list here (unlike this page's earlier draft) — matches
|
||||
// the mockup's minimal hero (headline, short 3-line description, price,
|
||||
// buy button only). The material/engraving/size facts live in Focus.tsx's
|
||||
// icon row instead, one enumeration point instead of two.
|
||||
|
||||
// Same "compact early teaser + delivery-time repeated next to every buy
|
||||
// button" reasoning as TodoKartenHero.tsx.
|
||||
@@ -56,33 +43,16 @@ export async function Hero() {
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-6 items-start w-full flex-1 lg:justify-center">
|
||||
<div className="flex flex-col gap-2 items-start w-full">
|
||||
<p
|
||||
className="font-semibold text-h-page text-text-primary"
|
||||
style={{ fontFamily: "var(--font-playfair)" }}
|
||||
>
|
||||
Der Eine<span className="text-brand">.</span>
|
||||
</p>
|
||||
<p
|
||||
className="font-semibold text-h3 text-text-primary"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
>
|
||||
Für die eine Sache, die gerade zählt.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="text-body text-text-body">
|
||||
Manchmal reicht ein Stift und ein Stück Papier. Der Eine. ist ein schlichter Kugelschreiber aus Metall — angenehm in der Hand, klein genug für die Tasche und gemacht für alles, was kurz raus aus dem Kopf und irgendwo hin muss.
|
||||
<p
|
||||
className="font-semibold text-h-page text-text-primary"
|
||||
style={{ fontFamily: "var(--font-playfair)" }}
|
||||
>
|
||||
Der Eine<span className="text-brand">.</span>
|
||||
</p>
|
||||
|
||||
<ul className="flex flex-col gap-3 items-start w-full">
|
||||
{features.map((item) => (
|
||||
<li key={item} className="flex gap-[0.625rem] items-start w-full">
|
||||
<IconCheck />
|
||||
<span className="flex-1 text-body text-text-primary">{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<p className="text-body text-text-body">
|
||||
Der Kugelschreiber zu unseren ToDo-Karten. Aus Metall, mit schwarzer Mine und „Der Eine.“ auf der Seite.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-1 items-start">
|
||||
{product && (
|
||||
@@ -110,7 +80,7 @@ export async function Hero() {
|
||||
|
||||
{product && (
|
||||
<AddToCartButton
|
||||
label="Der Eine. bestellen"
|
||||
label="In den Warenkorb"
|
||||
productId={product.id}
|
||||
numericId={product.numericId}
|
||||
outOfStock={!product.active || product.outOfStock}
|
||||
@@ -121,13 +91,10 @@ export async function Hero() {
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
{/* max-w cap, not the full lg:col-span-7 width — the source photos
|
||||
are only 338×338px (checked directly against the Payload media
|
||||
API, no larger size exists), so letting ProductGallery stretch
|
||||
to the full column blows them up hard. Capping the display
|
||||
width keeps the upscale factor small enough that it doesn't
|
||||
look broken; it can't fix the underlying resolution, only hide
|
||||
it. Real fix is new source photos, not a layout tweak. */}
|
||||
{/* max-w cap, not the full lg:col-span-7 width — image/gallery are
|
||||
still fairly small source crops (~594×370, ~480×230, taken
|
||||
2026-08-25 from the mockup design), so letting ProductGallery
|
||||
stretch to the full column would still upscale noticeably. */}
|
||||
{product && product.gallery.length > 0 && (
|
||||
<Reveal className="order-2 lg:order-none lg:col-span-7 flex lg:items-center" delay={0.15}>
|
||||
<div className="w-full max-w-[28rem] mx-auto lg:mx-0">
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
|
||||
// Full-bleed desk photo (ToDo-Karten notepad + "Der Eine." + notebook) —
|
||||
// a static /public asset, not a Payload product photo: it's page decoration
|
||||
// showing the pen alongside another product, not a photo *of* this product
|
||||
// alone, so it doesn't belong in Products.gallery (which ProductGallery.tsx
|
||||
// treats as swappable thumbnails of just the pen itself). Cropped from the
|
||||
// der-eine.png mockup, 2026-08-25.
|
||||
export function Lifestyle() {
|
||||
return (
|
||||
<Reveal className="w-full relative aspect-[1024/222] sm:aspect-[1024/180] lg:aspect-[1024/222]">
|
||||
<Image
|
||||
src="/der-eine-lifestyle.png"
|
||||
alt="Der Eine. neben den ToDo-Karten und einem Notizbuch auf dem Schreibtisch"
|
||||
fill
|
||||
sizes="100vw"
|
||||
className="object-cover"
|
||||
/>
|
||||
</Reveal>
|
||||
);
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
import Image from "next/image";
|
||||
import { AddToCartButton } from "../../components/AddToCartButton";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
import { getProductBySlug, getShippingSettings, getDefaultTaxRatePercent, getKleinunternehmer } from "../../lib/payload";
|
||||
import { getProductBySlug, getShippingSettings, getDefaultTaxRatePercent, getKleinunternehmer, getCartTrustBadges } from "../../lib/payload";
|
||||
import { formatPrice, discountPercent } from "../../lib/format";
|
||||
import { effectiveTaxRate } from "../../lib/cartTotals";
|
||||
|
||||
// Price/photo come from Payload (same "stift-kugelschreiber" product the
|
||||
// shop/cart use), not a hardcoded literal — same reasoning as
|
||||
// todo-cards/components/Pricing.tsx. Uses product.image (id 85, the
|
||||
// confident macro tip shot) — a third, distinct frame from Hero's gallery
|
||||
// opener and Focus's gallery[1] chrome-rings shot.
|
||||
// todo-cards/components/Pricing.tsx. Uses product.image (the mockup-derived
|
||||
// hero crop, see media ids 88/89 uploaded 2026-08-25).
|
||||
export async function Pricing() {
|
||||
const [product, shipping, defaultTaxRate, kleinunternehmer] = await Promise.all([
|
||||
const [product, shipping, defaultTaxRate, kleinunternehmer, trustBadges] = await Promise.all([
|
||||
getProductBySlug("stift-kugelschreiber"),
|
||||
getShippingSettings(),
|
||||
getDefaultTaxRatePercent(),
|
||||
getKleinunternehmer(),
|
||||
getCartTrustBadges(),
|
||||
]);
|
||||
if (!product) return null;
|
||||
const discount = discountPercent(product.price, product.compareAtPrice);
|
||||
@@ -55,7 +55,7 @@ export async function Pricing() {
|
||||
>
|
||||
Der Eine.
|
||||
</p>
|
||||
<p className="text-body-sm text-text-primary">Metall. Kugelschreiber. Fertig.</p>
|
||||
<p className="text-body-sm text-text-primary">Metall. Kugelschreiber. Für jeden Tag.</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3 items-start w-full lg:w-[18.75rem] lg:shrink-0">
|
||||
@@ -81,7 +81,7 @@ export async function Pricing() {
|
||||
</div>
|
||||
{anyLowStock && <p className="text-label font-bold text-warning">Nur noch wenige verfügbar</p>}
|
||||
<AddToCartButton
|
||||
label="In den Warenkorb"
|
||||
label="Der Eine. bestellen"
|
||||
className="w-full inline-flex items-center justify-center px-6 py-[0.8125rem] rounded-sm bg-brand hover:bg-brand-hover active:scale-[0.97] transition-all font-bold text-body text-text-primary text-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 focus-visible:ring-offset-bg-muted"
|
||||
productId={product.id}
|
||||
numericId={product.numericId}
|
||||
@@ -89,6 +89,21 @@ export async function Pricing() {
|
||||
maxQty={product.maxQty}
|
||||
variants={product.active ? product.variants : []}
|
||||
/>
|
||||
{/* Same content (getCartTrustBadges()) and markup as /cart's
|
||||
title-only row (CartContent.tsx) — reuses the real,
|
||||
already-vetted badge copy ("Nachhaltig verpackt" etc.)
|
||||
instead of inventing new text to pixel-match the mockup's
|
||||
placeholder wording. */}
|
||||
{trustBadges.length > 0 && (
|
||||
<div className="flex flex-wrap gap-x-8 gap-y-4 items-start w-full">
|
||||
{trustBadges.map((badge) => (
|
||||
<div key={badge.id} className="flex gap-3 items-center w-auto">
|
||||
<Image alt="" src={badge.icon} width={22} height={22} className="size-[1.375rem] shrink-0 object-contain" />
|
||||
<span className="text-body-sm text-text-primary whitespace-nowrap">{badge.title}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Reveal>
|
||||
</section>
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
import Image from "next/image";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
import { getProductBySlug } from "../../lib/payload";
|
||||
|
||||
// The brand-story section explaining the product's name. Same photo+text
|
||||
// layout as todo-cards/components/Focus.tsx (identical classes/structure,
|
||||
// reused for visual consistency rather than a one-off design) — the photo
|
||||
// is product.gallery[0], an engraving close-up ("einfach produktiv." on the
|
||||
// pen barrel) uploaded specifically for this section, see the mockup-derived
|
||||
// media uploaded 2026-08-25 (ids 88/89 replacing the earlier mismatched
|
||||
// green-pen supplier photos).
|
||||
export async function Why() {
|
||||
const product = await getProductBySlug("stift-kugelschreiber");
|
||||
const photo = product?.gallery[0] ?? product?.image ?? null;
|
||||
|
||||
// Plays the same structural role as todo-cards/components/HowItWorks.tsx (a
|
||||
// content section between Hero and the material/Pricing sections, matching
|
||||
// the site's established product-page rhythm) — but this is the brand-story
|
||||
// section explaining the product's name, so flowing prose fits better than
|
||||
// this file's former 2×2 scenario grid (replaced 2026-08-25 alongside the
|
||||
// Der Alltagsstift → Der Eine. rename).
|
||||
export function Why() {
|
||||
return (
|
||||
<section className="w-full bg-bg-base flex flex-col gap-6 items-center py-12 sm:py-16 px-[var(--layout-padding-x)]">
|
||||
<Reveal className="flex flex-col gap-5 items-start text-left max-w-2xl w-full">
|
||||
<section className="w-full bg-bg-base flex flex-col lg:flex-row gap-10 lg:gap-16 items-center py-12 md:py-16 px-[var(--layout-padding-x)]">
|
||||
{photo && (
|
||||
<Reveal className="group relative w-full lg:w-[42%] lg:shrink-0 aspect-[480/230] rounded-md overflow-hidden">
|
||||
<Image
|
||||
src={photo}
|
||||
alt="Gravur „einfach produktiv.“ auf dem Stiftkorpus"
|
||||
fill
|
||||
sizes="(min-width: 1024px) 42vw, 100vw"
|
||||
className="object-cover transition-transform duration-500 group-hover:scale-105"
|
||||
/>
|
||||
</Reveal>
|
||||
)}
|
||||
<Reveal className="flex flex-col gap-6 items-start flex-1 min-w-0 w-full" delay={0.1}>
|
||||
<p
|
||||
className="font-semibold text-h-emphasis text-text-primary"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
@@ -17,16 +34,16 @@ export function Why() {
|
||||
Warum „Der Eine.“?
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Weil du nicht alles gleichzeitig machen kannst.
|
||||
Unsere ToDo-Karten helfen dir, dich auf das zu konzentrieren, was heute wichtig ist.
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Aufschreiben hilft dabei, aus all den Dingen im Kopf das herauszuholen, was gerade wichtig ist. Und manchmal ist das eben nur: die eine Sache.
|
||||
Der Stift greift diese Idee auf.
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Daher steht auf der einen Seite des Stifts <strong className="font-semibold text-text-primary">Der Eine.</strong> und auf der anderen <strong className="font-semibold text-text-primary">einfach produktiv.</strong>
|
||||
Auf der einen Seite steht <strong className="font-semibold text-text-primary">„Der Eine.“</strong>, auf der anderen <strong className="font-semibold text-text-primary">„einfach produktiv.“</strong>
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Mehr steckt eigentlich nicht dahinter. Und vielleicht ist genau das der Punkt.
|
||||
Mehr Geschichte braucht es eigentlich nicht.
|
||||
</p>
|
||||
</Reveal>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user