- One-Page-Site nach Design-Handoff: Hero mit scroll-gesteuertem Bus, Stats, Leistungen, Foto-Band, Flotte, interaktive MapLibre-Karte, Karriere, Footer - Vollständige Handy-Optimierung: Hamburger-Menü, responsive Grids, touch-freundliche Karte - Bus-Foto lokal in assets/ Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
246 lines
15 KiB
Markdown
246 lines
15 KiB
Markdown
# Handoff: Unger Reisen — Website-Redesign (One-Pager)
|
||
|
||
## Overview
|
||
A modern, bold one-page marketing website for **Unger Reisen**, an omnibus (coach/bus)
|
||
company from Niederbayern (Buch am Erlbach & Landshut, Germany). The page pitches their
|
||
services (coach hire, corporate/club trips, transfers), shows the fleet, displays both
|
||
locations on an interactive map, and drives visitors to call. Language: **German**.
|
||
|
||
The signature element is a **scroll-driven hero**: a stylized bus drives left→right across
|
||
the bottom of the hero as the user scrolls down.
|
||
|
||
## About the Design Files
|
||
The file in this bundle (`Unger Reisen.dc.html`) is a **design reference created in HTML** —
|
||
a working prototype showing the intended look, motion, and behavior. It is **not** production
|
||
code to copy verbatim. The task is to **recreate this design in the target codebase's
|
||
environment** (React/Next.js, Vue, Astro, plain Vite, etc.) using that project's established
|
||
patterns, component library, and conventions. If no codebase exists yet, pick the most
|
||
appropriate stack (a React/Next.js + Tailwind setup fits this well) and implement it there.
|
||
|
||
> Note on the file format: the prototype is authored as a "Design Component" (`.dc.html`)
|
||
> with a small custom template runtime (`<x-dc>`, `{{ }}` holes, `<sc-for>`, a
|
||
> `class Component extends DCLogic`). **Ignore that runtime.** It is only a prototyping
|
||
> harness. Read it as: HTML structure + inline styles + a plain JS class whose `renderVals()`
|
||
> returns the data arrays and event handlers. Reimplement with normal components and state.
|
||
|
||
## Fidelity
|
||
**High-fidelity (hifi).** Final colors, typography, spacing, layout, motion, and copy are all
|
||
intentional. Recreate pixel-closely, but re-express the styling in the target system
|
||
(e.g. Tailwind classes / styled-components) rather than copying inline styles.
|
||
|
||
---
|
||
|
||
## Design Tokens
|
||
|
||
### Colors
|
||
| Token | Value | Usage |
|
||
|---|---|---|
|
||
| `--red` (accent) | `#C8102E` | Primary accent. Marquee, stat band, buttons, pins, route, section eyebrows. (Prototype default is `#C8102E`; original palette also used `#E4002B`. Curated options: `#E4002B`, `#D21F1F`, `#C8102E`, `#EE3524`.) |
|
||
| `--ink` / `--night` | `#0a0e18` | Page background (near-black navy) |
|
||
| `--paper` | `#f4f0e8` | Light text on dark; light card backgrounds |
|
||
| Card surface | `#111725` | Dark cards (services, fleet, contact) |
|
||
| Card surface (hover) | `#151d30` | Service card hover |
|
||
| Map panel bg | `#0d1420` | Map container background |
|
||
| `--line` | `rgba(255,255,255,.14)` | Hairline borders/dividers on dark |
|
||
| `--muted` | `#8b93a7` | Muted body text |
|
||
| Body text on dark | `#c8cdda` | Hero paragraph, secondary text |
|
||
| Sub-label text | `#9aa6c0` | Pin sublabels, small caps labels |
|
||
| Footer legal text | `#5a6274` / `#40485a` | Footer links & disclaimer |
|
||
| Input border (light card) | `#d3ccbe` | Form inputs (note: forms were later removed) |
|
||
|
||
### Typography
|
||
- **Display font:** `Anton` (Google Fonts). Used for all big headlines, stat numbers, logo,
|
||
pin labels. Always `text-transform: uppercase`, `letter-spacing: .5px`, `line-height: .9`.
|
||
- **Body/UI font:** `Archivo` (Google Fonts), weights 400–900. Body, nav, labels, buttons.
|
||
- Google Fonts import:
|
||
`https://fonts.googleapis.com/css2?family=Anton&family=Archivo:wght@400;500;600;700;800;900&display=swap`
|
||
- Type scale (fluid, `clamp`):
|
||
- Hero H1: `clamp(64px, 13vw, 190px)`
|
||
- Section H2 (Anton): `clamp(40px, 7vw, 90–96px)`
|
||
- Stat numbers: `clamp(44px, 6vw, 72px)`
|
||
- Fleet seat number: `40px`
|
||
- Body: `16–19px`; nav/labels/buttons: `12–15px` uppercase, `letter-spacing 1–3px`
|
||
|
||
### Spacing / Layout
|
||
- Section vertical padding: `clamp(70px, 10vw, 130px)`; horizontal: `clamp(20px, 5vw, 60px)`
|
||
- Card grid gaps: `16px`; large column gaps: `clamp(30px, 5vw, 70px)`
|
||
- Border radius: mostly **sharp** (0–2px). Buttons are rectangular (no pill). Only pins/dots are circular.
|
||
|
||
### Shadows
|
||
- Bus body: `0 18px 30px -10px rgba(0,0,0,.6)`
|
||
- Map pin dot: `0 0 0 5px <red>40, 0 2px 6px rgba(0,0,0,.55)` (red glow ring + drop)
|
||
- Buttons lift on hover via `transform: translateY(-2px)` (transition `.2s ease`)
|
||
|
||
---
|
||
|
||
## Screens / Views
|
||
Single continuous page. Sections top→bottom:
|
||
|
||
### 1. Top Marquee
|
||
- Full-width red (`--red`) bar, white uppercase text scrolling right→left infinitely.
|
||
- Content, `/`-separated: "Reisebusse mit Fahrer / Firmen & Vereine / Tagesfahrten /
|
||
Transfers rund um die Uhr / Niederbayern".
|
||
- Implementation: duplicate the track and animate `translateX(0 → -50%)` linear infinite (~24s).
|
||
- `font-size:13px; font-weight:700; letter-spacing:2px`.
|
||
|
||
### 2. Nav (fixed/absolute over hero)
|
||
- Left: logo — "UNGER" (Anton, 26px, white) + "REISEN" (Archivo, 11px, letter-spacing 5px, red).
|
||
- Right: links (uppercase, 13.5px, weight 600) — Leistungen, Flotte, Karriere, Kontakt —
|
||
plus a red CTA button **"Jetzt anrufen"** (`href="tel:+498762896"`).
|
||
- Sits at `top:39px` (below marquee) when at page top; **on scroll >40px** it solidifies:
|
||
background `rgba(10,14,24,.9)`, `backdrop-filter: blur(12px)`, moves to `top:0`, reduces
|
||
padding, adds a hairline bottom shadow. Transition `.35s ease`.
|
||
|
||
### 3. Hero (`#top`, min-height:88vh)
|
||
- Dark radial-gradient bg: `radial-gradient(120% 90% at 70% 10%, #182238 0%, #0a0e18 60%)`.
|
||
- Eyebrow: red rule + "OMNIBUSUNTERNEHMEN SEIT GENERATIONEN".
|
||
- H1 (Anton): "Wir bringen / Sie **weiter.**" — "weiter." in red.
|
||
- Paragraph (max 520px, `#c8cdda`): "Moderne Reisebusse mit erfahrenen Fahrern — für Firmen,
|
||
Vereine und Gruppen in ganz Bayern und Europa."
|
||
- Buttons: red **"Jetzt anrufen →"** (`tel:`), outline **"Unsere Flotte"** (`#flotte`).
|
||
- **Driving scene** (bottom of hero, `height: clamp(280px,42vh,420px)`, pinned bottom):
|
||
- Layered parallax: far scenery hills, near hills, a dark road strip, red-dashed lane stripes.
|
||
Each is a repeating radial/linear-gradient background animated via `background-position-x`
|
||
at different speeds (far slow ~40s, near ~18s, stripes fast ~.5s) — evokes forward motion.
|
||
- **The bus**: CSS-drawn side view — cream body with red mid-stripe, windshield, window strip,
|
||
"UNGER REISEN" wordmark, door, two spinning wheels (`@keyframes wheel` rotate, .5s linear),
|
||
a pulsing headlight glow. Bus width `clamp(380px,52vw,620px)`.
|
||
- **Scroll-driven horizontal motion:** on scroll, compute
|
||
`hp = clamp(scrollY / (heroHeight * 0.9), 0, 1)` and set the bus
|
||
`transform: translate(x, bob)` where `x` interpolates from just off-left
|
||
(`-busWidth*0.30`) to `sceneWidth - busWidth*0.70`, and `bob = sin(now/380)*4` (gentle
|
||
vertical bob; 0 if reduced-motion). Driven by `requestAnimationFrame`.
|
||
- Respect `prefers-reduced-motion`: disable marquee, hills, stripes, wheel spin, and bob.
|
||
|
||
### 4. Stat Band
|
||
- Full-width red bg, white. Auto-fit grid of 4 stats (Anton big number + label):
|
||
- **2** — Standorte in Bayern
|
||
- **60+** — Sitzplätze pro Reisebus
|
||
- **24/7** — Für Sie erreichbar
|
||
- **∞** — Ziele in ganz Europa
|
||
|
||
### 5. Leistungen (`#leistungen`)
|
||
- Header row: H2 "Das fahren wir für Sie" + intro paragraph.
|
||
- Auto-fit grid (min 260px) of 4 dark cards (`#111725`, hairline border, min-height 260px).
|
||
Each: big red Anton index (01–04), title (uppercase 22px/800), description. Hover: bg
|
||
`#151d30` + `translateY(-4px)`.
|
||
1. **Busanmietung** — "Moderne Reisebusse mit Fahrer — flexibel für einzelne Fahrten oder mehrtägige Touren."
|
||
2. **Firmenreisen** — "Betriebsausflüge, Tagungen und Events. Ihr Team sicher und entspannt am Ziel."
|
||
3. **Vereinsfahrten** — "Ausflüge, Feste und Sportevents — komfortabel für die ganze Gruppe."
|
||
4. **Transfers** — "Flughafen-, Hotel- und Event-Transfers. Pünktlich und rund um die Uhr planbar."
|
||
|
||
### 6. Real Photo Band
|
||
- Full-bleed band (`height: clamp(320px,48vw,520px)`) with a background bus photo, dark
|
||
gradient overlay (`rgba(10,14,24,.55 → .75)`), centered Anton headline:
|
||
"Komfort, auf den Sie sich verlassen können."
|
||
- Prototype image URL: `https://www.unger-reisen.de/wp-content/uploads/startslider-bus-1024x366.png`
|
||
(external; **replace with a licensed/owned photo** — see Assets). Has an `onerror` fallback
|
||
to a gradient.
|
||
|
||
### 7. Flotte (`#flotte`)
|
||
- Eyebrow "Unsere Flotte" + H2 "Für jede Gruppengröße".
|
||
- Auto-fit grid (min 280px) of 3 cards. Card header row: name (Anton 30px) on the left, and a
|
||
right-aligned inline seat unit: small "bis" + big red number (Anton 40px) + small "Sitze".
|
||
Body: description + tag chips (hairline-bordered pills of text).
|
||
- **Reisebus** — bis **60** — "Der Große für lange Strecken und große Gruppen — voll ausgestattet." Tags: Klimaanlage, WC, Bordküche, WLAN.
|
||
- **Midibus** — bis **35** — "Wendig und komfortabel — ideal für mittlere Gruppen und Tagestouren." Tags: Klimaanlage, Komfortbestuhlung.
|
||
- **Kleinbus** — bis **19** — "Persönlich und flexibel für kleine Gruppen, Transfers und Sonderfahrten." Tags: Flexibel, Wendig.
|
||
|
||
### 8. Kontakt + Karte (`#kontakt`)
|
||
- Eyebrow "So erreichen Sie uns" + H2 "Zwei Standorte. / Ein Anruf."
|
||
- Two-column grid (`1.35fr / .95fr`, stack on mobile):
|
||
- **Left — interactive map** (panel `min-height:440px`, bg `#0d1420`, hairline border):
|
||
- **MapLibre GL JS** map, dark Carto style
|
||
`https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json`.
|
||
- Two custom HTML markers (`anchor:'bottom'`): a label box (Anton title + Archivo sub) above
|
||
a circular dot with a red glow ring.
|
||
- **Landshut** — "Niederlassung" — coord `[12.1508, 48.5449]` — dot red, ring white.
|
||
- **Buch a. Erlbach** — "Hauptsitz" — coord `[12.0517, 48.4703]` — dot white, ring red.
|
||
- **Route line** between the two coords: a GeoJSON `LineString`, red, `width 3`,
|
||
`line-dasharray [1.6,1.4]`, plus a wider low-opacity casing (`width 9, opacity .18`).
|
||
- `NavigationControl` (zoom + compass) top-right. **`scrollZoom` disabled** so page scroll
|
||
isn't hijacked. `fitBounds` to both points with padding `{top:96,bottom:70,left:70,right:70}`,
|
||
`maxZoom:12`. Call `map.resize()` shortly after load.
|
||
- Overlay chip (bottom-left, `pointer-events:none`): "**15 km** zwischen den Standorten".
|
||
- Requires `maplibre-gl` (JS + CSS). In prototype loaded from
|
||
`https://unpkg.com/maplibre-gl@4.7.1/...`; in a real app install the npm package.
|
||
Map tiles load **online** — expected for a live site.
|
||
- **Right — contact card** (`#111725`, hairline border):
|
||
- **Hauptsitz** (white dot / red ring): "Eichenstr. 7+9, Vatersdorf · 84172 Buch am Erlbach"
|
||
· Tel. +49 (0)8762 / 896
|
||
- divider
|
||
- **Niederlassung** (red dot / white ring): "Jenaer Straße 4a · 84034 Landshut"
|
||
· Tel. +49 (0)871 / 96 58 586-0
|
||
- CTAs pinned to bottom: red **"Jetzt anrufen"** (`tel:+498762896`) + outline
|
||
**"info@unger-reisen.de"** (`mailto:`).
|
||
|
||
### 9. Karriere (`#karriere`)
|
||
- Bordered band. Left: eyebrow "Karriere & Jobs", H2 "Fahren Sie mit uns", paragraph
|
||
"Wir suchen Busfahrer:innen, Begleitpersonen und Sachbearbeiter:innen — steigen Sie ein."
|
||
- Right: white button **"Offene Stellen →"** (`mailto:info@unger-reisen.de`).
|
||
|
||
### 10. Footer
|
||
- 3-column grid on `--ink`, hairline top border:
|
||
- Logo + blurb: "Günter Unger e.K. — Omnibus- & Verkehrsunternehmen. Reisen erster Klasse aus Niederbayern."
|
||
- **Hauptsitz**: Eichenstr. 7+9, Vatersdorf · 84172 Buch am Erlbach · Tel. +49 (0)8762 / 896
|
||
- **Niederlassung**: Jenaer Straße 4a · 84034 Landshut · Tel. +49 (0)871 / 96 58 586-0
|
||
- Bottom bar: "© 2026 Unger Reisen · Alle Rechte vorbehalten" + Impressum / Datenschutz / AGB.
|
||
- Small disclaimer: "Konzept-Entwurf für ein mögliches Website-Redesign · noch nicht offiziell."
|
||
(**Remove this line** once it's the real site.)
|
||
|
||
---
|
||
|
||
## Interactions & Behavior
|
||
- **Nav solidify on scroll** (>40px) — see §2.
|
||
- **Scroll-driven bus** across hero — see §3. Core formula:
|
||
`hp = clamp(scrollY/(heroHeight*0.9),0,1)`; `x = lerp(-busW*0.3, sceneW - busW*0.7, hp)`.
|
||
- **Reveal on scroll**: elements marked for reveal start `opacity:0; translateY(28px)` and
|
||
animate to `opacity:1; none` via IntersectionObserver (threshold ~0.12), transition
|
||
`.7s cubic-bezier(.2,.7,.2,1)`. Provide a safety fallback that reveals everything after ~2.5s.
|
||
- **Marquee / hills / stripes / wheels**: continuous CSS keyframe loops (see §1, §3).
|
||
- **Buttons/links hover**: `translateY(-2px)` or border color → white.
|
||
- **Map**: pan/zoom via drag + control buttons; scroll-zoom disabled; compass resets bearing.
|
||
- **Smooth anchor scrolling** for nav links (`scroll-behavior: smooth`) to `#leistungen`,
|
||
`#flotte`, `#karriere`, `#kontakt`, `#top`.
|
||
- **Reduced motion**: disable all decorative animation; keep static end states.
|
||
|
||
## State Management
|
||
Minimal — the page is largely presentational. In a component framework you need:
|
||
- Nav-scrolled boolean (or do it with a scroll listener / IntersectionObserver on a sentinel).
|
||
- The bus `x`/`bob` transform driven by a scroll + rAF loop (a ref + effect).
|
||
- Reveal-on-scroll via IntersectionObserver (a small reusable hook/directive).
|
||
- The MapLibre instance held in a ref; init in mount effect, `remove()` on unmount.
|
||
- Data arrays for **stats**, **services**, **fleet** (see copy above) — render with `.map`.
|
||
- (An earlier version had a controlled contact form; it was **removed** in favor of call/email CTAs.
|
||
If you re-add a form, wire name/contact/dest/date/pax/message + a submitted state.)
|
||
|
||
## Configurable knobs (from the prototype's props)
|
||
- **accentColor** — the red. Default `#C8102E`; options `#E4002B / #D21F1F / #C8102E / #EE3524`.
|
||
Applied as a CSS variable `--red`; also recolors the map route on change. Expose as a theme
|
||
token in the real app.
|
||
|
||
## Assets
|
||
- **Fonts:** Anton + Archivo (Google Fonts) — see import above.
|
||
- **Icons:** none required (all visuals are CSS/SVG-drawn or map markers). The original shadcn
|
||
map component referenced `lucide-react` for map control icons — use those (Plus, Minus, Locate,
|
||
Maximize, Compass/X) if you build custom controls; MapLibre's built-in `NavigationControl`
|
||
needs no icon assets.
|
||
- **Bus hero photo (§6):** placeholder points at unger-reisen.de. **Replace with an owned or
|
||
licensed photo** of an Unger coach. If you need a temporary stand-in, use a royalty-free coach
|
||
photo (e.g. an Unsplash coach/bus image) and swap later.
|
||
- **Map:** MapLibre GL JS + CSS (npm `maplibre-gl`), Carto "dark-matter" style (free, attribution
|
||
required — keep the attribution control). Tiles fetched at runtime.
|
||
- **No logo file** — the "UNGER REISEN" logo is set in type (Anton + Archivo).
|
||
|
||
## Files
|
||
- `Unger Reisen.dc.html` — the full design prototype (all sections, styles, and JS behavior).
|
||
Read the `<x-dc>…</x-dc>` body for structure/markup, the `<style>` in `<helmet>` for keyframes,
|
||
and the `class Component` script for the scroll/bus/map/reveal logic and the data arrays.
|
||
|
||
## Contact facts (verbatim, safe to reuse)
|
||
- Hauptsitz: Eichenstr. 7+9, Vatersdorf, 84172 Buch am Erlbach — Tel. +49 (0)8762 / 896
|
||
- Niederlassung: Jenaer Straße 4a, 84034 Landshut — Tel. +49 (0)871 / 96 58 586-0
|
||
- E-Mail: info@unger-reisen.de
|
||
- Entity: Günter Unger e.K.
|
||
- Coordinates used on the map: Buch a. Erlbach `[12.0517, 48.4703]`, Landshut `[12.1508, 48.5449]`.
|