diff --git a/css/leistungen.css b/css/leistungen.css new file mode 100644 index 0000000..2b45352 --- /dev/null +++ b/css/leistungen.css @@ -0,0 +1,196 @@ +/* Vincent: Gemeinsame Klassennamen und Variablen sind auf .pakete begrenzt. */ +/* ========================================================== + tri-hub.de – Design-DNA (Block 4, Projekt-Kickoff) + Hintergrund: #0d0d1a / #1a1a2e + Akzent: #10B981 (Teal / Emerald Green) + Primärtext: #ffffff / #F8FAFC / #94A3B8 + Typografie: Playfair Display (Display) + Inter (Body) + Ton: Du-Ansprache, Premium, direkt + ========================================================== */ + +.pakete { + --bg-dark: #0d0d1a; + --bg-panel: #1a1a2e; + --accent: #10B981; + --accent-soft: rgba(16, 185, 129, 0.12); + --text-primary: #ffffff; + --text-secondary: #F8FAFC; + --text-muted: #94A3B8; + + --font-display: "Inter", system-ui, sans-serif; + --font-body: "Inter", system-ui, sans-serif; +} + +.pakete, +.pakete * { + box-sizing: border-box; +} + +.pakete { + margin: 0; + background: var(--bg-dark); + color: var(--text-secondary); + font-family: var(--font-body); +} + +/* ---------- Leistungsübersicht ---------- */ + +.pakete { + padding: 5rem 1.5rem; + max-width: 1120px; + margin: 0 auto; +} + +.pakete .pakete__intro { + text-align: center; + max-width: 42rem; + margin: 0 auto 3rem; +} + +.pakete .pakete__titel { + font-family: var(--font-display); + font-weight: 700; + font-size: clamp(1.8rem, 3vw, 2.4rem); + color: var(--text-primary); + margin: 0 0 0.75rem; +} + +.pakete .pakete__text { + color: var(--text-muted); + line-height: 1.6; + margin: 0; +} + +/* Kästchen nebeneinander, jede Karte für sich */ +.pakete .pakete__grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1.5rem; + align-items: stretch; +} + +.pakete .paket-karte { + display: flex; + flex-direction: column; + background: var(--bg-panel); + border: 1px solid rgba(248, 250, 252, 0.08); + border-radius: 14px; + padding: 2rem 1.75rem; + position: relative; +} + +.pakete .paket-karte--empfohlen { + border-color: var(--accent); + box-shadow: 0 0 0 1px var(--accent-soft); +} + +.pakete .paket-karte--ausgewaehlt { + border-color: var(--accent); + box-shadow: 0 0 0 2px var(--accent); +} + +.pakete .paket-karte__badge { + position: absolute; + top: -0.7rem; + left: 1.75rem; + background: var(--accent); + color: var(--bg-dark); + font-size: 0.75rem; + font-weight: 600; + padding: 0.25rem 0.75rem; + border-radius: 999px; + margin: 0; +} + +.pakete .paket-karte__name { + font-family: var(--font-display); + font-weight: 600; + font-size: 1.4rem; + color: var(--text-primary); + margin: 0 0 0.5rem; +} + +.pakete .paket-karte__preis { + margin: 0 0 0.75rem; + display: flex; + align-items: baseline; + gap: 0.35rem; +} + +.pakete .paket-karte__betrag { + font-family: var(--font-display); + font-size: 2rem; + font-weight: 700; + color: var(--text-primary); +} + +.pakete .paket-karte__zeitraum { + color: var(--text-muted); + font-size: 0.9rem; +} + +.pakete .paket-karte__beschreibung { + color: var(--text-muted); + line-height: 1.55; + margin: 0 0 1.5rem; + min-height: 3.3em; +} + +.pakete .paket-karte__leistungen { + list-style: none; + margin: 0 0 2rem; + padding: 0; + flex-grow: 1; +} + +.pakete .paket-karte__leistungen li { + position: relative; + padding-left: 1.4rem; + margin-bottom: 0.7rem; + line-height: 1.4; + color: var(--text-secondary); +} + +.pakete .paket-karte__leistungen li::before { + content: ""; + position: absolute; + left: 0; + top: 0.5em; + width: 8px; + height: 8px; + border-radius: 2px; + background: var(--accent); +} + +.pakete .paket-karte__cta { + font-family: var(--font-body); + font-weight: 600; + font-size: 0.95rem; + color: var(--bg-dark); + background: var(--accent); + border: none; + border-radius: 8px; + padding: 0.85rem 1rem; + cursor: pointer; + transition: filter 0.15s ease; +} + +.pakete .paket-karte__cta:hover, +.pakete .paket-karte__cta:focus-visible { + filter: brightness(1.1); +} + +.pakete .paket-karte__cta:focus-visible { + outline: 2px solid var(--text-primary); + outline-offset: 2px; +} + +@media (max-width: 860px) { + .pakete .pakete__grid { + grid-template-columns: 1fr; + } + + .pakete .paket-karte--empfohlen { + order: -1; + } +} diff --git a/index.html b/index.html index 2bad707..5cd95b3 100644 --- a/index.html +++ b/index.html @@ -5,8 +5,13 @@ Ernährungsberatung für Triathleten | tri-hub + + + + + @@ -73,6 +78,16 @@ + + +
+
+

+

+
+ +
+
diff --git a/js/leistungen.js b/js/leistungen.js new file mode 100644 index 0000000..e37dbee --- /dev/null +++ b/js/leistungen.js @@ -0,0 +1,119 @@ +// US-01-02 Leistungsübersicht +// Markiert das gewählte Paket visuell und stellt die Auswahl bereit, +// damit US-01-03 (Pakete online buchen) später darauf aufbauen kann. + +document.addEventListener("DOMContentLoaded", async () => { + const section = document.getElementById("leistungen"); + if (!section) return; + + // Integration: Der Datenpfad muss zum vorhandenen JSON-Ordner passen. + let daten; + try { + const response = await fetch("json/pakete.json"); + if (!response.ok) throw new Error(`HTTP ${response.status}`); + daten = await response.json(); + } catch (error) { + section.querySelector(".pakete__text").textContent = "Die Pakete konnten nicht geladen werden. Bitte lade die Seite erneut."; + console.error("Pakete konnten nicht geladen werden:", error); + return; + } + + // Elemente aus dem HTML holen + const titel = section.querySelector(".pakete__titel"); + const text = section.querySelector(".pakete__text"); + const grid = section.querySelector(".pakete__grid"); + + // Intro mit Daten aus JSON füllen + titel.textContent = daten.intro.titel; + text.textContent = daten.intro.text; + + // Vorhandenen Inhalt entfernen + grid.innerHTML = ""; + + // Für jedes Paket eine Karte erstellen + daten.pakete.forEach(paket => { + + // Artikel erstellen + const karte = document.createElement("article"); + karte.classList.add("paket-karte"); + + // Empfohlenes Paket bekommt zusätzliche Klasse + if (paket.empfohlen) { + karte.classList.add("paket-karte--empfohlen"); + } + + // Badge nur erstellen, wenn eines vorhanden ist + if (paket.badge) { + const badge = document.createElement("p"); + badge.classList.add("paket-karte__badge"); + badge.textContent = paket.badge; + karte.appendChild(badge); + } + + // Name + const name = document.createElement("h3"); + name.classList.add("paket-karte__name"); + name.textContent = paket.name; + karte.appendChild(name); + + // Preis + const preis = document.createElement("p"); + preis.classList.add("paket-karte__preis"); + + const betrag = document.createElement("span"); + betrag.classList.add("paket-karte__betrag"); + betrag.textContent = `${paket.preis} €`; + + const zeitraum = document.createElement("span"); + zeitraum.classList.add("paket-karte__zeitraum"); + zeitraum.textContent = `/ ${paket.zeitraum}`; + + preis.appendChild(betrag); + preis.appendChild(zeitraum); + karte.appendChild(preis); + + // Beschreibung + const beschreibung = document.createElement("p"); + beschreibung.classList.add("paket-karte__beschreibung"); + beschreibung.textContent = paket.beschreibung; + karte.appendChild(beschreibung); + + // Leistungen + const liste = document.createElement("ul"); + liste.classList.add("paket-karte__leistungen"); + + paket.leistungen.forEach(leistung => { + const punkt = document.createElement("li"); + punkt.textContent = leistung; + liste.appendChild(punkt); + }); + + karte.appendChild(liste); + + // Button + const button = document.createElement("button"); + button.classList.add("paket-karte__cta"); + button.type = "button"; + button.textContent = "Paket wählen"; + button.dataset.paket = paket.dataPaket; + button.setAttribute("aria-pressed", "false"); + + // Die Paketauswahl aus der ersten Version auch nach dem JSON-Rendering erhalten. + button.addEventListener("click", () => { + grid.querySelectorAll(".paket-karte").forEach(andereKarte => { + andereKarte.classList.remove("paket-karte--ausgewaehlt"); + andereKarte.querySelector("button").setAttribute("aria-pressed", "false"); + }); + karte.classList.add("paket-karte--ausgewaehlt"); + button.setAttribute("aria-pressed", "true"); + document.dispatchEvent(new CustomEvent("paket:ausgewaehlt", { + detail: { paket: button.dataset.paket } + })); + }); + + karte.appendChild(button); + + // Karte ins Grid einfügen + grid.appendChild(karte); + }); +}); diff --git a/json/pakete.json b/json/pakete.json new file mode 100644 index 0000000..482b2d5 --- /dev/null +++ b/json/pakete.json @@ -0,0 +1,55 @@ +{ + "intro": { + "titel": "Deine Pakete", + "text": "Drei Wege zu einer Ernährung, die zu deinem Training, deinem Alltag und deinem Alter passt – entwickelt für Triathletinnen und Triathleten ab 50." + }, + "pakete": [ + { + "name": "Starter", + "preis": 79, + "zeitraum": "Monat", + "beschreibung": "Für den Einstieg in eine bewusste Ernährung neben dem Training.", + "leistungen": [ + "Erstgespräch & Bedarfsanalyse", + "Individueller Ernährungsplan", + "Monatliches Check-in per E-Mail", + "Zugang zu Beispielplänen" + ], + "badge": null, + "empfohlen": false, + "dataPaket": "Starter" + }, + { + "name": "STANDART", + "preis": 149, + "zeitraum": "Monat", + "beschreibung": "Laufende Begleitung für alle, die regelmäßig für Wettkämpfe trainieren.", + "leistungen": [ + "Alles aus Starter", + "Plan-Anpassung je Trainingsphase", + "Zwei Beratungsgespräche pro Monat", + "Wettkampf-Ernährungsstrategie", + "Direkter Chat mit deiner Beraterin" + ], + "badge": "Beliebteste Wahl", + "empfohlen": true, + "dataPaket": "Ausdauer" + }, + { + "name": "Rundum Sorglos Paket", + "preis": 249, + "zeitraum": "Monat", + "beschreibung": "Volle Betreuung für ambitionierte Athletinnen und Athleten.", + "leistungen": [ + "Alles aus Ausdauer", + "Wöchentliche Beratungsgespräche", + "Individuelle Supplement-Empfehlung", + "Betreuung am Wettkampftag", + "Priorisierter Support" + ], + "badge": null, + "empfohlen": false, + "dataPaket": "Wettkampf" + } + ] +} \ No newline at end of file