Files
einfach-produktiv/app/components/Divider.tsx
T
Marco 7a3ae0ea53 Add /widerruf and /agb legal pages, fix newsletter modal scroll jank
- New /widerruf page: CMS-driven content via getLegalPage("widerruf"),
  sidebar TOC + "Nachhaltig handeln" callout, TrustRow, and a download
  card for the Muster-Widerrufsformular PDF attachment.
- New /agb page, same legal-page shell pattern as Impressum/Datenschutz.
- lib/payload.ts: getLegalPage now also resolves the optional `attachment`
  media relation (depth=1) for legal pages that have a downloadable file.
- NewsletterModal: replaced the body overflow/position scroll-lock hacks
  (which fought with the sticky Navbar and the global scroll-smooth CSS)
  with a wheel/touch event interceptor that never touches scroll position
  at all, plus `preventScroll: true` on all modal/drawer focus() calls to
  stop the browser's implicit scrollIntoView from nudging the page for
  elements near the sticky navbar's reserved scroll-padding-top zone.
  Same preventScroll fix applied to VersandModal and the Navbar mobile
  drawer for consistency.
- globals.css: scrollbar-gutter: stable, so a modal's overflow:hidden
  lock never causes a scrollbar-width layout shift.
- Divider: stagger its reveal animation slightly (delay 0.3s) behind the
  section above it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 19:57:28 +00:00

72 lines
2.3 KiB
TypeScript

import { Reveal } from "./Reveal";
function Word({ children }: { children: string }) {
return (
<p
className="font-bold leading-normal text-text-primary text-h2 whitespace-nowrap"
style={{ fontFamily: "var(--font-caveat)" }}
>
{children}
</p>
);
}
function Arrow() {
return (
<div className="flex items-center justify-center shrink-0">
<div className="-scale-y-100 rotate-180">
<div className="relative" style={{ height: "var(--divider-arrow-h)", width: "var(--divider-arrow-w)" }}>
<img alt="" src="/icon-separator.svg" className="absolute inset-0 w-full h-full" />
</div>
</div>
</div>
);
}
export function Divider() {
return (
<Reveal
delay={0.3}
className="flex items-center justify-center flex-wrap gap-x-8 gap-y-3 pb-5 pt-12 px-[var(--layout-padding-x)] w-full bg-bg-base text-center"
>
{/* Word + its trailing icon are grouped into one shrink-0 flex unit
so flex-wrap only ever breaks BETWEEN pairs, never leaving an
arrow stranded alone on its own line — the arrows are always
visible now (previously hidden below md: entirely to sidestep
that exact problem), this fixes the root cause instead. */}
<div className="flex items-center gap-8 shrink-0">
<Word>Klarheit</Word>
<Arrow />
</div>
<div className="flex items-center gap-8 shrink-0">
<Word>Fokus</Word>
<Arrow />
</div>
<div className="flex items-center gap-8 shrink-0">
<Word>Entlastung</Word>
{/* Sparkle icon — sizes now fluid (--divider-sparkle-*) to match
the text-h2 words next to it, previously hard rem values that
stayed visually static while the words scaled. */}
<div
className="flex items-center justify-center"
style={{ height: "var(--divider-sparkle-h)", width: "var(--divider-sparkle-w)" }}
>
<div style={{ rotate: "4.6deg" }}>
<div
className="relative"
style={{ height: "var(--divider-sparkle-inner-h)", width: "var(--divider-sparkle-inner-w)" }}
>
<img alt="" src="/icon-separator-right.svg" className="absolute inset-0 w-full h-full" />
</div>
</div>
</div>
</div>
</Reveal>
);
}