Native <select> chevrons render at varying offsets across browsers.
Replaced them with `appearance-none` + an absolute-positioned
chevron-down Icon at right-4 (16px) so the gap between the chevron
and the right border is consistent. Applied to RegisterPage's
salutation select and ShippingStep's shipping/billing country selects.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switched both the desktop and mobile account IconButton from `ghost`
to `float` (bg-brand-float + text-accent) with shadow disabled — same
md size (w-11 h-11) as the cart button beside it, so the pair reads
as a balanced complementary set: yellow cart, green account.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- IconButton (icon: user) in the desktop right cluster, left of cart,
and a mobile-only top-right account icon. Both navigate to /login.
- RegisterPage now matches the live kaiser-natron.at flow: salutation
dropdown (Frau/Herr/Divers), required terms & privacy checkbox
linking to /datenschutz, marketing opt-in.
- auth.js stub carries salutation + acceptsTerms through to the
session payload so the eventual backend swap is a no-op.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Vue Router's scrollBehavior doesn't fire when RouterLink resolves to
the current URL (logo while on /, /#bundles while already at #bundles),
so the smooth scroll never happened. Added onNavClick + onLogoClick
handlers that intercept the click when the destination is the same
route and call scrollIntoView / window.scrollTo with behavior:'smooth'
directly. Cross-route nav still goes through Vue Router's scrollBehavior
unchanged (savedPosition restore + same-route smooth + cross-route
instant).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two fixes:
- Bring back savedPosition handling in scrollBehavior so /shop ⇄
/shop/<slug> back-nav restores the previous scroll y.
- Add a route.hash watcher in HomePage that calls scrollIntoView with
smooth behaviour. Vue Router's scrollBehavior alone wasn't reliably
firing for same-route hash navigations, so this catches them
explicitly. Also handles direct /#bundles deep-links via immediate.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Navbar's primary, secondary, mobile and logo links were plain
<a href> tags, which triggered full-page reloads instead of SPA
navigation — Vue Router's scrollBehavior never ran. Switching them
to RouterLink keeps the user inside the SPA so the smooth-scroll
behaviour for /#bundles, /#revitalize, /#about kicks in.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Anchor links like /#bundles, /#revitalize, /#about now smooth-scroll
to their target instead of jumping. Reverts the earlier instant-jump
choice — for the homepage nav, the animation is the desired feedback.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Anchor links (e.g. /#bundles) still scroll to their target section.
Back/forward navigation now lands at the top of the destination
instead of restoring the previous scroll y, for predictable arrivals.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous commit (9177c79) updated public/ source images and HomePage
but forgot to rebuild dist/. Portainer deploys from committed dist/,
so the new hero images never reached the stack.
Replace inline circular-button markup and duplicated Badge classes with
first-class design-system components so every affordance is globally
controllable:
- IconButton (float / accent / cream-wash / brand-wash × sm / md / lg)
with optional count overlay; raised variants get the hover-lift
animation, flat variants keep transition-colors. No visual change.
- Badge gains an `as` prop so the search 'Clear' affordance renders as
a button with the exact same typography/pill.
- Navbar mobile search/menu + overlay close, and the search overlay's
mobile floating close, now use IconButton.
Cart icon buttons left inline for now — they combine size-specific
shadow with the count overlay and deserve a follow-up consolidation
once we add a shadow prop to IconButton.
Applies to navbar mobile search + menu and the search overlay close —
one step lighter than brand so shadow-lg actually reads. Clear pill
label trimmed to just 'Clear' / 'Löschen'.
Keeps the small-badge typography (px/py/radius/weight/tracking) but
renders "CLEAR" in accent text so it reads as an inline affordance
rather than a filled chip.
Revert mobile search/menu/close floaters to bg-brand text-accent with
shadow-lg — the cream-wash fill blended into the brand surface. Replace
the browser's native search cancel with a yellow accent-style badge
reading "clear", matching the small-badge typography.
Match the overlay menu's close button: subtle translucent fill on brand
green with a yellow icon. Drops the flat brand-on-brand buttons whose
shadows didn't read on a green page.
Adds a client-side fuzzy product search to the design system:
- `src/api/products.js`: fixture catalogue (22 products across the Kaiser
Natron, Holste, Gazelle, Grüne Tante and Linda ranges) plus a scored,
diacritic-folded search (ß→ss, ä→ae, NFKD) with weighted fields
(title 5, brand/keywords 3, size/category 2, id 1) and prefix bonus.
- `Search.vue`: tone-driven (brand/paper/cream) full-screen overlay on
mobile, centered modal on md+. Auto-focus, arrow-key nav, Enter/Esc,
suggested-products empty state, keyboard-hint footer on desktop, safe-
area aware, scroll-locks the document while open.
- Navbar now hosts two triggers: a pill-shaped "Search products"
lookalike (desktop, in the same LanguageSwitcher-style container) and
a green/accent shadow-sm floating button bottom-left on mobile. Both
open the same overlay.
- HomePage feeds the products list into Navbar.
- Design-system showcase (`/design/search`) with live demo + canned
result preview + usage snippet. Sidebar + mobile bottom-nav entries
and DE/EN i18n added.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Introduces:
- src/api/fixtures/products.js + src/api/index.js — placeholder catalog
(24 products across Kaiser-Natron / Holste / Gazelle / Grüne Tante /
Linda) so search has real data. Same shape the backend will return.
- Search.vue — Teleported dialog. Token-scored, diacritics-folded, ß→ss
normalized so German terms still match when users type ASCII. Keyboard
navigation (↑/↓/Enter/Esc), autofocus on open, scroll-lock. Full-screen
on mobile, centered command-palette modal on md+. Tone prop defaults
to 'brand' so the overlay reads as the site's primary affordance
(green), with 'paper' and 'cream' variants available.
- SearchSection.vue + ds-search route + sidebar entry.
- DE + EN strings for the overlay and the showcase.
Navbar wires the triggers: desktop search button sits left of the
LanguageSwitcher in the right cluster; mobile gets a matching bottom-
left floating button (cream surface, safe-area padded) that mirrors the
existing bottom-right cart/menu cluster. The Search overlay is mounted
inside Navbar with the default catalog, so every page that renders a
Navbar gets search for free. Selected products bubble up as a
@select event for navigation handling.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Trim the split/centered mediaSize widths and the responsive max-h caps
on the image itself by ~15% so the product cutout doesn't dominate the
first fold.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
DesignLayout now hides its 260px sidebar below lg and shows a fixed
bottom bar surfacing the current page. Tapping it opens a 50svh bottom
sheet with the full nav list (grouped, scrolls internally) plus the
back-to-site link. Route changes auto-close the sheet and the backdrop
is tap-to-dismiss.
Hero split variant: drop the grid's items-center and add lg:justify-center
on the copy column so the headline/CTA block now lines up with the
image's vertical midpoint instead of sitting at the top.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wrap the hero in an explicit flex-centering row on HomePage so vertical
centering doesn't depend on class merging, and swap the wrapper from
min-h-svh to h-svh so the layout is exactly one fold. Shrink the hero's
own py-16..lg:py-28 to py-10..lg:py-20 so the section fits comfortably
between navbar and viewport bottom.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The hero product image is a tall portrait PNG. With the hero now
stretching to fill the first fold, `w-full h-auto` was letting the
image's intrinsic height exceed the available vertical space — the
product box got clipped at the bottom and pushed the composition off.
Switch to `w-auto max-w-full max-h-[...svh]` so the image fits within
the fold and keeps its aspect ratio. Stepped 40 / 55 / 70 svh across
mobile / tablet / desktop — mobile keeps the image compact so the
headline + CTAs still land on the fold when stacked above.
Also drop the "Featured" badge from the home-page hero — the product
is already the only thing on the first fold.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>