Tools cards: icon above text below lg, left-aligned above mobile

Newsletter: left-align copy above mobile, fix missing vertical padding

Tools.tsx: icon+text now stacks below lg (1024px) instead of always
being a row — a 3-up grid from sm (640px) left each card too narrow
for side-by-side icon+text through 640-1023px. Centered on true
mobile, left-aligned from sm up.

Newsletter.tsx: same left-alignment treatment (centered only on true
mobile, left-aligned from sm up). Also removed the outer card's
sm:py-0 — it relied entirely on items-center centering against the
copy column's height for top/bottom breathing room, which broke down
whenever the form column (input/checkbox/privacy note) was as tall or
taller, leaving the input and "Keine Werbung" note flush against the
card edges. py-8 now applies at every breakpoint.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-30 21:31:15 +00:00
parent 7baf8f9e24
commit 6262a8ab01
2 changed files with 22 additions and 7 deletions
+13 -4
View File
@@ -51,18 +51,27 @@ export function Newsletter({
edge-to-edge while /lebensuhr's version stayed centered and
noticeably narrower — reported 2026-07-29. */}
{/* Rounded card: cream bg, stacks below sm (moved down from the old md:) */}
<Reveal className="bg-bg-muted flex flex-col sm:flex-row gap-8 sm:gap-12 items-center px-8 py-8 sm:py-0 rounded-md w-full max-w-[1280px] mx-auto">
{/* py-8 at every breakpoint, not just below sm (was sm:py-0,
relying purely on items-center + the taller column's own
height to create top/bottom breathing room) — the form column
(input, checkbox+label, privacy note) can be as tall as or
taller than the copy column depending on viewport width, so
centering alone left no slack to distribute and the input/
"Keine Werbung" note sat flush against the card's top/bottom
edge. */}
<Reveal className="bg-bg-muted flex flex-col sm:flex-row gap-8 sm:gap-12 items-center px-8 py-8 rounded-md w-full max-w-[1280px] mx-auto">
{/* Left: copy — fixed width from sm+ so the form always gets the remaining space.
Icon+text stacked (icon on top, centered) below lg: — side by
Icon+text stacked (icon on top, centered) below sm: — side by
side they squeezed the text into a narrow column on a phone
(icon width + gap eating most of the card's inner width),
wrapping awkwardly, and the same squeeze reappeared through
the whole tablet range (640-1023px) once the outer card's own
sm:flex-row already put this copy column next to the form —
row layout for icon+text is only comfortable once there's
real room, i.e. lg+. */}
<div className="flex flex-col items-center gap-4 text-center w-full lg:flex-row lg:items-start lg:gap-8 lg:text-left sm:w-[var(--newsletter-copy-width)] lg:py-4 lg:shrink-0">
real room, i.e. lg+. Left-aligned (not centered) from sm up —
only true mobile keeps the centered treatment. */}
<div className="flex flex-col items-center gap-4 text-center w-full sm:items-start sm:text-left lg:flex-row lg:gap-8 sm:w-[var(--newsletter-copy-width)] lg:py-4 lg:shrink-0">
{/* Decorative envelope icon, tilted -4° as per design.
w-[4rem], not w-16 — this project's --spacing-16 is a
+9 -3
View File
@@ -38,7 +38,13 @@ export async function Tools() {
{tools.map((tool) => (
<RevealItem
key={tool.id}
className="sm:col-span-4 flex gap-8 items-start rounded-md transition-transform duration-300 hover:-translate-y-1"
// Icon above text below lg (1024px) — a 3-up grid from sm
// (640px) leaves each card too narrow for icon+text side by
// side through the whole 640-1023px range. Centered on true
// mobile (matches the rest of this stacked-card pattern
// site-wide), left-aligned from sm up once there's a real
// single-column card width to left-align within.
className="sm:col-span-4 flex flex-col items-center text-center gap-4 sm:items-start sm:text-left lg:flex-row lg:gap-8 rounded-md transition-transform duration-300 hover:-translate-y-1"
>
{/* Icon — uniform box, pre-flipped/rotated source asset.
size-14 (56px) is a fixed value at every width (14 isn't
@@ -69,8 +75,8 @@ export async function Tools() {
minimum text→CTA gap even for the tallest card (the one
that defines the row height, and so has ~zero leftover
space for justify-between to distribute on its own). */}
<div className="flex flex-1 flex-col self-stretch h-full justify-between items-start gap-4 min-w-0 text-text-primary [word-break:break-word]">
<div className="flex flex-col gap-4 items-start w-full">
<div className="flex flex-1 flex-col self-stretch h-full justify-between items-center text-center sm:items-start sm:text-left gap-4 min-w-0 text-text-primary [word-break:break-word]">
<div className="flex flex-col gap-4 items-center sm:items-start w-full">
<p
className="font-semibold leading-normal text-h-section w-full"
style={{ fontFamily: "var(--font-lora)" }}