From 0805824e8bb4488b62df969adaa3a2ce1cb7628c Mon Sep 17 00:00:00 2001 From: root Date: Fri, 2 Oct 2026 09:50:52 +0000 Subject: [PATCH] Take-away neu: Karte der Umgebung, Pin am Restaurant, Lieferweg zum Zuhause MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Eigene Karten-Grafik (assets/img/map-kaiserslautern.svg) aus OpenStreetMap-Daten rund um die Merkurstraße 13, in Gelbtönen, blendet weich in den Hintergrund und läuft rechts aus dem Bild - Roter Pin mit Hahn am Restaurant, Karte 'Vor Ort essen oder abholen' mit Route planen und Anrufen - Gepunkteter Weg die Merkurstraße entlang bis zum App-Symbol 'Zuhause', Karte 'Nach Hause liefern' mit Lieferando und Uber Eats; Weg zeichnet sich beim Scrollen, der Hahn fährt mit - Handy: Kartenausschnitt mit Pin, darunter die beiden Karten mit Punktlinie - Gelbe Papierkante jetzt am Ende des Bucket-Abschnitts (Take-away schneidet die Karte ab) Co-Authored-By: Claude Opus 5.5 --- assets/css/style.css | 124 +++++++++++++++++++++++------- assets/img/map-kaiserslautern.svg | 1 + assets/js/main.js | 52 +++++++------ index.html | 56 +++++++------- 4 files changed, 154 insertions(+), 79 deletions(-) create mode 100644 assets/img/map-kaiserslautern.svg diff --git a/assets/css/style.css b/assets/css/style.css index 0df3d43..d7e5a3d 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -724,39 +724,92 @@ body.menu-open .menu-panel { transform: scale(1); opacity: 1; visibility: visibl .buckets__note { margin-top: 2.5rem; text-align: center; opacity: .8; font-size: .95rem; } /* ============ Take away (route) ============ */ -.takeaway { overflow-x: clip; background: var(--yellow); color: var(--ink); --spot: rgba(255, 255, 220, .5); --spot-x: 25%; --spot-y: 25%; --dot: rgba(229, 19, 11, .85); --dots-o: .16; --dots-mask: linear-gradient(200deg, #000, transparent 50%); --mottle-o: .06; --grain-o: .1; } -.takeaway .torn { color: var(--yellow); } -.takeaway__burst { right: -12%; top: -8%; width: min(900px, 70vw); aspect-ratio: 1; background: repeating-conic-gradient(rgba(229, 19, 11, .14) 0 6deg, transparent 6deg 15deg); -webkit-mask: radial-gradient(closest-side, #000 25%, transparent); mask: radial-gradient(closest-side, #000 25%, transparent); } -.takeaway .h2 { color: var(--white); --stroke-c: var(--ink); --sw: .04em; --ext: var(--ink); max-width: 13ch; } +.takeaway { overflow: clip; background: var(--yellow); color: var(--ink); --spot: rgba(255, 255, 220, .5); --spot-x: 25%; --spot-y: 25%; --dot: rgba(229, 19, 11, .85); --dots-o: .16; --dots-mask: linear-gradient(200deg, #000, transparent 50%); --mottle-o: .06; --grain-o: .1; } +.takeaway .h2 { color: var(--white); --stroke-c: var(--ink); --sw: .04em; --ext: var(--ink); max-width: 13ch; position: relative; z-index: 3; } +.takeaway .kicker, .takeaway__lead { position: relative; z-index: 3; } .takeaway__lead { max-width: 40ch; margin-top: 1.4rem; font-weight: 500; } -.route { position: relative; margin-top: clamp(6rem, 10vw, 9rem); } -.route__svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; } -.route__svg path { fill: none; stroke: var(--ink); stroke-width: 3; stroke-dasharray: 10 12; stroke-linecap: round; opacity: .55; } -.route__rider { position: absolute; left: 0; top: 0; width: clamp(64px, 7vw, 100px); z-index: 3; will-change: transform; pointer-events: none; } -.stops { position: relative; z-index: 2; display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.2rem, 3vw, 3rem); align-items: start; } -.stop { - border: 3px solid var(--ink); border-radius: var(--radius); - padding: clamp(1.3rem, 2.4vw, 2rem); - box-shadow: 8px 8px 0 var(--ink), 14px 24px 34px rgba(90, 50, 0, .3); - transition: transform .45s var(--ease-pop), box-shadow .3s; + +/* Bühne: Karte rechts (läuft aus dem Bild), roter Pin am Restaurant, Weg nach links zum Zuhause */ +.tstage { + --mw: clamp(1050px, 88vw, 1650px); /* Breite der Karte; Restaurant liegt bei 40 % / 62 % */ + --pin-x: 70%; --pin-y: 50%; /* Restaurant auf der Bühne */ + --home-x: 8%; --home-y: 92%; + /* Bühne zieht sich rechts neben die Überschrift hoch, links bleibt der Text frei */ + position: relative; height: clamp(600px, 50vw, 760px); margin-top: clamp(-320px, -21vw, -200px); } -.stop:nth-child(2) { margin-top: clamp(2rem, 6vw, 6rem); } -.stop:nth-child(3) { margin-top: clamp(4rem, 12vw, 12rem); } -.stop:hover { transform: translate(-3px, -3px) rotate(-1deg); box-shadow: 12px 12px 0 var(--red), 20px 30px 40px rgba(90, 50, 0, .3); } -.stop__num { font-family: var(--f-display); font-size: 3.6rem; line-height: .8; color: var(--red); --ext: var(--oxblood); text-shadow: 1px 1px 0 var(--ext), 2px 2px 0 var(--ext), 3px 3px 0 var(--ext), 4px 4px 0 var(--ext); } -.stop h3 { font-family: var(--f-sticker); text-transform: uppercase; font-weight: 400; font-size: clamp(1.4rem, 1.1rem + 1vw, 1.9rem); line-height: 1; margin: .5rem 0 .6rem; } -.stop p { font-size: 1rem; } -.stop__links { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1rem; } -.stop__links a { +.tmap { + position: absolute; z-index: 0; pointer-events: none; + width: var(--mw); aspect-ratio: 1400 / 1080; + left: calc(var(--pin-x) - .4 * var(--mw)); top: calc(var(--pin-y) - .4783 * var(--mw)); +} +.tmap__img { + width: 100%; height: 100%; + -webkit-mask: radial-gradient(ellipse 58% 72% at 50% 56%, #000 45%, rgba(0, 0, 0, .6) 72%, transparent 100%); + mask: radial-gradient(ellipse 58% 72% at 50% 56%, #000 45%, rgba(0, 0, 0, .6) 72%, transparent 100%); +} +.troute { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 1; } +.troute path { fill: none; stroke-linecap: round; stroke-linejoin: round; } +.troute__glow { stroke: rgba(255, 255, 255, .55); stroke-width: 14; } +.troute__line { stroke: var(--red); stroke-width: 6; stroke-dasharray: .1 14; } +.troute__reveal { stroke: #fff; stroke-width: 30; } +.troute__rider { position: absolute; left: 0; top: 0; z-index: 2; width: clamp(42px, 3.6vw, 56px); pointer-events: none; will-change: transform; } + +.tspot { position: absolute; z-index: 2; width: 0; height: 0; } +.tspot--shop { left: var(--pin-x); top: var(--pin-y); } +.tspot--home { left: var(--home-x); top: var(--home-y); } +.tspot__minimap { display: none; } + +/* Pin: Tropfen mit Hahn, darunter ein pulsierender Punkt */ +.tpin { position: absolute; left: 0; top: 0; } +.tpin__dot { position: absolute; left: -10px; top: -10px; width: 20px; height: 20px; border-radius: 50%; background: var(--red); border: 4px solid #fff; box-shadow: 0 3px 8px rgba(80, 0, 0, .4); } +.tpin__dot::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; background: rgba(229, 19, 11, .45); animation: pin-pulse 2s ease-out infinite; z-index: -1; } +@keyframes pin-pulse { from { transform: scale(1); opacity: 1; } to { transform: scale(4.2); opacity: 0; } } +.tpin__head { + position: absolute; left: -32px; top: -86px; width: 64px; height: 64px; + border-radius: 50% 50% 50% 0; transform: rotate(-45deg); + background: linear-gradient(135deg, var(--red-hot), var(--red-deep)); + border: 4px solid #fff; box-shadow: -6px 10px 18px rgba(80, 0, 0, .4); + display: grid; place-items: center; +} +.tpin__head img { width: 64%; height: auto; transform: rotate(45deg) translateY(-1px); filter: drop-shadow(0 2px 2px rgba(0, 0, 0, .3)); } + +/* App-Symbol "Zuhause" */ +.tapp { position: absolute; left: -40px; top: -40px; width: 80px; display: flex; flex-direction: column; align-items: center; gap: .45rem; } +.tapp__icon { + width: 80px; height: 80px; border-radius: 24px; display: grid; place-items: center; color: #fff; + background: linear-gradient(160deg, #ff4b26, var(--red) 45%, var(--red-deep)); + box-shadow: inset 0 2px 0 rgba(255, 255, 255, .45), inset 0 -4px 0 rgba(0, 0, 0, .15), 0 14px 26px rgba(120, 40, 0, .35), 0 0 0 4px #fff; +} +.tapp__icon svg { width: 44px; height: 44px; filter: drop-shadow(0 2px 2px rgba(0, 0, 0, .25)); } +.tapp__label { font-weight: 700; font-size: .85rem; color: var(--ink); background: rgba(255, 255, 255, .7); border-radius: 999px; padding: .1em .6em; } + +/* Info-Karten über Pin und Zuhause */ +.tcard { + position: absolute; bottom: 106px; width: min(360px, 30vw); + border: 3px solid var(--ink); border-radius: var(--radius); + padding: clamp(1.1rem, 2vw, 1.6rem); + box-shadow: 8px 8px 0 var(--ink), 14px 24px 34px rgba(90, 50, 0, .3); +} +.tspot--shop .tcard { left: 0; translate: -50% 0; } +.tspot--home .tcard { left: -44px; bottom: 74px; } +.tcard::after { content: ""; position: absolute; bottom: -14px; width: 22px; height: 22px; background: inherit; border: solid var(--ink); border-width: 0 3px 3px 0; transform: rotate(45deg); background-color: #fdf4e3; } +.tspot--shop .tcard::after { left: calc(50% - 11px); } +.tspot--home .tcard::after { left: 33px; } +.tcard__kicker { display: inline-flex; align-items: center; gap: .4em; font-family: var(--f-mono); font-size: .76rem; text-transform: uppercase; letter-spacing: .08em; color: var(--red-deep); } +.tcard__kicker svg { width: 1.1em; height: 1.1em; } +.tcard h3 { font-family: var(--f-sticker); text-transform: uppercase; font-weight: 400; font-size: clamp(1.3rem, 1rem + 1vw, 1.8rem); line-height: 1; margin: .45rem 0 .5rem; } +.tcard p { font-size: .95rem; } +.tcard__links { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .9rem; } +.tcard__links a { display: inline-flex; align-items: center; gap: .4em; font-weight: 800; font-size: .95rem; text-decoration: none; padding: .55em .95em; border-radius: 999px; border: 2px solid var(--ink); transition: background-color .2s, color .2s; } -.stop__links a:hover { background: var(--ink); color: var(--yellow); } -.stop__links a.is-primary { background: var(--red); border-color: var(--red); color: var(--white); } -.stop__links a.is-primary:hover { background: var(--ink); border-color: var(--ink); } -.stop__links svg { width: 1em; height: 1em; } +.tcard__links a:hover { background: var(--ink); color: var(--yellow); } +.tcard__links a.is-primary { background: var(--red); border-color: var(--red); color: var(--white); } +.tcard__links a.is-primary:hover { background: var(--ink); border-color: var(--ink); } +.tcard__links svg { width: 1em; height: 1em; } /* ============ Visit ============ */ .visit { --mottle-o: .12; --grain-o: .16; } @@ -1173,9 +1226,22 @@ html.js.anim .juggle { visibility: hidden; } .classic-wings__prices { justify-content: flex-start; } .fight-card-row { grid-template-columns: 1fr; } .vs { justify-self: center; margin: -.5rem 0; } - .stops { grid-template-columns: 1fr; } - .stop:nth-child(2), .stop:nth-child(3) { margin-top: 0; } - .route__svg, .route__rider { display: none; } + .tstage { height: auto; display: flex; flex-direction: column; gap: 2.4rem; margin-top: 1.5rem; } + .tmap, .troute, .troute__rider { display: none; } + .tspot { position: relative; left: auto; top: auto; width: auto; height: auto; } + .tspot__minimap { + display: block; position: relative; height: 300px; margin: 0 calc(-1 * var(--gutter)); overflow: hidden; + -webkit-mask: radial-gradient(ellipse 70% 50% at 50% 50%, #000 40%, transparent 100%); mask: radial-gradient(ellipse 70% 50% at 50% 50%, #000 40%, transparent 100%); + } + .tspot__minimap img { position: absolute; width: 900px; max-width: none; left: calc(50% - 360px); top: calc(50% - 430px); } + .tspot--shop .tpin { left: 50%; top: 150px; } + .tcard, .tspot--shop .tcard, .tspot--home .tcard { position: relative; left: auto; bottom: auto; width: auto; translate: none; } + .tspot--shop .tcard { margin-top: -2.2rem; } + .tcard::after, .tspot--shop .tcard::after, .tspot--home .tcard::after { bottom: auto; top: -14px; left: calc(50% - 11px); transform: rotate(-135deg); } + .tspot--home { display: flex; flex-direction: column; align-items: center; } + .tspot--home::before { content: ""; height: 70px; border-left: 6px dotted var(--red); margin: -1rem 0 1.2rem; } + .tapp { position: relative; left: auto; top: auto; } + .tspot--home .tcard { margin-top: 1.6rem; align-self: stretch; } .orderbar { display: flex; } .cta__rooster { width: 46vw; margin-top: -.5rem; } .footer { padding-bottom: 5.5rem; } diff --git a/assets/img/map-kaiserslautern.svg b/assets/img/map-kaiserslautern.svg new file mode 100644 index 0000000..c854087 --- /dev/null +++ b/assets/img/map-kaiserslautern.svg @@ -0,0 +1 @@ +MERKURSTRASSEVOGELWOOGSTRASSEREICHSWALDSTR. \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index d7183d1..d924fce 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -392,43 +392,47 @@ }); } - /* ---------- Route (Take away) ---------- */ - var route = $('[data-route]'); + /* ---------- Lieferweg (Take away): vom Pin die Merkurstraße entlang, dann zum Zuhause ---------- */ + // Merkurstraße ab dem Restaurant nach Westen, in % der Karte (aus OpenStreetMap, siehe map-kaiserslautern.svg) + var STREET = [[40, 62.04], [39.64, 60.93], [35.86, 62.41], [32.14, 63.33], [24.29, 65.37], [18.79, 66.85], [10.07, 68.98]]; + var route = $('[data-delivery]'); var routeState = null; function buildRoute() { if (!route) return null; - var svg = $('.route__svg', route), path = $('path', svg), stops = $$('.stop', route); - if (!stops.length || window.getComputedStyle(svg).display === 'none') return null; - var box = route.getBoundingClientRect(); - var pts = stops.map(function (s) { - var r = s.getBoundingClientRect(); - return { x: r.left - box.left + r.width * .5, y: r.top - box.top - 34 }; - }); - var start = { x: Math.max(40, pts[0].x - box.width * .2), y: pts[0].y + 6 }; - var d = 'M' + start.x + ' ' + start.y; - var prev = start; - pts.forEach(function (p, i) { - var dx = p.x - prev.x; - var lift = i % 2 ? 90 : -70; - d += ' C' + (prev.x + dx * .45) + ' ' + (prev.y + lift) + ' ' + (p.x - dx * .45) + ' ' + (p.y - lift) + ' ' + p.x + ' ' + p.y; - prev = p; - }); - path.setAttribute('d', d); - return { path: path, len: path.getTotalLength(), rider: $('.route__rider', route) }; + var map = $('.tmap', route), svg = $('.troute', route); + var home = $('.tspot--home', route); + if (!map || window.getComputedStyle(map).display === 'none') return null; + var mx = map.offsetLeft, my = map.offsetTop, mw = map.offsetWidth, mh = map.offsetHeight; + var pts = STREET.map(function (p) { return [mx + p[0] / 100 * mw, my + p[1] / 100 * mh]; }); + var end = [home.offsetLeft, home.offsetTop], last = pts[pts.length - 1]; + var d = 'M' + pts.map(function (p) { return p[0].toFixed(1) + ' ' + p[1].toFixed(1); }).join(' L'); + // Bogen nach unten-links, unter der Liefer-Karte hindurch, und von rechts zum Zuhause + d += ' C' + (last[0] - 40).toFixed(1) + ' ' + (last[1] + 160).toFixed(1) + ' ' + + (end[0] + 220).toFixed(1) + ' ' + (end[1] + 10).toFixed(1) + ' ' + end[0].toFixed(1) + ' ' + end[1].toFixed(1); + $$('path', svg).forEach(function (p) { p.setAttribute('d', d); }); + var line = $('.troute__line', svg), reveal = $('.troute__reveal', svg); + var len = line.getTotalLength(); + reveal.style.strokeDasharray = len + ' ' + len; + return { path: line, reveal: reveal, len: len, rider: $('.troute__rider', route) }; } function placeRider(progress) { if (!routeState) return; - var pt = routeState.path.getPointAtLength(routeState.len * progress); - var ahead = routeState.path.getPointAtLength(Math.min(routeState.len, routeState.len * progress + 4)); + routeState.reveal.style.strokeDashoffset = routeState.len * (1 - progress); + var at = Math.max(.02, Math.min(.98, progress)); + var pt = routeState.path.getPointAtLength(routeState.len * at); + var ahead = routeState.path.getPointAtLength(Math.min(routeState.len, routeState.len * at + 4)); var angle = Math.atan2(ahead.y - pt.y, ahead.x - pt.x) * 180 / Math.PI; var w = routeState.rider.offsetWidth, h = routeState.rider.offsetHeight; - routeState.rider.style.transform = 'translate(' + (pt.x - w / 2) + 'px,' + (pt.y - h / 2) + 'px) rotate(' + (angle * .25) + 'deg)'; + // Hahn schaut in Fahrtrichtung (nach links), leicht geneigt + routeState.rider.style.transform = 'translate(' + (pt.x - w / 2) + 'px,' + (pt.y - h * .85) + 'px) scaleX(-1) rotate(' + ((angle - 180) * -.2) + 'deg)'; } /* ---------- Ohne GSAP: fertig ---------- */ if (!hasGsap) { routeState = buildRoute(); placeRider(1); + if (routeState) routeState.rider.style.visibility = 'hidden'; + window.addEventListener('resize', function () { routeState = buildRoute(); placeRider(1); }); return; } @@ -465,6 +469,8 @@ if (reduce) { routeState = buildRoute(); placeRider(1); + if (routeState) routeState.rider.style.visibility = 'hidden'; + window.addEventListener('resize', function () { routeState = buildRoute(); placeRider(1); }); return; } diff --git a/index.html b/index.html index 1fbf801..2f18ff1 100644 --- a/index.html +++ b/index.html @@ -301,44 +301,46 @@

Lieber einzeln? Tenders gibt’s ab 5 Stück, Menüs mit Pommes und Coleslaw – alles auf der Karte.

+
- - +
Take away -

Hol’s dir. Oder lass kommen.

-

Drei Wege zu deinem Chicken – alle starten in der Merkurstraße 13.

+

Hol’s dir. Oder lass kommen.

+

Zwei Wege zu deinem Chicken: vorbeikommen in der Merkurstraße 13 – oder liefern lassen, direkt bis vor deine Tür.

-
- - -
-
-
01
-

Vor Ort essen

-

Restaurant & Bar mit Plätzen drinnen und draußen. Einfach vorbeikommen – mit größerer Gruppe am besten vorher anrufen.

-