Add ToDo-Karten product page, fluid design tokens, and Navbar/Hero fixes

New /todo-cards page (Hero, How-it-works, Focus, Testimonials, Pricing)
built with the fluid clamp() token system (app/lib/fluid.ts) and
scroll-reveal animations (app/components/Reveal.tsx), matching styling
consistency with /challenge's testimonial section.

Navbar: page-aware active state and anchor-link navigation from any
route (not just "/"), fixed logo click to actually navigate instead of
silently rewriting the URL, fluid nav text size, custom hash-scroll
handling for cross-page anchor links.

Hero: responsive breakpoint fix for the text/image split at Tablet
widths, entrance animation for the brand's orange dot, removed a red
dot artifact from hero.png.

Also includes prior uncommitted work on About/Blog/Newsletter/Footer
and the cart lib (app/lib/cart.ts).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-19 11:34:52 +00:00
parent 35670126ca
commit e4f0c66d7b
42 changed files with 1635 additions and 363 deletions
+49 -33
View File
@@ -1,72 +1,88 @@
import { Reveal } from "./Reveal";
export function About() {
return (
<section id="ueber-bjoern" className="bg-[#111] flex items-stretch w-full">
<section id="ueber-bjoern" className="bg-bg-dark flex flex-col md:flex-row md:items-stretch w-full">
{/* Left: text content — relative + z-10 so it renders above the overlapping photo */}
<div className="flex-[1_0_0] flex flex-col gap-4 justify-center px-[5rem] py-8 min-w-0 relative z-10">
{/* Text content — relative + z-10 so it renders above the overlapping
photo at md+. Comes first in DOM at every breakpoint (no reorder
here — unlike Hero, there's no conversion CTA at stake). */}
<Reveal className="flex flex-col gap-4 justify-center px-[var(--layout-padding-x)] py-8 md:flex-[1_0_0] min-w-0 relative z-10">
{/* Large serif statement — width-constrained as per design */}
<p
className="font-semibold text-white text-[1.75rem] leading-normal w-[17.625rem]"
className="font-semibold text-bg-white text-h-section leading-normal w-[17.625rem]"
style={{ fontFamily: "var(--font-lora)" }}
>
Ich glaube nicht, dass Menschen mehr Disziplin brauchen.
</p>
{/* Quote row: script quote + golden divider + author bio */}
<div className="flex items-start justify-between w-full">
{/* Quote row: script quote / divider / author bio — side-by-side
from md+, stacked with a horizontal divider below md */}
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-6 md:gap-0 w-full">
{/* Caveat script text with signature positioned below */}
<div className="relative flex-1" style={{ minHeight: "8rem" }}>
<div
className="font-normal text-[#f6a701] text-[2.25rem]"
className="font-normal text-brand text-[2.25rem]"
style={{ fontFamily: "var(--font-caveat)", lineHeight: "2rem" }}
>
<p>Ich glaube,</p>
<p>sie brauchen&nbsp;</p>
<p>weniger Reibung.</p>
</div>
{/* Signature — absolute, sits just below the three Caveat lines (3 × 32px = 96px) */}
{/* Signature underline — hand-drawn organic stroke, sits just below the three Caveat lines (3 × 32px = 96px) */}
<div
className="absolute overflow-hidden pointer-events-none"
className="absolute pointer-events-none"
style={{ top: "6.44rem", left: "1.5rem", width: "9.375rem", height: "1.375rem" }}
>
<img
alt=""
src="/about-signature.png"
className="absolute max-w-none"
style={{ width: "101.25%", height: "118.18%", left: "-0.62%", top: "-17.72%" }}
/>
<svg viewBox="0 0 150 22" fill="none" className="w-full h-full text-brand" aria-hidden="true">
{/* Thin, near-constant-width ease-out sweep, traced from the actual
Figma signature-image raster (node 4175:150, page-home) — a single
smooth concave rise, no waviness/taper, ending ~88% across. */}
<path
d="M3,10 C20,8.3 35,6.7 50,5.4 C70,3.7 85,2.2 100,1.1 C112,0.5 122,0.3 131,0.1"
stroke="currentColor"
strokeWidth="1.3"
strokeLinecap="round"
/>
</svg>
</div>
</div>
{/* Golden vertical divider + author lines */}
<div className="flex gap-6 items-start shrink-0">
<div className="bg-[#f6a701] w-[2px] h-24 shrink-0" />
<div
className="text-white font-normal whitespace-nowrap"
style={{ fontSize: "1rem", lineHeight: "1.5rem" }}
>
<p>Björn.</p>
<p>Führungskraft.</p>
<p>Familienmensch.</p>
<p>Gründer von einfach-produktiv.</p>
</div>
{/* Divider — horizontal full-width line below md, vertical
gold line beside the author bio from md+ */}
<div className="bg-brand w-full h-px md:w-[2px] md:h-24 md:mx-6 shrink-0" />
<div
className="text-bg-white font-normal whitespace-nowrap md:shrink-0"
style={{ fontSize: "1rem", lineHeight: "1.5rem" }}
>
<p>Björn.</p>
<p>Führungskraft.</p>
<p>Familienmensch.</p>
<p>Gründer von einfach-produktiv.</p>
</div>
</div>
</div>
</Reveal>
{/* Right: author photo — overlaps text column via -ml-32, gradient covers the overlap */}
<div className="flex-[1.4_0_0] relative overflow-hidden -ml-48" style={{ minHeight: "14rem" }}>
{/* Author photo — overlaps the text column via -ml-48 from md+ only
(that overlap trick has nothing to blend into once stacked);
plain full-width photo below the text on Mobile. */}
<Reveal
className="relative overflow-hidden w-full md:flex-[1.4_0_0] md:-ml-48"
style={{ minHeight: "14rem" }}
delay={0.15}
>
<img
alt="Björn"
src="/about-author.jpg"
className="absolute inset-0 w-full h-full object-cover object-center pointer-events-none"
/>
{/* Left gradient: wide enough to cover the text-column overlap */}
<div className="absolute inset-y-0 left-0 w-72 bg-gradient-to-r from-[#111] to-transparent pointer-events-none" />
</div>
{/* Left gradient: wide enough to cover the text-column overlap — md+ only */}
<div className="hidden md:block absolute inset-y-0 left-0 w-72 bg-gradient-to-r from-bg-dark to-transparent pointer-events-none" />
</Reveal>
</section>
);