Initiale Unger Reisen Website (statisch, mobil optimiert)
- 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>
This commit is contained in:
245
design_handoff_unger_reisen/README.md
Normal file
245
design_handoff_unger_reisen/README.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# 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]`.
|
||||
466
design_handoff_unger_reisen/Unger Reisen.dc.html
Normal file
466
design_handoff_unger_reisen/Unger Reisen.dc.html
Normal file
@@ -0,0 +1,466 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Anton&family=Archivo:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css" rel="stylesheet">
|
||||
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
:root{
|
||||
--red:#E4002B; --ink:#0a0e18; --night:#0a0e18; --paper:#f4f0e8;
|
||||
--cream:#efe9dc; --line:rgba(255,255,255,.14); --muted:#8b93a7;
|
||||
}
|
||||
html{scroll-behavior:smooth}
|
||||
body{background:var(--ink); color:var(--paper);
|
||||
font-family:'Archivo',system-ui,sans-serif; -webkit-font-smoothing:antialiased;
|
||||
line-height:1.5; overflow-x:hidden}
|
||||
a{color:inherit; text-decoration:none}
|
||||
::selection{background:var(--red); color:#fff}
|
||||
input,textarea,button{font-family:inherit}
|
||||
input:focus,textarea:focus{outline:none; border-color:var(--ink)!important}
|
||||
.display{font-family:'Anton',sans-serif; font-weight:400; text-transform:uppercase; letter-spacing:.5px; line-height:.9}
|
||||
|
||||
@keyframes scrollx{to{background-position-x:-360px}}
|
||||
@keyframes scrollxFast{to{background-position-x:-120px}}
|
||||
@keyframes scrollFar{to{background-position-x:-800px}}
|
||||
@keyframes wheel{to{transform:rotate(360deg)}}
|
||||
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
|
||||
@keyframes marquee{to{transform:translateX(-50%)}}
|
||||
@keyframes headlightPulse{0%,100%{opacity:.55}50%{opacity:.9}}
|
||||
@keyframes ping{0%{transform:scale(1);opacity:.7}70%,100%{transform:scale(3);opacity:0}}
|
||||
@keyframes routedraw{to{stroke-dashoffset:0}}
|
||||
.mapPing{transform-origin:center; transform-box:fill-box; animation:ping 2.6s ease-out infinite}
|
||||
.mapRoute{stroke-dasharray:6 9; stroke-dashoffset:520; animation:routedraw 3.2s ease-out .3s forwards}
|
||||
@media (prefers-reduced-motion:reduce){
|
||||
.hills,.hillsFar,.stripes,.marqueeTrack,.wheelSpin,.busBob,.mapPing,.mapRoute,.mapBus{animation:none!important}
|
||||
.mapRoute{stroke-dashoffset:0}
|
||||
}
|
||||
</style>
|
||||
</helmet>
|
||||
|
||||
<div style="position:relative">
|
||||
|
||||
<!-- TOP MARQUEE -->
|
||||
<div style="background:var(--red); color:#fff; overflow:hidden; white-space:nowrap; padding:9px 0; position:relative; z-index:60; font-weight:700; font-size:13px; letter-spacing:2px; text-transform:uppercase">
|
||||
<div class="marqueeTrack" style="display:inline-flex; gap:0; animation:marquee 24s linear infinite; will-change:transform">
|
||||
<span style="display:inline-flex">
|
||||
<span style="padding:0 26px">Reisebusse mit Fahrer</span><span style="opacity:.55">/</span>
|
||||
<span style="padding:0 26px">Firmen & Vereine</span><span style="opacity:.55">/</span>
|
||||
<span style="padding:0 26px">Tagesfahrten</span><span style="opacity:.55">/</span>
|
||||
<span style="padding:0 26px">Transfers rund um die Uhr</span><span style="opacity:.55">/</span>
|
||||
<span style="padding:0 26px">Niederbayern</span><span style="opacity:.55">/</span>
|
||||
</span>
|
||||
<span style="display:inline-flex" aria-hidden="true">
|
||||
<span style="padding:0 26px">Reisebusse mit Fahrer</span><span style="opacity:.55">/</span>
|
||||
<span style="padding:0 26px">Firmen & Vereine</span><span style="opacity:.55">/</span>
|
||||
<span style="padding:0 26px">Tagesfahrten</span><span style="opacity:.55">/</span>
|
||||
<span style="padding:0 26px">Transfers rund um die Uhr</span><span style="opacity:.55">/</span>
|
||||
<span style="padding:0 26px">Niederbayern</span><span style="opacity:.55">/</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- NAV -->
|
||||
<nav data-nav="1" style="position:absolute; top:39px; left:0; right:0; z-index:50; display:flex; align-items:center; justify-content:space-between; padding:22px clamp(20px,5vw,60px); transition:background .35s ease, padding .35s ease, box-shadow .35s ease">
|
||||
<a href="#top" style="display:flex; align-items:baseline; gap:9px">
|
||||
<span class="display" style="font-size:26px; color:#fff">UNGER</span>
|
||||
<span style="font-weight:700; font-size:11px; letter-spacing:5px; color:var(--red)">REISEN</span>
|
||||
</a>
|
||||
<div style="display:flex; align-items:center; gap:34px">
|
||||
<div style="display:flex; gap:28px; font-size:13.5px; font-weight:600; text-transform:uppercase; letter-spacing:1px">
|
||||
<a href="#leistungen" data-navlink>Leistungen</a>
|
||||
<a href="#flotte" data-navlink>Flotte</a>
|
||||
<a href="#karriere" data-navlink>Karriere</a>
|
||||
<a href="#kontakt" data-navlink>Kontakt</a>
|
||||
</div>
|
||||
<a href="tel:+498762896" style="background:var(--red); color:#fff; padding:12px 24px; font-size:13px; font-weight:700; text-transform:uppercase; letter-spacing:1px; transition:transform .2s ease" style-hover="transform:translateY(-2px); color:#fff">Jetzt anrufen</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- HERO with animated driving scene -->
|
||||
<header id="top" style="position:relative; min-height:88vh; display:flex; flex-direction:column; justify-content:center; overflow:hidden; background:radial-gradient(120% 90% at 70% 10%, #182238 0%, #0a0e18 60%)">
|
||||
|
||||
<!-- Giant type -->
|
||||
<div style="position:relative; z-index:20; padding:150px clamp(20px,5vw,60px) 0; pointer-events:none">
|
||||
<div data-reveal style="display:inline-flex; align-items:center; gap:12px; font-size:12px; font-weight:700; letter-spacing:3px; text-transform:uppercase; color:var(--red); margin-bottom:22px; pointer-events:auto">
|
||||
<span style="width:34px; height:2px; background:var(--red)"></span>Omnibusunternehmen seit Generationen
|
||||
</div>
|
||||
<h1 class="display" data-reveal style="font-size:clamp(64px,13vw,190px); color:#fff; letter-spacing:-1px">
|
||||
Wir bringen<br>Sie <span style="color:var(--red)">weiter.</span>
|
||||
</h1>
|
||||
<p data-reveal style="max-width:520px; margin-top:26px; font-size:clamp(16px,1.5vw,19px); color:#c8cdda; pointer-events:auto">
|
||||
Moderne Reisebusse mit erfahrenen Fahrern — für Firmen, Vereine und Gruppen in ganz Bayern und Europa.
|
||||
</p>
|
||||
<div data-reveal style="display:flex; flex-wrap:wrap; gap:14px; margin-top:34px; pointer-events:auto">
|
||||
<a href="tel:+498762896" style="background:var(--red); color:#fff; padding:17px 34px; font-size:15px; font-weight:700; text-transform:uppercase; letter-spacing:1px; display:inline-flex; align-items:center; gap:10px; transition:transform .2s ease" style-hover="transform:translateY(-2px); color:#fff">Jetzt anrufen →</a>
|
||||
<a href="#flotte" style="border:1.5px solid rgba(255,255,255,.3); color:#fff; padding:17px 30px; font-size:15px; font-weight:700; text-transform:uppercase; letter-spacing:1px; transition:border-color .2s ease" style-hover="border-color:#fff">Unsere Flotte</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DRIVING SCENE -->
|
||||
<div aria-hidden="true" style="position:relative; z-index:10; height:clamp(280px,42vh,420px); margin-top:auto; width:100%">
|
||||
<!-- far scenery -->
|
||||
<div class="hillsFar" style="position:absolute; bottom:64px; left:0; right:0; height:120px; background-repeat:repeat-x; background-size:800px 120px; opacity:.4; animation:scrollFar 40s linear infinite; background-image:radial-gradient(120px 120px at 120px 120px, #223052 0 99%, transparent 100%), radial-gradient(160px 160px at 460px 150px, #1c2743 0 99%, transparent 100%), radial-gradient(120px 120px at 700px 130px, #223052 0 99%, transparent 100%)"></div>
|
||||
<!-- near hills -->
|
||||
<div class="hills" style="position:absolute; bottom:58px; left:0; right:0; height:90px; background-repeat:repeat-x; background-size:360px 90px; opacity:.7; animation:scrollx 18s linear infinite; background-image:radial-gradient(90px 90px at 70px 100px, #2a3a5f 0 99%, transparent 100%), radial-gradient(120px 120px at 250px 120px, #26355699 0 99%, transparent 100%)"></div>
|
||||
<!-- road -->
|
||||
<div style="position:absolute; bottom:0; left:0; right:0; height:64px; background:#11151f; border-top:3px solid #1c2233"></div>
|
||||
<!-- lane stripes -->
|
||||
<div class="stripes" style="position:absolute; bottom:29px; left:0; right:0; height:5px; background-repeat:repeat-x; background-size:120px 5px; animation:scrollxFast .5s linear infinite; background-image:linear-gradient(90deg, rgba(228,0,43,.9) 0 60px, transparent 60px 120px)"></div>
|
||||
|
||||
<!-- BUS (scroll-driven left→right) -->
|
||||
<div data-bus class="busBob" style="position:absolute; bottom:52px; left:0; width:clamp(380px,52vw,620px); will-change:transform; transform:translateX(-30%)">
|
||||
<!-- headlight glow -->
|
||||
<div style="position:absolute; right:-40px; bottom:6px; width:120px; height:60px; background:radial-gradient(ellipse at left center, rgba(255,220,120,.5), transparent 70%); animation:headlightPulse 2s ease-in-out infinite"></div>
|
||||
<!-- body -->
|
||||
<div style="position:relative; height:clamp(120px,17vw,178px); background:linear-gradient(180deg,#f2f0ea 0%,#dfdbd0 100%); border-radius:22px 30px 12px 12px; box-shadow:0 18px 30px -10px rgba(0,0,0,.6); overflow:hidden">
|
||||
<!-- red stripe -->
|
||||
<div style="position:absolute; bottom:24%; left:0; right:0; height:15%; background:var(--red)"></div>
|
||||
<!-- windshield -->
|
||||
<div style="position:absolute; top:14%; right:5%; width:20%; height:42%; background:linear-gradient(120deg,#8fb4d8,#4d6f96); border-radius:6px 14px 6px 6px"></div>
|
||||
<!-- windows -->
|
||||
<div style="position:absolute; top:14%; left:6%; width:66%; height:42%; border-radius:6px; background-image:linear-gradient(90deg, transparent 0 3%, #6f92b8 3% 15%, transparent 15% 18%); background-size:16.6% 100%; background-repeat:repeat-x; background-color:#4d6f96"></div>
|
||||
<!-- brand on bus -->
|
||||
<div class="display" style="position:absolute; bottom:6%; left:7%; font-size:clamp(11px,1.5vw,15px); color:var(--ink); letter-spacing:1px">UNGER<span style="color:var(--red)"> REISEN</span></div>
|
||||
<!-- door -->
|
||||
<div style="position:absolute; top:14%; right:27%; width:8%; height:70%; background:#37506f; border-radius:4px"></div>
|
||||
</div>
|
||||
<!-- wheels -->
|
||||
<div class="wheelSpin" style="position:absolute; bottom:-14px; left:16%; width:clamp(42px,6vw,60px); height:clamp(42px,6vw,60px); border-radius:50%; background:#14181f; border:6px solid #23262e; animation:wheel .5s linear infinite">
|
||||
<div style="position:absolute; inset:34%; background:#3a3f49; border-radius:50%"></div>
|
||||
<div style="position:absolute; top:2px; left:50%; width:2px; height:40%; background:#454a55; transform:translateX(-50%)"></div>
|
||||
</div>
|
||||
<div class="wheelSpin" style="position:absolute; bottom:-14px; right:18%; width:clamp(42px,6vw,60px); height:clamp(42px,6vw,60px); border-radius:50%; background:#14181f; border:6px solid #23262e; animation:wheel .5s linear infinite">
|
||||
<div style="position:absolute; inset:34%; background:#3a3f49; border-radius:50%"></div>
|
||||
<div style="position:absolute; top:2px; left:50%; width:2px; height:40%; background:#454a55; transform:translateX(-50%)"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- STATS BAND -->
|
||||
<section style="background:var(--red); color:#fff; padding:clamp(34px,5vw,54px) clamp(20px,5vw,60px)">
|
||||
<div style="display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:30px">
|
||||
<sc-for list="{{ stats }}" as="s" hint-placeholder-count="4">
|
||||
<div data-reveal>
|
||||
<div class="display" style="font-size:clamp(44px,6vw,72px); color:#fff; line-height:.85">{{ s.big }}</div>
|
||||
<div style="font-size:14px; font-weight:600; margin-top:10px; color:rgba(255,255,255,.85)">{{ s.label }}</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- LEISTUNGEN -->
|
||||
<section id="leistungen" style="padding:clamp(70px,10vw,130px) clamp(20px,5vw,60px)">
|
||||
<div data-reveal style="display:flex; align-items:flex-end; justify-content:space-between; flex-wrap:wrap; gap:20px; margin-bottom:54px">
|
||||
<h2 class="display" style="font-size:clamp(40px,7vw,96px); color:#fff; max-width:12ch">Das fahren wir für Sie</h2>
|
||||
<p style="max-width:320px; color:var(--muted); font-size:16px">Ein Ansprechpartner, ein Bus, alles organisiert — von der Anfrage bis zur Rückfahrt.</p>
|
||||
</div>
|
||||
<div style="display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:16px">
|
||||
<sc-for list="{{ services }}" as="s" hint-placeholder-count="4">
|
||||
<div data-reveal style="position:relative; background:#111725; border:1px solid var(--line); padding:38px 30px 34px; min-height:260px; display:flex; flex-direction:column; overflow:hidden; transition:background .3s ease, transform .3s ease" style-hover="background:#151d30; transform:translateY(-4px)">
|
||||
<div class="display" style="font-size:60px; color:rgba(228,0,43,.9); line-height:.8">{{ s.no }}</div>
|
||||
<h3 style="font-size:22px; font-weight:800; margin:auto 0 10px; text-transform:uppercase; letter-spacing:.3px">{{ s.title }}</h3>
|
||||
<p style="font-size:15px; color:var(--muted); line-height:1.55">{{ s.desc }}</p>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- REAL PHOTO BAND -->
|
||||
<section style="position:relative; height:clamp(320px,48vw,520px); overflow:hidden; display:flex; align-items:center; justify-content:center; text-align:center">
|
||||
<img src="https://www.unger-reisen.de/wp-content/uploads/startslider-bus-1024x366.png" alt="Unger Reisen Reisebus" style="position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:center" onerror="this.parentNode.style.background='linear-gradient(135deg,#151d30,#0a0e18)'; this.style.display='none'">
|
||||
<div style="position:absolute; inset:0; background:linear-gradient(180deg, rgba(10,14,24,.55), rgba(10,14,24,.75))"></div>
|
||||
<div data-reveal style="position:relative; z-index:2; padding:20px">
|
||||
<div class="display" style="font-size:clamp(30px,5vw,64px); color:#fff; max-width:16ch; margin:0 auto">Komfort, auf den Sie sich verlassen können.</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FLOTTE -->
|
||||
<section id="flotte" style="padding:clamp(70px,10vw,130px) clamp(20px,5vw,60px)">
|
||||
<div data-reveal style="margin-bottom:48px">
|
||||
<div style="font-size:12px; font-weight:700; letter-spacing:3px; text-transform:uppercase; color:var(--red); margin-bottom:16px">Unsere Flotte</div>
|
||||
<h2 class="display" style="font-size:clamp(40px,7vw,90px); color:#fff">Für jede Gruppengröße</h2>
|
||||
</div>
|
||||
<div style="display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:16px">
|
||||
<sc-for list="{{ fleet }}" as="f" hint-placeholder-count="3">
|
||||
<div data-reveal style="border:1px solid var(--line); background:#111725; display:flex; flex-direction:column">
|
||||
<div style="padding:34px 30px 22px; border-bottom:1px solid var(--line); display:flex; align-items:center; justify-content:space-between; gap:16px">
|
||||
<h3 class="display" style="font-size:30px; color:#fff">{{ f.name }}</h3>
|
||||
<div style="display:flex; align-items:baseline; gap:8px; white-space:nowrap">
|
||||
<span style="font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:1px">bis</span>
|
||||
<span class="display" style="font-size:40px; color:var(--red); line-height:1">{{ f.seats }}</span>
|
||||
<span style="font-size:12px; color:var(--muted); text-transform:uppercase; letter-spacing:1px">Sitze</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding:24px 30px 30px">
|
||||
<p style="font-size:15px; color:var(--muted); line-height:1.55; margin-bottom:20px">{{ f.desc }}</p>
|
||||
<div style="display:flex; flex-wrap:wrap; gap:8px">
|
||||
<sc-for list="{{ f.tags }}" as="t" hint-placeholder-count="3">
|
||||
<span style="font-size:12px; font-weight:600; border:1px solid var(--line); padding:6px 13px; color:#c8cdda">{{ t }}</span>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- KONTAKT + KARTE -->
|
||||
<section id="kontakt" style="padding:clamp(70px,10vw,130px) clamp(20px,5vw,60px)">
|
||||
<div data-reveal style="margin-bottom:48px">
|
||||
<div style="font-size:12px; font-weight:700; letter-spacing:3px; text-transform:uppercase; color:var(--red); margin-bottom:16px">So erreichen Sie uns</div>
|
||||
<h2 class="display" style="font-size:clamp(40px,7vw,90px); color:#fff">Zwei Standorte.<br>Ein Anruf.</h2>
|
||||
</div>
|
||||
|
||||
<div style="display:grid; grid-template-columns:1.35fr .95fr; gap:20px; align-items:stretch">
|
||||
|
||||
<!-- SPECIAL MAP (interactive MapLibre) -->
|
||||
<div data-reveal style="position:relative; border:1px solid var(--line); background:#0d1420; overflow:hidden; min-height:440px; border-radius:2px">
|
||||
<div id="unger-map" style="position:absolute; inset:0"></div>
|
||||
<div style="position:absolute; left:16px; bottom:16px; z-index:2; pointer-events:none; background:rgba(10,14,24,.85); backdrop-filter:blur(6px); border:1px solid var(--line); padding:10px 14px; display:flex; align-items:center; gap:10px">
|
||||
<span class="display" style="font-size:20px; color:var(--red)">15 km</span>
|
||||
<span style="font-size:11px; color:#9aa6c0; text-transform:uppercase; letter-spacing:1px; font-weight:700; line-height:1.2">zwischen<br>den Standorten</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CONTACT CARD -->
|
||||
<div data-reveal style="border:1px solid var(--line); background:#111725; padding:clamp(28px,3vw,40px); display:flex; flex-direction:column; gap:30px">
|
||||
<div style="display:flex; gap:16px">
|
||||
<div style="width:14px; height:14px; border-radius:50%; background:#fff; border:4px solid var(--red); flex-shrink:0; margin-top:4px"></div>
|
||||
<div>
|
||||
<div style="font-size:11px; font-weight:800; letter-spacing:2px; text-transform:uppercase; color:var(--red); margin-bottom:6px">Hauptsitz</div>
|
||||
<div style="font-size:17px; font-weight:700; color:#fff; line-height:1.4">Eichenstr. 7+9, Vatersdorf<br>84172 Buch am Erlbach</div>
|
||||
<a href="tel:+498762896" style="display:inline-block; margin-top:8px; font-size:15px; font-weight:600; color:#c8cdda">Tel. +49 (0)8762 / 896</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="height:1px; background:var(--line)"></div>
|
||||
|
||||
<div style="display:flex; gap:16px">
|
||||
<div style="width:14px; height:14px; border-radius:50%; background:var(--red); border:4px solid rgba(255,255,255,.25); flex-shrink:0; margin-top:4px"></div>
|
||||
<div>
|
||||
<div style="font-size:11px; font-weight:800; letter-spacing:2px; text-transform:uppercase; color:var(--red); margin-bottom:6px">Niederlassung</div>
|
||||
<div style="font-size:17px; font-weight:700; color:#fff; line-height:1.4">Jenaer Straße 4a<br>84034 Landshut</div>
|
||||
<a href="tel:+4987196585860" style="display:inline-block; margin-top:8px; font-size:15px; font-weight:600; color:#c8cdda">Tel. +49 (0)871 / 96 58 586-0</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top:auto; display:flex; flex-direction:column; gap:12px">
|
||||
<a href="tel:+498762896" style="background:var(--red); color:#fff; padding:16px; text-align:center; font-size:14px; font-weight:700; text-transform:uppercase; letter-spacing:1px; transition:transform .2s ease" style-hover="transform:translateY(-2px); color:#fff">Jetzt anrufen</a>
|
||||
<a href="mailto:info@unger-reisen.de" style="border:1.5px solid var(--line); color:#fff; padding:16px; text-align:center; font-size:14px; font-weight:700; text-transform:uppercase; letter-spacing:1px; transition:border-color .2s ease" style-hover="border-color:#fff">info@unger-reisen.de</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- KARRIERE -->
|
||||
<section id="karriere" style="padding:clamp(60px,8vw,110px) clamp(20px,5vw,60px)">
|
||||
<div data-reveal style="border:1px solid var(--line); padding:clamp(34px,5vw,60px); display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:28px">
|
||||
<div style="max-width:600px">
|
||||
<div style="font-size:12px; font-weight:700; letter-spacing:3px; text-transform:uppercase; color:var(--red); margin-bottom:16px">Karriere & Jobs</div>
|
||||
<h2 class="display" style="font-size:clamp(34px,5vw,62px); color:#fff; margin-bottom:14px">Fahren Sie mit uns</h2>
|
||||
<p style="font-size:16px; color:var(--muted)">Wir suchen Busfahrer:innen, Begleitpersonen und Sachbearbeiter:innen — steigen Sie ein.</p>
|
||||
</div>
|
||||
<a href="mailto:info@unger-reisen.de" style="background:#fff; color:var(--ink); padding:17px 34px; font-size:14px; font-weight:700; text-transform:uppercase; letter-spacing:1px; white-space:nowrap; transition:transform .2s ease" style-hover="transform:translateY(-2px); color:var(--ink)">Offene Stellen →</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<footer style="border-top:1px solid var(--line); padding:clamp(50px,6vw,80px) clamp(20px,5vw,60px) 40px">
|
||||
<div style="display:grid; grid-template-columns:1.4fr 1fr 1fr; gap:40px; padding-bottom:44px; border-bottom:1px solid var(--line)">
|
||||
<div>
|
||||
<div style="display:flex; align-items:baseline; gap:9px; margin-bottom:18px">
|
||||
<span class="display" style="font-size:30px; color:#fff">UNGER</span>
|
||||
<span style="font-weight:700; font-size:11px; letter-spacing:5px; color:var(--red)">REISEN</span>
|
||||
</div>
|
||||
<p style="font-size:15px; color:var(--muted); max-width:300px">Günter Unger e.K. — Omnibus- & Verkehrsunternehmen. Reisen erster Klasse aus Niederbayern.</p>
|
||||
</div>
|
||||
<div style="font-size:14.5px; color:var(--muted); line-height:1.9">
|
||||
<div style="color:#fff; font-weight:700; margin-bottom:12px; letter-spacing:1.5px; font-size:12px; text-transform:uppercase">Hauptsitz</div>
|
||||
Eichenstr. 7+9, Vatersdorf<br>84172 Buch am Erlbach<br><a href="tel:+498762896" style="color:var(--muted)">Tel. +49 (0)8762 / 896</a>
|
||||
</div>
|
||||
<div style="font-size:14.5px; color:var(--muted); line-height:1.9">
|
||||
<div style="color:#fff; font-weight:700; margin-bottom:12px; letter-spacing:1.5px; font-size:12px; text-transform:uppercase">Niederlassung</div>
|
||||
Jenaer Straße 4a<br>84034 Landshut<br><a href="tel:+4987196585860" style="color:var(--muted)">Tel. +49 (0)871 / 96 58 586-0</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex; justify-content:space-between; flex-wrap:wrap; gap:14px; padding-top:24px; font-size:13px; color:#5a6274">
|
||||
<div>© 2026 Unger Reisen · Alle Rechte vorbehalten</div>
|
||||
<div style="display:flex; gap:22px">
|
||||
<a href="#" style="color:#5a6274">Impressum</a>
|
||||
<a href="#" style="color:#5a6274">Datenschutz</a>
|
||||
<a href="#" style="color:#5a6274">AGB</a>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top:26px; font-size:11px; color:#40485a">Konzept-Entwurf für ein mögliches Website-Redesign · noch nicht offiziell.</div>
|
||||
</footer>
|
||||
</div>
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props="{"$preview":{"width":1280,"height":900},"accentColor":{"editor":"color","default":"#C8102E","tsType":"string","options":["#E4002B","#D21F1F","#C8102E","#EE3524"],"section":"Design"}}">
|
||||
class Component extends DCLogic {
|
||||
state = { submitted:false, name:'', contact:'', dest:'', date:'', pax:'', msg:'' };
|
||||
|
||||
componentDidMount(){
|
||||
this.applyTweaks();
|
||||
this.initMap();
|
||||
// Scroll-driven bus: drives left→right across the hero as you scroll
|
||||
this._reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion:reduce)').matches;
|
||||
this._tick = () => {
|
||||
const bus = document.querySelector('.busBob');
|
||||
const hero = document.getElementById('top');
|
||||
if(bus && hero){
|
||||
const hp = Math.min(1, Math.max(0, window.scrollY / (hero.offsetHeight * 0.9)));
|
||||
const scene = bus.parentNode;
|
||||
const sceneW = scene ? scene.offsetWidth : window.innerWidth;
|
||||
const busW = bus.offsetWidth || 400;
|
||||
const minX = -busW * 0.30;
|
||||
const maxX = sceneW - busW * 0.70;
|
||||
const x = minX + (maxX - minX) * hp;
|
||||
const bob = this._reduce ? 0 : Math.sin(Date.now() / 380) * 4;
|
||||
bus.style.transform = 'translate(' + x.toFixed(1) + 'px,' + bob.toFixed(1) + 'px)';
|
||||
}
|
||||
this._raf = requestAnimationFrame(this._tick);
|
||||
};
|
||||
this._raf = requestAnimationFrame(this._tick);
|
||||
const nav = document.querySelector('[data-nav="1"]');
|
||||
const onScroll = () => {
|
||||
if(!nav) return;
|
||||
if(window.scrollY > 40){
|
||||
nav.style.background = 'rgba(10,14,24,.9)';
|
||||
nav.style.backdropFilter = 'blur(12px)';
|
||||
nav.style.webkitBackdropFilter = 'blur(12px)';
|
||||
nav.style.top = '0px';
|
||||
nav.style.padding = '14px clamp(20px,5vw,60px)';
|
||||
nav.style.boxShadow = '0 1px 0 rgba(255,255,255,.08)';
|
||||
} else {
|
||||
nav.style.background = 'transparent';
|
||||
nav.style.backdropFilter = 'none';
|
||||
nav.style.webkitBackdropFilter = 'none';
|
||||
nav.style.top = '39px';
|
||||
nav.style.padding = '22px clamp(20px,5vw,60px)';
|
||||
nav.style.boxShadow = 'none';
|
||||
}
|
||||
};
|
||||
this._onScroll = onScroll;
|
||||
window.addEventListener('scroll', onScroll, {passive:true});
|
||||
onScroll();
|
||||
|
||||
const els = Array.from(document.querySelectorAll('[data-reveal]'));
|
||||
els.forEach(el=>{ el.style.opacity='0'; el.style.transform='translateY(28px)'; el.style.transition='opacity .7s cubic-bezier(.2,.7,.2,1), transform .7s cubic-bezier(.2,.7,.2,1)'; });
|
||||
if('IntersectionObserver' in window){
|
||||
const io = new IntersectionObserver((ents)=>{
|
||||
ents.forEach(e=>{ if(e.isIntersecting){ e.target.style.opacity='1'; e.target.style.transform='none'; io.unobserve(e.target); } });
|
||||
},{threshold:0.12});
|
||||
els.forEach(el=>io.observe(el));
|
||||
this._io = io;
|
||||
} else { els.forEach(el=>{ el.style.opacity='1'; el.style.transform='none'; }); }
|
||||
this._fallback = setTimeout(()=>els.forEach(el=>{ el.style.opacity='1'; el.style.transform='none'; }), 2500);
|
||||
}
|
||||
|
||||
componentDidUpdate(){ this.applyTweaks(); }
|
||||
componentWillUnmount(){
|
||||
if(this._onScroll) window.removeEventListener('scroll', this._onScroll);
|
||||
if(this._io) this._io.disconnect();
|
||||
if(this._fallback) clearTimeout(this._fallback);
|
||||
if(this._raf) cancelAnimationFrame(this._raf);
|
||||
if(this._mapTimer) clearTimeout(this._mapTimer);
|
||||
if(this._map){ try{ this._map.remove(); }catch(e){} this._map=null; }
|
||||
}
|
||||
|
||||
initMap(){
|
||||
const HOME=[12.0517,48.4703]; // Buch am Erlbach / Vatersdorf
|
||||
const BRANCH=[12.1508,48.5449]; // Landshut
|
||||
const RED = this.props.accentColor || '#C8102E';
|
||||
const makePin=(fill, ring, title, sub)=>{
|
||||
const wrap=document.createElement('div');
|
||||
wrap.style.cssText='display:flex;flex-direction:column;align-items:center;gap:6px';
|
||||
const label=document.createElement('div');
|
||||
label.style.cssText='background:rgba(10,14,24,.9);border:1px solid rgba(255,255,255,.16);padding:5px 10px;white-space:nowrap;text-align:center;border-radius:2px';
|
||||
label.innerHTML='<div style="font-family:Anton,sans-serif;text-transform:uppercase;color:#fff;font-size:14px;letter-spacing:.5px;line-height:1.05">'+title+'</div><div style="font-family:Archivo,sans-serif;font-size:9px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:#9aa6c0;margin-top:2px">'+sub+'</div>';
|
||||
const dot=document.createElement('div');
|
||||
dot.style.cssText='width:18px;height:18px;border-radius:50%;background:'+fill+';border:3px solid '+ring+';box-shadow:0 0 0 5px '+RED+'40, 0 2px 6px rgba(0,0,0,.55)';
|
||||
wrap.appendChild(label); wrap.appendChild(dot);
|
||||
return wrap;
|
||||
};
|
||||
const start=()=>{
|
||||
if(!window.maplibregl){ this._mapTimer=setTimeout(start,120); return; }
|
||||
const el=document.getElementById('unger-map');
|
||||
if(!el){ this._mapTimer=setTimeout(start,120); return; }
|
||||
if(this._map) return;
|
||||
const map=new maplibregl.Map({
|
||||
container: el,
|
||||
style: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
|
||||
center: [(HOME[0]+BRANCH[0])/2, (HOME[1]+BRANCH[1])/2],
|
||||
zoom: 10.4,
|
||||
attributionControl: { compact: true }
|
||||
});
|
||||
this._map=map;
|
||||
map.scrollZoom.disable();
|
||||
map.addControl(new maplibregl.NavigationControl({ showCompass:true, visualizePitch:false }), 'top-right');
|
||||
new maplibregl.Marker({ element: makePin(RED,'#fff','Landshut','Niederlassung'), anchor:'bottom' }).setLngLat(BRANCH).addTo(map);
|
||||
new maplibregl.Marker({ element: makePin('#fff',RED,'Buch a. Erlbach','Hauptsitz'), anchor:'bottom' }).setLngLat(HOME).addTo(map);
|
||||
map.on('load',()=>{
|
||||
map.addSource('unger-route',{ type:'geojson', data:{ type:'Feature', properties:{}, geometry:{ type:'LineString', coordinates:[HOME,BRANCH] } } });
|
||||
map.addLayer({ id:'unger-route-casing', type:'line', source:'unger-route', layout:{'line-join':'round','line-cap':'round'}, paint:{'line-color':RED,'line-width':9,'line-opacity':.18} });
|
||||
map.addLayer({ id:'unger-route-line', type:'line', source:'unger-route', layout:{'line-join':'round','line-cap':'round'}, paint:{'line-color':RED,'line-width':3,'line-dasharray':[1.6,1.4]} });
|
||||
map.fitBounds([HOME,BRANCH],{ padding:{top:96,bottom:70,left:70,right:70}, duration:0, maxZoom:12 });
|
||||
setTimeout(()=>{ try{ map.resize(); }catch(e){} }, 60);
|
||||
});
|
||||
};
|
||||
start();
|
||||
}
|
||||
|
||||
applyTweaks(){
|
||||
const root = document.documentElement;
|
||||
if(this.props.accentColor) root.style.setProperty('--red', this.props.accentColor);
|
||||
const RED = this.props.accentColor;
|
||||
if(RED && this._map && this._map.getLayer && this._map.getLayer('unger-route-line')){
|
||||
try{ this._map.setPaintProperty('unger-route-line','line-color',RED);
|
||||
this._map.setPaintProperty('unger-route-casing','line-color',RED); }catch(e){}
|
||||
}
|
||||
}
|
||||
|
||||
field(key){ return (e)=> this.setState({[key]: e.target.value}); }
|
||||
|
||||
renderVals(){
|
||||
return {
|
||||
submitted:this.state.submitted,
|
||||
notSubmitted:!this.state.submitted,
|
||||
f_name:this.state.name, f_contact:this.state.contact, f_dest:this.state.dest,
|
||||
f_date:this.state.date, f_pax:this.state.pax, f_msg:this.state.msg,
|
||||
onName:this.field('name'), onContact:this.field('contact'), onDest:this.field('dest'),
|
||||
onDate:this.field('date'), onPax:this.field('pax'), onMsg:this.field('msg'),
|
||||
onSubmit:()=>this.setState({submitted:true}),
|
||||
stats:[
|
||||
{big:'2', label:'Standorte in Bayern'},
|
||||
{big:'60+', label:'Sitzplätze pro Reisebus'},
|
||||
{big:'24/7', label:'Für Sie erreichbar'},
|
||||
{big:'∞', label:'Ziele in ganz Europa'}
|
||||
],
|
||||
services:[
|
||||
{no:'01', title:'Busanmietung', desc:'Moderne Reisebusse mit Fahrer — flexibel für einzelne Fahrten oder mehrtägige Touren.'},
|
||||
{no:'02', title:'Firmenreisen', desc:'Betriebsausflüge, Tagungen und Events. Ihr Team sicher und entspannt am Ziel.'},
|
||||
{no:'03', title:'Vereinsfahrten', desc:'Ausflüge, Feste und Sportevents — komfortabel für die ganze Gruppe.'},
|
||||
{no:'04', title:'Transfers', desc:'Flughafen-, Hotel- und Event-Transfers. Pünktlich und rund um die Uhr planbar.'}
|
||||
],
|
||||
fleet:[
|
||||
{name:'Reisebus', seats:'60', desc:'Der Große für lange Strecken und große Gruppen — voll ausgestattet.', tags:['Klimaanlage','WC','Bordküche','WLAN']},
|
||||
{name:'Midibus', seats:'35', desc:'Wendig und komfortabel — ideal für mittlere Gruppen und Tagestouren.', tags:['Klimaanlage','Komfortbestuhlung']},
|
||||
{name:'Kleinbus', seats:'19', desc:'Persönlich und flexibel für kleine Gruppen, Transfers und Sonderfahrten.', tags:['Flexibel','Wendig']}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1702
design_handoff_unger_reisen/support.js
Normal file
1702
design_handoff_unger_reisen/support.js
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user