Revert Der Eine. mockup redesign, keep only 2 targeted changes
The full mockup-driven redesign (Banner/Lifestyle sections, restyled
Focus/Why/Pricing) was more than asked for — reverted back to the
pre-redesign version (Hero/Focus/Why exactly match commit 13fb37e), with
only the two changes actually requested applied on top:
- Focus.tsx ("Was kann er?"): dropped the product photo, plain text
section now — a second product shot here was redundant with Hero's own.
- Pricing.tsx (bottom price/buy bar) replaced by PasstDazu.tsx, a
"Passt dazu" cross-sell card linking to ToDo-Karten — same markup as
blog/[slug]/page.tsx's own related-product card, hardcoded to
"todo-karten" the same way Hero.tsx hardcodes "stift-kugelschreiber".
Kept the Payload product.image/gallery repointed at the mockup-derived
photos (ids 88/89) rather than reverting those too — the previous gallery
was mismatched stock photos of a different-colored pen, an independent
correction from the layout redesign.
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
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,69 +1,41 @@
|
||||
import { Reveal, RevealGroup, RevealItem } from "../../components/Reveal";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
|
||||
// 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).
|
||||
// "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.
|
||||
const items = [
|
||||
{ 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." },
|
||||
{ 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." },
|
||||
];
|
||||
|
||||
// No product photo here (removed 2026-08-25 — feedback: another product
|
||||
// shot in this section was redundant with Hero's own gallery). Plain
|
||||
// full-width text block instead of the earlier photo+text two-column
|
||||
// layout.
|
||||
export function Focus() {
|
||||
return (
|
||||
<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 className="w-full bg-bg-base py-12 md:py-16 px-[var(--layout-padding-x)]">
|
||||
<Reveal className="flex flex-col gap-6 items-start max-w-[48rem] mx-auto">
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,23 @@ import { getProductBySlug, getShippingSettings, getDefaultTaxRatePercent, getKle
|
||||
import { formatPrice, discountPercent } from "../../lib/format";
|
||||
import { effectiveTaxRate } from "../../lib/cartTotals";
|
||||
|
||||
// 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.
|
||||
// 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>
|
||||
);
|
||||
}
|
||||
|
||||
// Same "compact early teaser + delivery-time repeated next to every buy
|
||||
// button" reasoning as TodoKartenHero.tsx.
|
||||
@@ -43,17 +56,34 @@ export async function Hero() {
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-6 items-start w-full flex-1 lg:justify-center">
|
||||
<p
|
||||
className="font-semibold text-h-page text-text-primary"
|
||||
style={{ fontFamily: "var(--font-playfair)" }}
|
||||
>
|
||||
Der Eine<span className="text-brand">.</span>
|
||||
</p>
|
||||
<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">
|
||||
Der Kugelschreiber zu unseren ToDo-Karten. Aus Metall, mit schwarzer Mine und „Der Eine.“ auf der Seite.
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
<div className="flex flex-col gap-1 items-start">
|
||||
{product && (
|
||||
<div className="flex gap-2 items-baseline">
|
||||
@@ -80,7 +110,7 @@ export async function Hero() {
|
||||
|
||||
{product && (
|
||||
<AddToCartButton
|
||||
label="In den Warenkorb"
|
||||
label="Der Eine. bestellen"
|
||||
productId={product.id}
|
||||
numericId={product.numericId}
|
||||
outOfStock={!product.active || product.outOfStock}
|
||||
@@ -91,10 +121,13 @@ export async function Hero() {
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
{/* 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. */}
|
||||
{/* 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. */}
|
||||
{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">
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
import { getProductBySlug } from "../../lib/payload";
|
||||
|
||||
// Replaces the page's final price/buy bar entirely (explicit choice —
|
||||
// Hero.tsx already has the primary buy CTA, this page doesn't need a
|
||||
// second one at the very bottom too). Same "Passend dazu" card markup as
|
||||
// blog/[slug]/page.tsx's own related-product card (that one is driven by
|
||||
// Posts.relatedProduct, a per-post CMS field; this page hardcodes
|
||||
// "todo-karten" directly, same as Hero.tsx already hardcodes
|
||||
// "stift-kugelschreiber" — a fixed cross-sell, not a general relation).
|
||||
export async function PasstDazu() {
|
||||
const product = await getProductBySlug("todo-karten");
|
||||
if (!product?.href) return null;
|
||||
|
||||
return (
|
||||
<section className="w-full bg-bg-base px-[var(--layout-padding-x)] py-12 sm:py-16">
|
||||
<Reveal className="max-w-[48rem] mx-auto">
|
||||
<Link
|
||||
href={product.href}
|
||||
className="group flex items-center gap-4 sm:gap-6 border border-border rounded-md px-5 py-5 sm:px-9 sm:py-7 hover:border-brand transition-colors"
|
||||
>
|
||||
<div className="relative w-16 h-[4.6875rem] shrink-0 rounded-sm overflow-hidden">
|
||||
<Image alt="" src={product.image} fill sizes="64px" className="object-cover" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0 flex flex-col gap-2.5">
|
||||
<p className="font-bold text-[0.8125rem] text-brand">Passt dazu:</p>
|
||||
<div className="flex flex-col sm:flex-row sm:items-end sm:justify-between gap-4 w-full">
|
||||
<div className="flex flex-col gap-2 items-start w-full sm:w-[19rem] sm:shrink-0">
|
||||
<p
|
||||
className="font-semibold text-[1.375rem] text-text-primary sm:whitespace-nowrap"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
>
|
||||
{product.name}
|
||||
</p>
|
||||
<p className="text-[0.9375rem] text-text-muted leading-[1.45]">{product.description}</p>
|
||||
</div>
|
||||
<span className="flex items-center gap-1.5 font-bold text-[0.875rem] text-text-primary whitespace-nowrap mt-1 sm:mt-0">
|
||||
Entdecken
|
||||
<svg
|
||||
viewBox="0 0 20 20"
|
||||
className="size-3.5 transition-transform duration-200 group-hover:translate-x-1"
|
||||
fill="none"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M4 10h12m0 0-5-5m5 5-5 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</Reveal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
import Image from "next/image";
|
||||
import { AddToCartButton } from "../../components/AddToCartButton";
|
||||
import { Reveal } from "../../components/Reveal";
|
||||
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 (the mockup-derived
|
||||
// hero crop, see media ids 88/89 uploaded 2026-08-25).
|
||||
export async function Pricing() {
|
||||
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);
|
||||
const taxRate = effectiveTaxRate(product, defaultTaxRate);
|
||||
const fullyOutOfStock =
|
||||
!product.active || (product.variants.length > 0 ? product.variants.every((v) => v.outOfStock) : product.outOfStock);
|
||||
const anyLowStock = product.active && (product.variants.length > 0 ? product.variants.some((v) => v.lowStock) : product.lowStock);
|
||||
|
||||
return (
|
||||
<section className="w-full bg-bg-base px-[var(--layout-padding-x)] py-8">
|
||||
<Reveal className="bg-bg-muted rounded-md flex flex-col lg:flex-row gap-8 lg:gap-12 items-center p-6 lg:pl-8 lg:pr-10 lg:py-6">
|
||||
<div className="group relative w-full lg:w-[15.625rem] lg:shrink-0 aspect-square rounded-sm overflow-hidden bg-bg-base">
|
||||
<Image
|
||||
src={product.image}
|
||||
alt="Der Eine."
|
||||
fill
|
||||
sizes="(min-width: 1024px) 250px, 100vw"
|
||||
className="object-contain p-4 transition-transform duration-500 group-hover:scale-105"
|
||||
/>
|
||||
{fullyOutOfStock ? (
|
||||
<span className="absolute top-3 left-3 rounded-full bg-text-muted px-2.5 py-1 text-label font-bold text-bg-base">
|
||||
Ausverkauft
|
||||
</span>
|
||||
) : (
|
||||
discount !== null && (
|
||||
<span className="absolute top-3 left-3 rounded-full bg-brand px-2.5 py-1 text-label font-bold text-text-primary">
|
||||
-{discount}%
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-3 items-start flex-1 min-w-0 w-full">
|
||||
<p
|
||||
className="font-semibold text-h-small text-text-primary"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
>
|
||||
Der Eine.
|
||||
</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">
|
||||
<div className="flex flex-col gap-1 items-start">
|
||||
<div className="flex gap-2 items-baseline">
|
||||
{discount !== null && (
|
||||
<p className="text-body text-text-muted line-through">{formatPrice(product.compareAtPrice!)}</p>
|
||||
)}
|
||||
<p className="font-bold text-h3 text-text-primary">{formatPrice(product.price)}</p>
|
||||
</div>
|
||||
<p className="text-label text-text-muted">
|
||||
{kleinunternehmer
|
||||
? product.noShippingCost
|
||||
? "Keine Versandkosten"
|
||||
: "zzgl. Versand"
|
||||
: `inkl. ${taxRate}% MwSt. ${product.noShippingCost ? "– keine Versandkosten" : "zzgl. Versand"}`}
|
||||
</p>
|
||||
{!product.noShippingCost && (
|
||||
<p className="text-label text-text-muted">
|
||||
Lieferzeit: {shipping.totalDays.min}–{shipping.totalDays.max} Werktage innerhalb Deutschlands
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{anyLowStock && <p className="text-label font-bold text-warning">Nur noch wenige verfügbar</p>}
|
||||
<AddToCartButton
|
||||
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}
|
||||
outOfStock={!product.active || product.outOfStock}
|
||||
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,32 +1,15 @@
|
||||
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 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}>
|
||||
<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">
|
||||
<p
|
||||
className="font-semibold text-h-emphasis text-text-primary"
|
||||
style={{ fontFamily: "var(--font-lora)" }}
|
||||
@@ -34,16 +17,16 @@ export async function Why() {
|
||||
Warum „Der Eine.“?
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Unsere ToDo-Karten helfen dir, dich auf das zu konzentrieren, was heute wichtig ist.
|
||||
Weil du nicht alles gleichzeitig machen kannst.
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Der Stift greift diese Idee auf.
|
||||
Aufschreiben hilft dabei, aus all den Dingen im Kopf das herauszuholen, was gerade wichtig ist. Und manchmal ist das eben nur: die eine Sache.
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
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>
|
||||
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>
|
||||
</p>
|
||||
<p className="text-body text-text-body">
|
||||
Mehr Geschichte braucht es eigentlich nicht.
|
||||
Mehr steckt eigentlich nicht dahinter. Und vielleicht ist genau das der Punkt.
|
||||
</p>
|
||||
</Reveal>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user