Commit Graph

44 Commits

Author SHA1 Message Date
Marco c64902c381 Rename /lebensuhr to /7-tage-klarheits-check, update CTA/content copy
Renames the route, its canonical/OG metadata, Navbar's active-route
list, and the testimonials page filter to match. Also updates CTA
copy ("Klarheits-Check starten"), the "So funktioniert" heading, the
"3. Umsetzen" step text, and the breadcrumb label.
2026-08-26 15:04:03 +00:00
Marco 13fb37eb5e Rename Der Alltagsstift back to Der Eine., move route to /der-eine
New copy throughout (hero, "Was kann er?", the "Warum Der Eine.?" brand-story
section replacing the old phone-vs-pen scenario grid, final CTA) plus the
Payload product's name/detailHref updated to match (done directly via psql,
no Payload admin API key available — see reference_payload_direct_db_access).
2026-08-25 12:36:03 +00:00
Marco e49dacf057 Fix search overlay CSS trap and blog filter navigation race
SearchOverlay was rendered as a <header> descendant, so the header's
conditional backdrop-blur-md (once scrolled) made it the containing
block for the overlay's fixed positioning, clipping the opaque
background to the header's height and letting page content show
through underneath. Now rendered as a header sibling, same pattern
already used for NewsletterModal.

Blog category chips are now a client component gating navigation
behind useTransition, disabling the chips while a navigation is
pending so rapid clicks can't fire overlapping RSC navigations that
commit out of order and briefly show an empty result.
2026-08-01 06:17:09 +00:00
Marco 8b636bef25 Add the same badge pulse animation to the wishlist icon as the cart icon
Same mount-guard pattern as CartLink's own pulse fix — useWishlist()'s
count only fills in after its client-side fetch resolves, so without the
guard this would have pulsed on every page load too, not just a real
add/remove during the session. Fires on either direction (add or
remove) since the wishlist has no separate "flying" animation like the
cart's ball-to-icon effect to lean on instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018unaXmuzVA8ct1b6WoyP1U
2026-07-31 22:54:42 +00:00
Marco 7c26bf7b7c Fix cart-badge false pulse, blog hero-card misattribution, legal breadcrumb color
- Cart badge pulsed on every page load/reload, not just real cart
  changes — useCartCount's SSR snapshot is always 0, so hydration alone
  satisfied the "count increased" check. Skip the very first effect run.
- WishlistButton: touch-device smaller/subtler sizing now applies
  regardless of revealOnHover (e.g. the homepage spotlight heart), not
  just the shop grid's hover-reveal mode.
- /blog: the big featured-style hero card was applied to whatever post
  sorted first post-filter, even when that post isn't actually the
  `featured` one (a category filter can exclude the real featured post
  entirely). Now gated on the post's own `featured` flag.
