3be8682e1a
Lebensuhr clock: each of the 8 points had 3 stacked text lines (age, time, vorm./nachm.) plus a leader line — too much text crammed around a small dial. Down to just the age number per point; the matching time is one glance away in the table. 3x3-system: removed the IconGrid3x3 decorative mark per explicit feedback that it added nothing.
410 lines
20 KiB
TypeScript
410 lines
20 KiB
TypeScript
import type { Metadata } from "next";
|
||
import Link from "next/link";
|
||
import { Reveal, RevealGroup, RevealItem } from "../components/Reveal";
|
||
import { Footer } from "../components/Footer";
|
||
import { StepArrow } from "../components/StepArrow";
|
||
|
||
const title = "Die Lebensuhr: Wie spät ist es in deinem Leben?";
|
||
const description =
|
||
"Wie spät ist es eigentlich in deinem Leben? Die Lebensuhr zeigt dir, wo du gerade stehst – und was in dieser Phase wirklich zählt.";
|
||
|
||
export const metadata: Metadata = {
|
||
title,
|
||
description,
|
||
alternates: { canonical: "/lebensuhr" },
|
||
openGraph: {
|
||
title,
|
||
description,
|
||
url: "/lebensuhr",
|
||
type: "article",
|
||
},
|
||
twitter: {
|
||
title,
|
||
description,
|
||
},
|
||
};
|
||
|
||
// Same "H2 with brand underline" treatment RichText.tsx's heading
|
||
// converter uses for CMS-driven content — this page is hand-written (no
|
||
// Payload post backs it, it lives at the plain /lebensuhr slug, not
|
||
// /blog/…), so the styling is copied by hand instead of shared.
|
||
function H2({ children }: { children: React.ReactNode }) {
|
||
return (
|
||
<h2
|
||
className="font-semibold text-h-small text-text-primary mt-4 first:mt-0"
|
||
style={{ fontFamily: "var(--font-lora)" }}
|
||
>
|
||
{children}
|
||
<span className="block h-[0.125rem] w-8 bg-brand mt-2" aria-hidden />
|
||
</h2>
|
||
);
|
||
}
|
||
|
||
function P({ children }: { children: React.ReactNode }) {
|
||
return <p className="text-body text-text-body">{children}</p>;
|
||
}
|
||
|
||
// Same visual language as RichText.tsx's Quote component (Caveat script +
|
||
// brand divider) — copied rather than imported since that component is
|
||
// tied to the CMS quoteLabel prop this static page has no use for.
|
||
function Quote({ children }: { children: React.ReactNode }) {
|
||
return (
|
||
<div className="relative flex items-start gap-6 w-full my-2">
|
||
<div className="w-px self-stretch bg-brand shrink-0" />
|
||
<p className="text-text-primary text-[1.75rem] leading-[1.1] flex-1" style={{ fontFamily: "var(--font-caveat)" }}>
|
||
{children}
|
||
</p>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// Same "icon-above-text, StepArrow-connected" row /7-tage-klarheits-check's
|
||
// "So funktioniert" section and /todo-cards's/newsletter's own "How it
|
||
// works" sections use — reused here for the four life phases instead of
|
||
// stacking them as plain H3 blocks.
|
||
function IconSunrise() {
|
||
return (
|
||
<svg width="44" height="40" viewBox="0 0 44 40" fill="none">
|
||
<line x1="4" y1="30" x2="40" y2="30" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<path d="M13 30a9 9 0 0 1 18 0" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="22" y1="4" x2="22" y2="10" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="9" y1="10" x2="13" y2="14" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="35" y1="10" x2="31" y2="14" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
</svg>
|
||
);
|
||
}
|
||
|
||
function IconGrowthBars() {
|
||
return (
|
||
<svg width="44" height="40" viewBox="0 0 44 40" fill="none">
|
||
<line x1="4" y1="36" x2="40" y2="36" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<rect x="7" y="25" width="7" height="11" rx="1" stroke="#f6a701" strokeWidth="2" />
|
||
<rect x="18.5" y="16" width="7" height="20" rx="1" stroke="#f6a701" strokeWidth="2" />
|
||
<rect x="30" y="6" width="7" height="30" rx="1" stroke="#f6a701" strokeWidth="2" />
|
||
</svg>
|
||
);
|
||
}
|
||
|
||
function IconSunHigh() {
|
||
return (
|
||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none">
|
||
<circle cx="20" cy="20" r="8" stroke="#f6a701" strokeWidth="2" />
|
||
<line x1="20" y1="2" x2="20" y2="7" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="20" y1="33" x2="20" y2="38" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="2" y1="20" x2="7" y2="20" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="33" y1="20" x2="38" y2="20" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="7" y1="7" x2="10.5" y2="10.5" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="29.5" y1="29.5" x2="33" y2="33" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="33" y1="7" x2="29.5" y2="10.5" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
<line x1="10.5" y1="29.5" x2="7" y2="33" stroke="#f6a701" strokeWidth="2" strokeLinecap="round" />
|
||
</svg>
|
||
);
|
||
}
|
||
|
||
// Same checkmark used by /7-tage-klarheits-check's "Das erwartet dich"
|
||
// checklist.
|
||
function Check() {
|
||
return (
|
||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" className="shrink-0 mt-1">
|
||
<path d="M3 9.5l4 4L15 4" stroke="#f6a701" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" />
|
||
</svg>
|
||
);
|
||
}
|
||
|
||
// Age boundaries — same 90-year scale as lebensuhrRows below (age/90 =
|
||
// time/24), picked so "Vormittag" ends exactly at 12:00 (age 45), which
|
||
// also happens to line up with "Mittag" as the literal midpoint between
|
||
// Vormittag and Nachmittag. Independent of lebensuhrRows (different
|
||
// breakpoints), not derived from it.
|
||
const phases = [
|
||
{
|
||
icon: <IconSunrise />,
|
||
title: "Der Morgen: Ausprobieren",
|
||
ageRange: "ca. 0–25 Jahre",
|
||
desc: "Man probiert aus, lernt, macht Fehler, entdeckt Interessen. Man muss noch nicht alles perfekt können.",
|
||
},
|
||
{
|
||
icon: <IconGrowthBars />,
|
||
title: "Der Vormittag: Aufbauen",
|
||
ageRange: "ca. 25–45 Jahre",
|
||
desc: "Jetzt wird gebaut – Gewohnheiten, Beziehungen, Fähigkeiten. Ein Leben, das sich nach dem eigenen anfühlt.",
|
||
},
|
||
{
|
||
icon: <IconSunHigh />,
|
||
title: "Der Nachmittag: Stärken",
|
||
ageRange: "ca. 45–65 Jahre",
|
||
desc: "Nicht alles neu, sondern das Bestehende wird stärker: Erfahrung zahlt sich aus, Entscheidungen fallen leichter.",
|
||
},
|
||
{
|
||
// Same icon as the morning — a rising and a setting sun both show as
|
||
// the same arc-above-the-horizon silhouette, rays above it.
|
||
icon: <IconSunrise />,
|
||
title: "Der Abend: Weitergeben",
|
||
ageRange: "ca. 65–90 Jahre",
|
||
desc: "Weniger Wachstum, mehr Bedeutung – weiterzugeben, was man aufgebaut hat.",
|
||
},
|
||
];
|
||
|
||
const questions = [
|
||
"Wie spät ist es gerade in meinem Leben?",
|
||
"Was passt eigentlich zu dieser Tageszeit?",
|
||
"Und welche Aufgabe schleppe ich noch mit mir herum, obwohl sie zu einer früheren Stunde gehört?",
|
||
];
|
||
|
||
const lebensuhrRows: [string, string][] = [
|
||
["10", "02:40 Uhr"],
|
||
["20", "05:20 Uhr"],
|
||
["30", "08:00 Uhr"],
|
||
["40", "10:40 Uhr"],
|
||
["50", "13:20 Uhr"],
|
||
["60", "16:00 Uhr"],
|
||
["70", "18:40 Uhr"],
|
||
["80", "21:20 Uhr"],
|
||
];
|
||
|
||
export default function LebensuhrPage() {
|
||
return (
|
||
<>
|
||
<main className="flex flex-col flex-1 bg-bg-base">
|
||
<Reveal className="flex flex-col gap-4 items-start pt-10 pb-8 px-[var(--layout-padding-x)] w-full max-w-[48rem] mx-auto">
|
||
<p className="flex items-center gap-2 text-body-sm text-text-muted">
|
||
<Link href="/" className="hover:text-brand transition-colors">Startseite</Link>
|
||
<span>›</span>
|
||
<span className="text-text-primary">Lebensuhr</span>
|
||
</p>
|
||
<p
|
||
className="font-semibold text-[clamp(2.25rem,1.393rem+1.786vw,3rem)] text-text-primary leading-[1.15]"
|
||
style={{ fontFamily: "var(--font-playfair)" }}
|
||
>
|
||
Die Lebensuhr: Wie spät ist es eigentlich in deinem Leben?
|
||
</p>
|
||
</Reveal>
|
||
|
||
<Reveal delay={0.1} className="w-full max-w-[48rem] mx-auto px-[var(--layout-padding-x)] pb-14 flex flex-col gap-5">
|
||
<P>Wie spät ist es eigentlich in deinem Leben?</P>
|
||
<P>Keine philosophische Frage. Eine überraschend praktische.</P>
|
||
<P>
|
||
Wir planen unsere Tage bis auf die Stunde. Wir blocken Meetings, setzen Erinnerungen und
|
||
schreiben To-do-Listen. Aber kaum jemand weiß, wie er seine aktuelle Lebensphase eigentlich
|
||
nutzen möchte.
|
||
</P>
|
||
|
||
<H2>Die Lebensuhr: Dein Leben in 24 Stunden</H2>
|
||
<P>
|
||
Stell dir vor, dein ganzes Leben wäre auf einen einzigen Tag mit 24 Stunden komprimiert.
|
||
Wirst du 90 Jahre alt, sieht das ungefähr so aus:
|
||
</P>
|
||
|
||
{/* Decorative companion to the table below, not a replacement for
|
||
it — a real 12-hour dial (1–12, like an actual clock face)
|
||
with the 8 ages plotted at their 12-hour position. Only the
|
||
age is labeled here (a version that also spelled out
|
||
time + vorm./nachm. on every point — 3 lines × 8 points —
|
||
read as clutter); the exact time for each age is one glance
|
||
down, in the table. Coordinates are hand-computed from
|
||
lebensuhrRows's own age→time pairs (hour mod 12, -90° so 12
|
||
sits at the top) — if those rows ever change, these need
|
||
updating too. */}
|
||
<div className="flex justify-center py-2">
|
||
<svg viewBox="-10 -10 440 440" className="w-full max-w-[22rem] h-auto" aria-hidden="true">
|
||
<circle cx="210" cy="210" r="150" stroke="var(--color-border)" strokeWidth="1.5" fill="none" />
|
||
{[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((h) => {
|
||
const deg = (h / 12) * 360 - 90;
|
||
const rad = (deg * Math.PI) / 180;
|
||
const major = h % 3 === 0;
|
||
const rIn = major ? 140 : 145;
|
||
const x1 = 210 + rIn * Math.cos(rad), y1 = 210 + rIn * Math.sin(rad);
|
||
const x2 = 210 + 150 * Math.cos(rad), y2 = 210 + 150 * Math.sin(rad);
|
||
return <line key={h} x1={x1} y1={y1} x2={x2} y2={y2} stroke="var(--color-border)" strokeWidth={major ? 2 : 1.5} />;
|
||
})}
|
||
{/* The dial's own numerals, 1–12, same as a real clock face. */}
|
||
{([
|
||
[1, 292.5, 67.1, "start"],
|
||
[2, 352.9, 127.5, "start"],
|
||
[3, 375, 210, "start"],
|
||
[4, 352.9, 292.5, "start"],
|
||
[5, 292.5, 352.9, "start"],
|
||
[6, 210, 375, "middle"],
|
||
[7, 127.5, 352.9, "end"],
|
||
[8, 67.1, 292.5, "end"],
|
||
[9, 45, 210, "end"],
|
||
[10, 67.1, 127.5, "end"],
|
||
[11, 127.5, 67.1, "end"],
|
||
[12, 210, 45, "middle"],
|
||
] as [number, number, number, "start" | "middle" | "end"][]).map(([h, x, y, anchor]) => (
|
||
<text key={h} x={x} y={y} textAnchor={anchor} dominantBaseline="middle" className="fill-text-muted" style={{ fontSize: 12, fontWeight: 600 }}>
|
||
{h}
|
||
</text>
|
||
))}
|
||
{/* One dot per lebensuhrRows entry, at its 12h-dial position
|
||
(hour mod 12), labeled with just the age. */}
|
||
{([
|
||
[10, 308.5, 192.6, 332.1, 188.5, "start"],
|
||
[20, 244.2, 304.0, 252.4, 326.5, "start"],
|
||
[30, 123.4, 260.0, 102.6, 272.0, "end"],
|
||
[40, 145.7, 133.4, 130.3, 115.0, "end"],
|
||
[50, 274.3, 133.4, 289.7, 115.0, "start"],
|
||
[60, 296.6, 260.0, 317.4, 272.0, "start"],
|
||
[70, 175.8, 304.0, 167.6, 326.5, "end"],
|
||
[80, 111.5, 192.6, 87.9, 188.5, "end"],
|
||
] as [number, number, number, number, number, "start" | "end"][]).map(([age, dx, dy, lx, ly, anchor]) => (
|
||
<g key={age}>
|
||
<circle cx={dx} cy={dy} r="5" fill="var(--color-brand)" />
|
||
<text x={lx} y={ly} textAnchor={anchor} dominantBaseline="middle" className="fill-text-primary" style={{ fontSize: 15, fontWeight: 700 }}>
|
||
{age}
|
||
</text>
|
||
</g>
|
||
))}
|
||
<text x="210" y="196" textAnchor="middle" className="fill-text-primary" style={{ fontFamily: "var(--font-caveat)", fontSize: 30 }}>
|
||
dein
|
||
</text>
|
||
<text x="210" y="228" textAnchor="middle" className="fill-text-primary" style={{ fontFamily: "var(--font-caveat)", fontSize: 30 }}>
|
||
Leben
|
||
</text>
|
||
</svg>
|
||
</div>
|
||
<p className="text-center text-body-sm text-text-muted -mt-1">Dein Alter auf dem Zifferblatt. Die genaue Uhrzeit dazu steht unten.</p>
|
||
|
||
{/* Still a real table (explicit "Alter"/"Uhrzeit" headers — a
|
||
dot-on-a-line version tried here first read ambiguous
|
||
without them, and forced a horizontal scroll on mobile for
|
||
no gain). Dressed up with the same bg-bg-muted rounded card
|
||
the AGB sidebar and blog author box use, brand-colored
|
||
header, and zebra rows instead of a bare bordered table. */}
|
||
<div className="bg-bg-muted rounded-xl overflow-hidden">
|
||
<table className="w-full text-left border-collapse">
|
||
<thead>
|
||
<tr className="border-b-2 border-brand">
|
||
<th className="py-3 pl-6 pr-4 font-semibold text-body-sm text-text-primary uppercase tracking-wide">Alter</th>
|
||
<th className="py-3 pr-6 font-semibold text-body-sm text-text-primary uppercase tracking-wide">Uhrzeit</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{lebensuhrRows.map(([alter, uhrzeit], i) => (
|
||
<tr key={alter} className={i % 2 === 1 ? "bg-bg-base/60" : undefined}>
|
||
<td className="py-2.5 pl-6 pr-4 text-body text-text-body">{alter}</td>
|
||
<td className="py-2.5 pr-6 font-semibold text-body text-text-primary">{uhrzeit}</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<P>Und? Wie spät ist es gerade bei dir?</P>
|
||
|
||
<H2>Warum die Lebensuhr mehr zeigt als dein Alter</H2>
|
||
<P>
|
||
Viele Menschen haben gar nicht das Gefühl, zu wenig Zeit zu haben. Sie haben das Gefühl,
|
||
nicht dort zu sein, wo sie sein wollten. Zwei verschiedene Dinge. Man kann morgens schon
|
||
erschöpft sein oder abends voller Energie – die Uhr sagt nichts darüber, wie du dich fühlst,
|
||
nur wie viel Tag noch vor dir liegt.
|
||
</P>
|
||
<P>Die spannendere Frage lautet deshalb: Lebst du gerade so, wie es zu deiner Tageszeit passt?</P>
|
||
<P>
|
||
Die Lebensuhr ist dabei kein Fahrplan. Sie schreibt dir nichts vor, nur weil du an einem
|
||
bestimmten Punkt stehst – manche fangen mit 45 nochmal komplett neu an, manche bauen mit 60
|
||
ihr erstes eigenes Ding auf. Sie zeigt eine Tendenz, keine Vorschrift, und sie bewertet auch
|
||
nicht, ob du "weiter" bist als andere. Sie zeigt nur, welche Art von Aufgabe in deiner
|
||
aktuellen Phase gut zu dir passen könnte. Ein Vormittag ist schließlich auch nicht besser als
|
||
ein Abend – nur anders.
|
||
</P>
|
||
|
||
<H2>Was zu welcher Lebensphase passt</H2>
|
||
<P>
|
||
Diese Zuordnungen halten sich nicht strikt an die Uhr – manchmal probiert man am Nachmittag
|
||
nochmal etwas komplett Neues aus, manchmal gibt man schon morgens etwas weiter. Sie sind ein
|
||
Muster, kein Gesetz: Nimm dir davon, was zu deiner Situation passt.
|
||
</P>
|
||
</Reveal>
|
||
|
||
{/* Full-width StepArrow row — same pattern as /7-tage-klarheits-check's
|
||
"So funktioniert" section, reused here for the four life phases
|
||
instead of stacking them as plain headings. */}
|
||
<section className="bg-bg-muted w-full py-10 lg:py-14">
|
||
<div className="px-8 lg:px-[5rem] max-w-[1280px] mx-auto">
|
||
<RevealGroup className="flex flex-col lg:flex-row items-center lg:items-start gap-8 lg:gap-2 w-full">
|
||
{phases.flatMap((phase, i) => [
|
||
<RevealItem key={phase.title} className="group flex flex-col items-center gap-4 lg:gap-5 flex-1 min-w-0">
|
||
<div className="flex items-center justify-center w-16 h-14 shrink-0 transition-transform duration-300 group-hover:scale-110">
|
||
{phase.icon}
|
||
</div>
|
||
<div className="flex flex-col gap-1 text-center">
|
||
<p className="font-semibold text-text-primary text-[1rem]">{phase.title}</p>
|
||
<p className="font-semibold text-[0.75rem] text-brand">{phase.ageRange}</p>
|
||
<p className="text-[0.875rem] text-text-muted leading-[1.5]">{phase.desc}</p>
|
||
</div>
|
||
</RevealItem>,
|
||
i < phases.length - 1 ? (
|
||
<div key={`arrow-${i}`} className="flex items-center justify-center shrink-0 lg:mt-5">
|
||
<StepArrow className="w-8 h-8 rotate-90 lg:w-10 lg:h-4 lg:rotate-0" />
|
||
</div>
|
||
) : null,
|
||
])}
|
||
</RevealGroup>
|
||
</div>
|
||
</section>
|
||
|
||
<Reveal delay={0.1} className="w-full max-w-[48rem] mx-auto px-[var(--layout-padding-x)] pt-10 pb-14 flex flex-col gap-5">
|
||
<Quote>
|
||
Wer am Nachmittag immer wieder bei null anfängt, verschenkt oft das Wertvollste, was er
|
||
besitzt – den Zinseszins des eigenen Lebens.
|
||
</Quote>
|
||
|
||
<H2>Produktivität beginnt mit der richtigen Lebensphase</H2>
|
||
<P>
|
||
Wir behandeln oft jede Lebensphase gleich – immer schneller, immer mehr, immer weiter. Dabei
|
||
erwarten wir von einem Abend dieselbe Dynamik wie von einem frühen Morgen. Das funktioniert
|
||
weder an einem einzigen Tag noch in einem ganzen Leben.
|
||
</P>
|
||
<P>
|
||
Produktivität bedeutet für mich deshalb etwas anderes: das Richtige zur richtigen Zeit zu
|
||
tun. Nicht ständig neu anzufangen, wenn es Zeit wäre, etwas wachsen zu lassen. Nicht
|
||
krampfhaft festzuhalten, wenn es Zeit wäre, loszulassen. Und nicht auf "den richtigen
|
||
Moment" warten – du lebst bereits in ihm.
|
||
</P>
|
||
|
||
<H2>Drei Fragen für deine persönliche Lebensuhr</H2>
|
||
<P>Schau heute Abend noch mal auf deine Uhr. Nicht die am Handgelenk – deine Lebensuhr.</P>
|
||
<ul className="flex flex-col gap-3">
|
||
{questions.map((q) => (
|
||
<li key={q} className="flex items-start gap-3">
|
||
<Check />
|
||
<p className="text-body text-text-body">{q}</p>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
<P>
|
||
Vielleicht zeigt dir die Lebensuhr heute nicht, dass du dich beeilen musst – sondern dass
|
||
genau jetzt die richtige Zeit für das ist, was vor dir liegt. Manchmal reicht das schon, um
|
||
den nächsten Schritt klarer zu gehen.
|
||
</P>
|
||
|
||
{/* Same bordered CTA-card treatment as the blog's "Passend dazu"
|
||
link — more click surface and visibility than a plain inline
|
||
text link. */}
|
||
<Link
|
||
href="/7-tage-klarheits-check"
|
||
className="group flex items-center justify-between gap-4 border border-border rounded-md px-6 py-5 mt-2 hover:border-brand transition-colors"
|
||
>
|
||
<div className="flex flex-col gap-1">
|
||
<p className="font-bold text-[0.8125rem] text-brand">Nächster Schritt:</p>
|
||
<p className="font-semibold text-body text-text-primary" style={{ fontFamily: "var(--font-lora)" }}>
|
||
7-Tage-Klarheits-Check
|
||
</p>
|
||
<p className="text-body-sm text-text-muted">Ein ruhiger Einstieg, sieben Tage lang.</p>
|
||
</div>
|
||
<svg
|
||
viewBox="0 0 20 20"
|
||
className="size-4 shrink-0 text-text-primary 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>
|
||
</Reveal>
|
||
</main>
|
||
<Footer />
|
||
</>
|
||
);
|
||
}
|