Add shop, cart, versand pages and Impulse & Tipps detail page
- New /shop overview, /cart (real cart state via useSyncExternalStore), /versand (shipping policy page with TOC) and /newsletter detail page - Cart: quantity/removal, order summary, related-products cross-sell with randomized picks, VersandModal quick-reference instead of navigating away, MwSt. disclosure next to unit prices - Add-to-cart UX: inline success feedback (green state) plus a fly-to-navbar-cart-icon animation (CartFlyProvider) with a delayed badge count-up; AddToCartButton no longer navigates straight to /cart - Shared lib/products.ts catalog and lib/shipping.ts constants (cost, free-shipping threshold, handling/transit days) so cart, trust badges and the versand page can never drift apart - Fix Navbar smooth-scroll easing (ease-out instead of ease-in-out, no more perceived start delay); compress newsletter modal photo 2.4MB -> 85KB to fix first-open jank
This commit is contained in:
+75
-39
@@ -178,47 +178,70 @@ export default function ChallengePage() {
|
||||
{/* ── Hero ── */}
|
||||
<section className="w-full flex items-stretch overflow-hidden" style={{ minHeight: "32rem" }}>
|
||||
|
||||
{/* Left: text + form */}
|
||||
<Reveal className="flex flex-col justify-center gap-6 px-8 lg:px-[5rem] py-10 lg:py-14 w-full lg:w-[52%] lg:shrink-0">
|
||||
{/* Left: text + form. justify-center removed from here — the
|
||||
outer section's items-stretch already makes this column full
|
||||
height, but centering its whole content (breadcrumb included)
|
||||
made the breadcrumb's Y position drift depending on this
|
||||
page's content length vs. /todo-cards's and /newsletter's own
|
||||
(different) content lengths. Same fix as both of those. */}
|
||||
{/* pt-10 md:pt-12 (not the original py-10 lg:py-14's top value) —
|
||||
matches /todo-cards's and /newsletter's breadcrumb top offset
|
||||
exactly; pb-10 lg:pb-14 keeps this page's original bottom
|
||||
spacing, which was never the inconsistent part. */}
|
||||
<Reveal className="flex flex-col gap-6 px-8 lg:px-[5rem] pt-10 md:pt-12 pb-10 lg:pb-14 w-full lg:w-[52%] lg:shrink-0">
|
||||
|
||||
{/* Breadcrumb */}
|
||||
<p className="text-[0.875rem] text-[#888] flex items-center gap-1.5">
|
||||
<Link href="/" className="hover:text-[#f6a701] transition-colors">Startseite</Link>
|
||||
{/* Breadcrumb — 3 levels (Startseite › Werkzeuge ›
|
||||
7-Tage-Challenge), matching /todo-cards's and
|
||||
/newsletter's pattern; was missing "Werkzeuge" in the
|
||||
middle. Also switched from this page's hardcoded hex
|
||||
colors to the shared text-body-sm/text-text-muted/
|
||||
text-text-primary tokens the other two breadcrumbs use —
|
||||
text-body-sm is 0.875rem, identical to the old literal
|
||||
value, so this is a pure consistency fix, not a visual
|
||||
change. Deliberately NOT part of the centered block below. */}
|
||||
<p className="text-body-sm text-text-muted flex items-center gap-2">
|
||||
<Link href="/" className="hover:text-brand transition-colors">Startseite</Link>
|
||||
<span>›</span>
|
||||
<span className="text-[#222221]">7-Tage-Challenge</span>
|
||||
<Link href="/#werkzeuge" className="hover:text-brand transition-colors">Werkzeuge</Link>
|
||||
<span>›</span>
|
||||
<span className="text-text-primary">7-Tage-Challenge</span>
|
||||
</p>
|
||||
|
||||
{/* Headline */}
|
||||
<h1
|
||||
className="font-semibold text-[#222221] leading-[1.15]"
|
||||
style={{ fontFamily: "var(--font-lora)", fontSize: "clamp(2.25rem, 5vw, 3.75rem)" }}
|
||||
>
|
||||
7 Tage.<br />
|
||||
Mehr Klarheit.<br />
|
||||
Weniger Stress.
|
||||
</h1>
|
||||
{/* Everything else — centered in the remaining vertical space,
|
||||
same fix as /todo-cards's and /newsletter's Hero sections. */}
|
||||
<div className="flex flex-col gap-6 flex-1 justify-center">
|
||||
{/* Headline */}
|
||||
<h1
|
||||
className="font-semibold text-[#222221] leading-[1.15]"
|
||||
style={{ fontFamily: "var(--font-lora)", fontSize: "clamp(2.25rem, 5vw, 3.75rem)" }}
|
||||
>
|
||||
7 Tage.<br />
|
||||
Mehr Klarheit.<br />
|
||||
Weniger Stress.
|
||||
</h1>
|
||||
|
||||
{/* Subtitle */}
|
||||
<p className="text-[1rem] text-[#444] leading-[1.6] max-w-[30rem]">
|
||||
Die 7-Tage-Challenge für deinen klaren Kopf und mehr Struktur im Alltag.
|
||||
</p>
|
||||
{/* Subtitle */}
|
||||
<p className="text-[1rem] text-[#444] leading-[1.6] max-w-[30rem]">
|
||||
Die 7-Tage-Challenge für deinen klaren Kopf und mehr Struktur im Alltag.
|
||||
</p>
|
||||
|
||||
{/* Checklist */}
|
||||
<ul className="flex flex-col gap-2">
|
||||
{[
|
||||
"7 kurze Impulse – direkt in dein Postfach",
|
||||
"Praktisch, umsetzbar und alltagstauglich",
|
||||
"Für mehr Fokus, Ruhe und Klarheit",
|
||||
].map((item) => (
|
||||
<li key={item} className="flex items-start gap-2 text-[#222221] text-[0.95rem]">
|
||||
<Check />
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{/* Checklist */}
|
||||
<ul className="flex flex-col gap-2">
|
||||
{[
|
||||
"7 kurze Impulse – direkt in dein Postfach",
|
||||
"Praktisch, umsetzbar und alltagstauglich",
|
||||
"Für mehr Fokus, Ruhe und Klarheit",
|
||||
].map((item) => (
|
||||
<li key={item} className="flex items-start gap-2 text-[#222221] text-[0.95rem]">
|
||||
<Check />
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{/* Email form */}
|
||||
<EmailCapture />
|
||||
{/* Email form */}
|
||||
<EmailCapture />
|
||||
</div>
|
||||
</Reveal>
|
||||
|
||||
{/* Right: hero image with badge — group + scale-105 on hover,
|
||||
@@ -330,8 +353,14 @@ export default function ChallengePage() {
|
||||
</section>
|
||||
|
||||
{/* ── Was andere sagen ── */}
|
||||
{/* max-w-[1600px], not this page's other sections' 1280px — a
|
||||
deliberate compromise with /todo-cards's and /newsletter's
|
||||
unbounded fluid width, so all three testimonial sections cap
|
||||
at the same width instead of Challenge's reading narrower on
|
||||
wide viewports. Only this one section's cap changed, not the
|
||||
rest of the page. */}
|
||||
<section className="bg-white w-full py-14 lg:py-20">
|
||||
<div className="px-8 lg:px-[5rem] max-w-[1280px] mx-auto flex flex-col gap-10">
|
||||
<div className="px-8 lg:px-[5rem] max-w-[1600px] mx-auto flex flex-col gap-10">
|
||||
|
||||
<Reveal
|
||||
className="font-semibold text-[#222221] text-center"
|
||||
@@ -340,16 +369,23 @@ export default function ChallengePage() {
|
||||
Was andere sagen
|
||||
</Reveal>
|
||||
|
||||
{/* Same micro-interactions as /todo-cards's identically-styled
|
||||
testimonial cards (kept in sync deliberately): hover-lift on
|
||||
{/* Same style + micro-interactions as /todo-cards's and
|
||||
/newsletter's identically-styled testimonial cards (kept in
|
||||
sync deliberately): decorative quote-mark, hover-lift on
|
||||
the card, avatar scale on the same hover via `group`. */}
|
||||
<RevealGroup className="flex flex-col lg:flex-row gap-6">
|
||||
{testimonials.map((t) => (
|
||||
<RevealItem
|
||||
key={t.name}
|
||||
className="group flex-1 bg-[#f5f0e8] rounded-xl p-6 flex flex-col gap-4 transition-transform duration-300 hover:-translate-y-1"
|
||||
className="group relative flex-1 bg-[#f5f0e8] rounded-xl p-6 flex flex-col gap-4 transition-transform duration-300 hover:-translate-y-1"
|
||||
>
|
||||
<p className="text-[#222221] text-[0.95rem] leading-[1.6] flex-1">{t.quote}</p>
|
||||
<span
|
||||
aria-hidden
|
||||
className="absolute top-4 right-6 font-bold text-[2.5rem] text-[#ccc] leading-none select-none"
|
||||
>
|
||||
”
|
||||
</span>
|
||||
<p className="text-[#222221] text-[0.95rem] leading-[1.6] flex-1 pr-8">{t.quote}</p>
|
||||
<div className="flex items-center gap-3">
|
||||
<img
|
||||
alt={t.name}
|
||||
|
||||
Reference in New Issue
Block a user