- Legal pages' "Startseite" breadcrumb link now matches the same
  text-brand/hover:underline treatment already used elsewhere on these
  pages (e.g. Impressum's Anbieter email link), instead of staying muted
  until hover.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018unaXmuzVA8ct1b6WoyP1U
2026-07-31 22:46:24 +00:00
Marco 92727ff22a Keep icon touch targets full-size; shrink logo instead; fluid nav gap
Revert the 40px icon-shrink below 375px (hard to tap accurately) and reclaim that space from the logo instead (76-130px depending on width, vs the always-181px controls). Re-verified overflow-free at 320px via Playwright with all 4 icons at full 44px.

Also: wishlist heart's touch-friendly smaller/subtler size now applies to already-wishlisted (filled) hearts too, not just not-yet-wishlisted ones. The wishlist page's login redirect now returns to the wishlist instead of the generic account/orders overview. Desktop nav-link gap now scales fluidly between 1024-1300px instead of a fixed 48px that felt too wide right where nav labels have the least room.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 21:20:01 +00:00
Marco 1a3a8ba20e Show search/wishlist icons on all screen widths, not just sm+
Both were deliberately hidden below 640px to avoid icon-row overflow. Verified via an actual Playwright viewport sweep (320-640px) that simply un-hiding them did overflow — the header's fixed 181px logo + 32px padding left no room. Fixed properly: logo shrinks to 130px and padding drops to px-4 below sm, plus a 40px icon-size step below 375px. Re-verified overflow-free down to 320px.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 21:08:11 +00:00
Marco bc40e22910 Gate search behind CompanySettings.searchEnabled; fix two reported bugs
Search icon now gated behind the new backend toggle, same pattern as
wishlistEnabled — off by default.

Fixed: blog category filter bar was invisible — it was wrapped in
<Reveal>, which sits right at/just past the hero's bottom edge, the
exact "already near the initial viewport" position Reveal.tsx's own
comment documents as a whileInView(margin:"-80px") trap (an element
already visible without scrolling can permanently never register as
"entered view", since `once: true` never gets a second chance). Now a
plain div, no scroll-reveal animation needed for a filter bar anyway.

Fixed: wishlist count showing one behind on the Navbar badge —
useWishlist.ts's toggle() broadcast the "refetch me" event immediately
after the optimistic local update, before the POST request was even
sent. Another instance's resulting refetch could race the actual
server-side write, get the pre-toggle list, and then never get told to
refetch again. Broadcast now only fires after the request settles.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 22:51:37 +00:00
Marco 2eda211a29 Add instant-search overlay (products + blog posts)
Separate commit on purpose so this can be reverted independently if
needed. Search icon in the Navbar (hidden below sm:, same reasoning
as WishlistLink — Account+Cart are the only always-visible icons on
true mobile) opens a debounced (250ms) overlay searching both
collections at once via a new /api/search route.

Plain Payload `where[...][contains]` queries (Postgres ILIKE), not a
real search index (Meilisearch/Algolia) — matches the catalog's
current small size, see [[project-ecommerce-sota-gaps]]'s own "search
becomes necessary past ~20 products" note. Worth upgrading later
without touching the overlay component itself.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 22:39:38 +00:00
Marco 11aa9689c1 Add wishlist feature (frontend), gated by CompanySettings.wishlistEnabled
New: useWishlist.ts (fetch+optimistic-toggle hook, server-backed since
a wishlist needs a logged-in customer, unlike the guest-friendly cart),
WishlistButton.tsx (heart toggle, login-redirects on 401), Navbar's
wishlist icon+badge (hidden below sm: — Account+Cart are the only
always-visible icons on true mobile, a 3rd icon there risks the same
computed nav-overflow class of bug documented in the figma-to-nextjs
skill), and /konto/merkliste (list page, 404s if the feature gets
disabled after a customer already has rows).

Product gained numericId (the raw Payload id) alongside its existing
slug id — WishlistItems.product is a real numeric relationship field,
unlike cart/checkout's slug-keyed "commerce id".

Backend counterpart (WishlistItems collection, CompanySettings toggle,
migration) already deployed separately.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 22:28:30 +00:00
Marco 32f4068272 Slow down the mobile nav drawer's close animation
The shared ease-out curve (fast start, slow finish) worked well for
the open reveal but made the close shrink almost instantly then
linger on a barely-visible sliver — read as abrupt. Gave exit its own
longer, easeInOut transition instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 19:59:36 +00:00
Marco 275d5abd95 Close the mobile nav drawer when clicking the navbar itself
Added an onClick on <header> that closes the drawer whenever it's
open — the panel is a sibling, not a descendant, so this never fires
for clicks inside the open drawer, only the bar itself. The
hamburger's own click now stops propagation so toggling the drawer
open doesn't get immediately undone by this same handler.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 19:57:14 +00:00
Marco fb1bedcacd Fix invisible Stripe pay button, add brand favicon/OG image, navbar 3x3-System CTA, blog hero crop
- PaymentStep: bg-brand-primary was never a real Tailwind class, leaving
  the "Jetzt bezahlen" button unstyled/invisible; switched to bg-brand
  with dark text, matching every other CTA on the site.
- New app/icon.svg + app/apple-icon.png + app/favicon.ico: brand-yellow
  rounded square with a bold italic "e", replacing the Next.js default.
- New public/og-image.png (logo on the site's cream background) wired in
  as the SEO fallback default OG image/description/title in payload.ts.
- Navbar CTA: "Klarheitskompass" -> "Mein 3x3-System", now links to
  /3x3-system (page not built yet).
- Blog overview hero image anchored to the top instead of center-cropped.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 21:48:22 +00:00
Marco 96fddf4cd9 ueberarbeitung mit bjoern 2026-07-29 20:11:55 +00:00
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
Marco 268f2e841d Nudge checkmark/login icon vertical alignment
- Checklist checkmarks (Challenge, todo-cards, newsletter): mt-0.5 -> mt-1,
  centering against the first line's glyphs instead of sitting flush at
  the very top edge.
- Navbar login icon: -translate-y-0.5 — its round head vs. wide shoulders
  read as optically bottom-heavy next to the cart icon despite both
  having a mathematically centered bounding box.
2026-07-24 20:02:44 +00:00
Marco f20a02dfa2 Match the profile icon's size to the cart icon in the navbar
Profile was h-6 w-6 (24px) next to cart's h-7 w-7 (28px), a noticeable
size mismatch between the two always-visible nav icons.
2026-07-24 18:38:33 +00:00
Marco 55de9b3e29 Fix three mobile layout issues on the homepage
- Hero CTA: whitespace-nowrap forced the button as wide as the full
  32-char phrase, overflowing the stacked mobile column. Now wraps to
  two lines below lg:, single line from lg: up where there's room.
- Navbar: the account/cart icons are 44px touch targets with the glyph
  centered inside, so the outer gap-2 read as too much space on top of
  that padding. Grouped them with no gap between just the two.
- Divider: "Klarheit -> Fokus -> Entlastung" plus its connector icons
  needs ~550px to fit one row even at the site's 768px fluid floor, far
  more than a phone's ~310px content width. Added a component-scoped
  --divider-word-size (independent from --text-h2) plus a <640px
  override that shrinks the words/icons/gaps together.
2026-07-24 18:32:35 +00:00
Marco 43944d8cc8 Fix navbar/discount/invoice bugs from manual QA, add VAT breakdown, shipping-address override, checkout persistence, redesigned mobile menu
Bug fixes:
- Navbar login/logout state now updates immediately (custom ep-auth-changed
  event) instead of requiring a hard reload
- Status-change email links were broken by an un-encoded "#" in the order
  number; fixed for all 4 status emails
- Cart discount code: manual input field restored (was removed entirely)
- Quote-label underline now scales with the label's actual text width
- Number Ranges admin list now shows the invoice prefix/counter columns

Pricing & VAT:
- Prices show the real per-product VAT rate ("inkl. X% MwSt.") instead of
  a generic disclosure
- Cart/checkout/confirmation totals show the actual € amount of VAT
  included, broken down per rate when a cart spans more than one
  (new lib/taxBreakdown.ts, shared with the invoice PDF's own math)
- Account order pages gained product thumbnails and the same VAT breakdown

Low-stock warning: a "Nur noch wenige verfügbar" badge/hint across the
shop grid, spotlight, and add-to-cart variant pickers, driven by the
existing lowStockThreshold field (still never exposes raw stock counts).

Invoice PDFs: product thumbnails on every line item, a plain "Netto"
label (rate was redundant, already stated on the MwSt. line below), no
more duplicate USt-IdNr. in the header, and — for a Stornorechnung
specifically — an explicit "Versand" line that was previously only
folded silently into the tax totals.

Checkout:
- Optional deviating shipping address (separate from the billing address
  used for the invoice), with its own toggle + address form
- Full checkout draft persistence (name/address/shipping/payment
  selections) survives navigating away and back, via localStorage
- Invoice PDF shows a third "Lieferadresse" block when the shipping
  address differs from billing

Mobile navigation: fullscreen panel with a circular reveal animation from
the hamburger's corner, replacing the old in-flow accordion drawer; no
login CTA inside it (redundant with the always-visible header icon).

Admin-facing (Payload backend, mirrored where the frontend has a ported
copy of the same renderer): dashboard rebuilt as individual cards, split
into 3 task queues (received/processing/returns) instead of 2, revenue
and order counts now exclude cancelled/returned orders immediately, and
the low-stock alert links to the specific affected product(s) instead of
the unfiltered list. A new immediate email notifies the shop owner the
moment an order comes in, instead of only via the daily digest.

Testimonials admin list now groups by page instead of interleaving all
three grids' entries. ~45 English admin field descriptions translated to
German for consistency.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 22:52:15 +00:00
Marco 7a9fed6f95 Remove duplicate Newsletter/7-Tage-Challenge buttons from tablet drawer
They already show inline in the header from md (768px) up — now that the
drawer panel actually renders (previous fix), this pairing became visibly
redundant on the 768-1023px tier specifically. md:hidden on just those two
buttons; the drawer's "Anmelden"/"Mein Konto" link stays, since the header's
account icon links to the same place but doesn't carry that label text.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018PL4zfTY1sXc8x5QS6FatM
2026-07-22 18:28:34 +00:00
Marco b3c44e3082 Fix invisible mobile nav drawer, redesign its open/close as a modern fade
Root cause: the <header> had a fixed h-[6.25rem], not min-h. Its flex-col
first child (top row) has shrink-0 and always fills all 6.25rem, leaving
zero room for the drawer panel — the panel's own overflow-hidden (needed
for its animation) resets flexbox's automatic min-height to 0, so it got
crushed to a literal 0px box regardless of its own max-height. The
hamburger button itself always worked (toggled to "X" correctly); the
panel it opened was rendering at zero height beneath it, at every
breakpoint where it exists (below lg/1024px).

Also replaced the max-height-accordion technique with a CSS grid-rows
(0fr/1fr) transition — no more guessing/capping a max-height — plus an
opacity+translateY fade on the inner content for a softer, more modern
open/close instead of a flat height-only reveal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018PL4zfTY1sXc8x5QS6FatM
2026-07-22 18:24:14 +00:00
Marco ec75a480bd Detect checkout email collisions and show login state in the navbar
Registering with an email that already has an account previously just
failed with a generic error and no clear next step. registerCustomer()
now flags emailExists specifically, and checkout switches straight to the
login toggle (email pre-filled, scrolled into view) instead. The account
icon also gets a small underline while logged in, matching the nav links'
active-state styling — it was otherwise the only nav element that gave no
visual signal of session state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 08:26:00 +00:00
Marco f0df359db4 Add password reset, order confirmation email with editable templates, and fix missing account entry points
Password reset uses Payload's built-in forgot/reset-password flow,
customized to link to this app instead of the Payload admin. Order
confirmation email and the password-reset email's wording both come from
a new Payload email-templates collection, editable without a deploy and
previewable via Live Preview at /email-preview/[type] (same mechanism as
Posts/LegalPages/Testimonials, sample data instead of a real document).

Also: order numbers get a random suffix (prevents guessing, motivated by
a considered-and-deferred guest order-lookup feature); the discount code
field only shows in the cart when a code is actually active (codes now
apply via a ?code= link instead of manual entry); and three navigation
gaps found while testing — no reachable login link with an empty cart, no
logout link anywhere, no way back from profile to order history.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-22 08:14:08 +00:00
Marco 028a1fc4ec Add active-product-count-driven automation
- Products gain `active`/`spotlight*`/`updatedAt` on the base Product type
  (folded in from the now-removed separate SpotlightProduct type) so shop
  grid, spotlight, and related-products can each filter `.active` from the
  same already-fetched list — cart/checkout/order-confirmation/product-
  detail pages keep resolving any product regardless of active status.
- getSpotlightProduct() now derives from getProducts() instead of its own
  Payload query: with exactly 1 active product, that one IS the spotlight
  (overriding any `spotlight` flag elsewhere); otherwise same
  most-recently-updated tie-break as before, just computed client-side.
- ProductGrid drops the already-dead SHOP_GRID_EXCLUDE_IDS list in favor of
  the same `active` filter, with an empty-state message if 0 active.
- RelatedProducts gates on >=2 active products regardless of cart contents
  or how many display slots would otherwise resolve.
- Navbar's "Shop" link becomes an anchor to the homepage spotlight section
  (id="spotlight") instead of a real /shop navigation whenever exactly 1
  product is active — passed down from the now-async root layout, which
  fetches the catalog once for this decision.
2026-07-21 20:39:22 +00:00
Marco a72aea1070 fix(navbar): reset scroll to top when navigating home via logo
Since the Navbar lives in the root layout and never unmounts across
navigations, Next.js's default Link scroll behavior left the previous
page's scroll offset in place instead of resetting to top — landing
users wherever that old offset happened to fall in Home's layout
(often around the Werkzeuge section) instead of at the top.
2026-07-21 11:15:37 +00:00
Marco ed58a65b8f Add blog overview page (/blog), link Navbar "Blog" to it
- app/blog/page.tsx: header (title/subheading + bleeding photo with a
  left-edge fade, per Figma node 4577:330), featured-post card (most
  recent), remaining posts as a divided list with category/readTime/date,
  and the reusable Newsletter signup panel. Uses all real posts from
  Payload — the Figma mockup padded its list out to 4 items with two
  posts that were never actually seeded, so this only renders what
  exists (currently 1 featured + 2 listed).
- lib/payload.ts: BlogPost now carries publishedAt (needed for the list's
  per-post date), removed the now-redundant duplicate field on PostDetail.
- Navbar: "Blog" now links to /blog instead of scrolling to the
  homepage's #blog anchor — same real-route pattern as "Shop".
- blog/[slug]/page.tsx: earlier title-size tuning (fluid clamp between
  text-h-feature and text-display) from this session's follow-up
  feedback, not yet pushed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 21:04:10 +00:00
Marco f5df384b13 fix(Navbar): stop backdrop-blur from breaking NewsletterModal's fixed positioning
backdrop-filter (backdrop-blur-md, applied to the sticky header once
scrolled) creates a new containing block for position:fixed descendants,
same as transform does. NewsletterModal was rendered inside that header,
so its `fixed inset-0` backdrop silently stopped being fixed to the
viewport once scrolled and became fixed to the 100px header instead,
clipping the modal to the top of the page. Moved the modal to be a
sibling of <header> instead of a child.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 20:03:12 +00:00
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
Marco 9e5532be63 Add shop, cart, versand pages and Impulse & Tipps detail page
- New /shop overview, /cart (real cart state via useSyncExternalStore),
  /versand (shipping policy page with TOC) and /newsletter detail page
- Cart: quantity/removal, order summary, related-products cross-sell
  with randomized picks, VersandModal quick-reference instead of
  navigating away, MwSt. disclosure next to unit prices
- Add-to-cart UX: inline success feedback (green state) plus a
  fly-to-navbar-cart-icon animation (CartFlyProvider) with a delayed
  badge count-up; AddToCartButton no longer navigates straight to /cart
- Shared lib/products.ts catalog and lib/shipping.ts constants (cost,
  free-shipping threshold, handling/transit days) so cart, trust badges
  and the versand page can never drift apart
- Fix Navbar smooth-scroll easing (ease-out instead of ease-in-out, no
  more perceived start delay); compress newsletter modal photo
  2.4MB -> 85KB to fix first-open jank
2026-07-19 14:42:22 +00:00
Marco e4f0c66d7b 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>
2026-07-19 11:34:52 +00:00
Marco fdab68efe5 fix(Navbar): replace IntersectionObserver with scroll-based active section 2026-06-30 22:24:02 +00:00
Marco 155b8b6dae fix(Navbar): active section triggers at 2/3 from bottom 2026-06-30 22:22:02 +00:00
Marco 38da6b503e feat(Navbar): active section highlight via IntersectionObserver 2026-06-30 22:19:57 +00:00
Marco 824bce8638 feat(Navbar): logo click smooth-scrolls to top 2026-06-30 22:16:18 +00:00
Marco b946697b12 Revert "feat: full responsive layout — mobile-first, lg breakpoint, fluid typography"
This reverts commit 2505a87717.
2026-06-30 22:07:51 +00:00
Marco 2505a87717 feat: full responsive layout — mobile-first, lg breakpoint, fluid typography
Strategy: one layout breakpoint at lg (1024px), clamp() for fluid type.

Navbar: hamburger menu (animated ✕) with max-h dropdown, resize-close,
  h-20 mobile / h-[6.25rem] desktop, blur triggers on scroll or menu-open.
Hero: flex-col→lg:flex-row, clamp(2rem,5vw,4rem) heading, background-image
  scales responsively, gradient mask via .hero-mask only at lg+ in CSS.
Divider: flex-wrap + gap-y for smaller screens.
Tools: grid-cols-1→md:2→lg:3, removed fixed height and per-card paddingRight.
Blog: featured flex-col→lg:flex-row, secondary flex-col→md:flex-row,
  excerpt hidden on mobile secondary cards to save space.
About: flex-col→lg:flex-row, clamp on quote size, min-h-[18rem] for photo.
Newsletter: flex-col→lg:flex-row, input+button stack on xs / row on sm+.
Footer: flex-col→lg:flex-row, flex-wrap on legal links.
globals.css: scroll-padding-top 5rem mobile / 6.25rem desktop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 22:04:23 +00:00
Marco 2ed1acf997 feat(Navbar): custom 800ms ease-in-out smooth scroll via rAF
Replaces browser scroll-behavior:smooth (no duration control) with a
requestAnimationFrame loop using cubic ease-in-out over 800ms. Offset
accounts for navbar height (100px) via getBoundingClientRect + scrollY.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 21:47:09 +00:00
Marco 4aa5b924fc fix(Navbar): replace Next.js Link with <a> + onClick for anchor navigation
Next.js Link appends hash instead of replacing it (#a#b#b...). Anchor
links now use native <a> with e.preventDefault(), manual scrollIntoView,
and history.replaceState so only the current hash appears in the URL.
Page routes (/shop etc.) still use Link as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 21:45:39 +00:00
Marco 1aa03476c3 fix(Navbar): remove shadow-sm on scroll — no bottom line when sticky
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 21:42:33 +00:00
Marco 117e4704ca feat(Navbar): sticky with scroll-triggered backdrop blur + smooth scrolling
Navbar is sticky top-0 z-50. On scroll >8px: bg opacity drops to 80%
and backdrop-blur-md activates with a subtle shadow. Transitions on
background-color and backdrop-filter (300ms). Smooth scrolling via
html { scroll-behavior: smooth } in globals.css.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 21:39:09 +00:00
Marco eded5a5812 feat(Navbar): wire anchor links to page sections
Werkzeuge→#werkzeuge, Blog→#blog, Über Björn→#ueber-bjoern.
Shop remains /shop (no matching section). Added matching id attributes
to Tools, Blog and About section root elements.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 21:36:48 +00:00
Marco 6c295c8d8a fix: use exported Figma assets for logo, hero image, avatars and icon
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 19:18:49 +00:00
Marco 601507df1d feat: add Hero section, fix logo with Caveat font + brush stroke SVG
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 19:15:32 +00:00
Marco de924cae2d feat: add desktop navigation matching Figma design
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-30 19:12:14 +00:00