Files
einfach-produktiv/app/not-found.tsx
T
Marco cc935420ec Move structural breakpoint to 640px, shorten Hero heading
Tablet layout (768-1023px) hit the md: grid switch exactly where the
fluid clamp() tokens were already at their floor, leaving no room to
shrink. Moves the fluid floor and structural breakpoint down together
to sm: (640px) so real tablets always get the fluid, desktop-like
structure; consolidates the ad-hoc md:+lg: patchwork in Hero/About/
Newsletter/Footer/Tools back onto one line, leaving documented lg:
exceptions where content genuinely doesn't fit yet. Also shortens the
Hero heading to a single sentence with no trailing period (the brand's
orange dot already renders one, animated).
2026-07-29 10:49:56 +00:00

213 lines
9.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Metadata } from "next";
import Link from "next/link";
import Image from "next/image";
import { Reveal, RevealGroup, RevealItem } from "./components/Reveal";
import { Footer } from "./components/Footer";
import { TrustRow } from "./components/TrustRow";
export const metadata: Metadata = {
title: "Seite nicht gefunden",
description: "Diese Seite ist gerade nicht dort, wo sie sein sollte.",
robots: { index: false, follow: true },
};
const helpLinks = [
{
href: "/",
title: "Startseite",
desc: "Zurück zu den wichtigsten Inhalten und Angeboten.",
cta: "Zur Startseite",
icon: (
<svg viewBox="0 0 24 24" className="size-6" fill="none" aria-hidden="true">
<path
d="M4 11.5 12 4l8 7.5M6 9.5V20h5v-5.5h2V20h5V9.5"
stroke="currentColor"
strokeWidth="1.6"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
),
},
{
href: "/blog",
title: "Im Blog stöbern",
desc: "Lass dich von Impulsen, Methoden und Gedanken inspirieren.",
cta: "Zum Blog",
icon: (
<svg viewBox="0 0 24 24" className="size-6" fill="none" aria-hidden="true">
<path
d="M6 3.5h9.5L20 8v12.5a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-16a1 1 0 0 1 1-1Z"
stroke="currentColor"
strokeWidth="1.6"
strokeLinejoin="round"
/>
<path d="M8.5 9.5h7M8.5 13h7M8.5 16.5h4.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" />
</svg>
),
},
{
href: "/#werkzeuge",
title: "Werkzeuge entdecken",
desc: "Praktische Tools für mehr Fokus, Struktur und Klarheit.",
cta: "Zu den Werkzeugen",
icon: (
<svg viewBox="0 0 24 24" className="size-6" fill="none" aria-hidden="true">
<path
d="M4 9.5h16a1 1 0 0 1 1 1V19a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-8.5a1 1 0 0 1 1-1Z"
stroke="currentColor"
strokeWidth="1.6"
strokeLinejoin="round"
/>
<path
d="M8.5 9.5V7a2 2 0 0 1 2-2h3a2 2 0 0 1 2 2v2.5"
stroke="currentColor"
strokeWidth="1.6"
strokeLinejoin="round"
/>
</svg>
),
},
];
export default function NotFound() {
return (
<>
<main className="flex flex-col flex-1 bg-bg-base">
{/* Hero — eyebrow / Ups. / subheading / copy / CTA, sticky note beside it */}
<div className="flex flex-col lg:flex-row gap-12 lg:gap-16 items-center pt-16 pb-20 px-[var(--layout-padding-x)] w-full">
<Reveal className="flex flex-col gap-4 items-start w-full lg:flex-1 max-w-[32rem]">
<p className="font-semibold text-body-sm text-brand tracking-wide">404 Seite nicht gefunden</p>
<p
className="font-semibold text-[3.5rem] leading-[1.05] text-text-primary"
style={{ fontFamily: "var(--font-lora)" }}
>
Ups.
</p>
<p
className="font-semibold text-h-feature text-text-primary"
style={{ fontFamily: "var(--font-lora)" }}
>
Diese Seite ist gerade nicht dort, wo sie sein sollte.
</p>
<div className="h-[0.125rem] w-8 bg-brand" />
<p className="text-body text-text-muted">
Vielleicht wurde sie verschoben, umbenannt oder es hat sich ein kleiner Tippfehler eingeschlichen.
</p>
<p className="text-body text-text-muted">Aber kein Problem wir bringen dich gerne zurück auf Kurs.</p>
<Link
href="/"
className="group flex items-center gap-2 mt-2 px-7 py-4 rounded-sm bg-brand text-h4 font-bold text-text-primary hover:bg-brand-hover active:scale-[0.97] transition-all"
>
Zur Startseite
<svg
viewBox="0 0 20 20"
className="size-4 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="1.75" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</Link>
</Reveal>
{/* Sticky note — real asset exported straight from the built
Figma page (page-404, node 4693:382), not a hand-coded
approximation — matches project convention of using the
actual photographed/rendered note rather than recreating its
handwriting in CSS. */}
<Reveal delay={0.15} className="w-full lg:flex-1 flex items-center justify-center">
<Image
alt="Sticky Note: 404. Nicht hier. Aber dein Ziel ist sicher nicht weit."
src="/404-sticky-note.png"
width={600}
height={689}
sizes="(min-width: 1024px) 22rem, 100vw"
className="w-full max-w-[22rem] rotate-2 hover:rotate-0 transition-transform duration-300"
/>
</Reveal>
</div>
{/* Help links */}
<div className="flex flex-col gap-10 items-center pb-16 px-[var(--layout-padding-x)] w-full">
<Reveal className="flex flex-col items-center gap-2">
<p
className="font-semibold text-h-small text-text-primary"
style={{ fontFamily: "var(--font-lora)" }}
>
Vielleicht hilft dir das weiter:
</p>
<div className="h-[0.125rem] w-8 bg-brand" />
</Reveal>
<RevealGroup className="grid grid-cols-1 sm:grid-cols-3 gap-10 sm:gap-8 w-full max-w-[64rem] divide-y sm:divide-y-0 sm:divide-x divide-border">
{helpLinks.map((link) => (
<RevealItem
key={link.href}
className="group flex flex-col items-center text-center gap-3 pt-10 sm:pt-0 first:pt-0 px-4 transition-transform duration-200 hover:-translate-y-1"
>
<div className="flex size-14 items-center justify-center rounded-full bg-bg-muted text-brand transition-transform duration-300 group-hover:scale-110">
{link.icon}
</div>
<p className="font-semibold text-body text-text-primary">{link.title}</p>
<p className="text-body-sm text-text-muted">{link.desc}</p>
<Link href={link.href} className="flex items-center gap-1.5 text-body-sm font-semibold text-text-primary hover:underline">
{link.cta}
<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>
</Link>
</RevealItem>
))}
</RevealGroup>
</div>
{/* Testimonial band — photo bleeds to the viewport edge, gradient
fade into bg-base on its trailing edge instead of a hard cut,
same idea as page-bestellbestaetigung's photo+quote pattern
(see that page's own comment for the fixed-h-/-inset-1
reasoning — a min-height alone lets whichever column has more
content stretch the row past what the other side visually
fills, and a plain inset-0 image can show a hairline gap at
the container edge). 404-testimonial-photo.jpg is cropped
directly from the actual mockup pixels
(mockups/einfach-produktiv_mockup_404.png) rather than
reusing an unrelated existing asset — same real-photo
extraction convention the Figma rebuild used, just done on
the flat mockup image instead of in Figma. */}
<Reveal className="relative w-full flex items-stretch h-[14rem] sm:h-[16rem] bg-bg-muted overflow-hidden">
<div className="relative w-full sm:w-[45%] shrink-0">
<Image
alt=""
src="/404-testimonial-photo.jpg"
width={810}
height={291}
sizes="(min-width: 640px) 45vw, 100vw"
className="absolute -inset-1 w-[calc(100%+0.5rem)] h-[calc(100%+0.5rem)] object-cover"
/>
<div className="hidden sm:block absolute inset-y-0 right-0 w-40 bg-gradient-to-l from-bg-muted to-transparent" />
</div>
<div className="flex-1 flex flex-col justify-center gap-3 px-8 md:px-16 py-6">
<p
className="font-semibold text-h-section text-text-primary leading-[1.3] max-w-[28rem]"
style={{ fontFamily: "var(--font-lora)" }}
>
Manchmal führt der falsche Weg zu neuen klaren Gedanken.
</p>
<div className="h-[0.125rem] w-8 bg-brand" />
<p className="text-body text-text-muted">Björn</p>
</div>
</Reveal>
<TrustRow />
</main>
<Footer />
</>
);
}