Compare commits

..

12 Commits

39 changed files with 3498 additions and 1698 deletions

1282
FAQ.html 100644

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,10 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Lerne die Ernährungsberaterinnen und Ernährungsberater von Tri-Hub kennen." /> <meta
name="description"
content="Lerne die Ernährungsberaterinnen und Ernährungsberater von Tri-Hub kennen."
/>
<title>Beraterprofil · Tri-Hub</title> <title>Beraterprofil · Tri-Hub</title>
<link rel="stylesheet" href="/src/styles/navigation.css" /> <link rel="stylesheet" href="/src/styles/navigation.css" />
<link rel="stylesheet" href="/src/styles/packages.css" /> <link rel="stylesheet" href="/src/styles/packages.css" />
@ -17,17 +20,35 @@
<div class="advisor-container"> <div class="advisor-container">
<header class="advisor-heading"> <header class="advisor-heading">
<p class="advisor-eyebrow">PERSÖNLICH FÜR DICH DA</p> <p class="advisor-eyebrow">PERSÖNLICH FÜR DICH DA</p>
<h1 id="advisor-heading">Lerne deine Ernährungsberater kennen.</h1> <h1 id="advisor-heading">
<p class="advisor-intro">Hinter einer guten Ernährungsstrategie stehen Menschen, die zuhören und ihre Erfahrung in deinen Alltag und dein Training einbringen.</p> Lerne deine Ernährungsberater kennen.
</h1>
<p class="advisor-intro">
Hinter einer guten Ernährungsstrategie stehen
Menschen, die zuhören und ihre Erfahrung in deinen
Alltag und dein Training einbringen.
</p>
</header> </header>
<div class="advisor-grid" id="advisor-profiles" aria-live="polite"> <div
<p class="advisor-loading">Beraterprofile werden geladen …</p> class="advisor-grid"
id="advisor-profiles"
aria-live="polite"
>
<p class="advisor-loading">
Beraterprofile werden geladen …
</p>
</div> </div>
</div> </div>
</section> </section>
</main> </main>
<script type="module" src="/src/components/navigationsbar/navigation.js"></script> <script
<script type="module" src="/src/features/berater/berater-entry.js"></script> type="module"
src="/src/components/navigationsbar/navigation.js"
></script>
<script
type="module"
src="/src/features/berater/berater-entry.js"
></script>
<div id="footer-placeholder"></div> <div id="footer-placeholder"></div>
<script type="module" src="/src/components/footer/footer.js"></script> <script type="module" src="/src/components/footer/footer.js"></script>
</body> </body>

View File

@ -164,10 +164,26 @@
} }
.hero { .hero {
position: relative;
isolation: isolate;
padding: 92px 0 82px; padding: 92px 0 82px;
border-bottom: 1px solid var(--line); border-bottom: 1px solid var(--line);
} }
.hero::before {
content: "";
position: absolute;
inset: 0 0 56px;
z-index: -1;
background:
linear-gradient(
180deg,
rgba(8, 15, 21, 0.72),
rgba(8, 15, 21, 0.84)
),
url("/images/startseiter_hintergrund.jpeg") 38% center / cover no-repeat;
}
.hero-grid { .hero-grid {
display: grid; display: grid;
grid-template-columns: minmax(0, 1.2fr) minmax(330px, 0.8fr); grid-template-columns: minmax(0, 1.2fr) minmax(330px, 0.8fr);
@ -241,6 +257,7 @@
.hero-card { .hero-card {
position: relative; position: relative;
transform: translateX(80px);
min-height: 410px; min-height: 410px;
padding: 38px; padding: 38px;
display: flex; display: flex;
@ -257,8 +274,8 @@
), ),
linear-gradient( linear-gradient(
145deg, 145deg,
rgba(255, 255, 255, 0.075), rgba(13, 19, 31, 0.78),
rgba(255, 255, 255, 0.025) rgba(13, 19, 31, 0.84)
); );
box-shadow: 0 28px 80px rgba(0, 0, 0, 0.28); box-shadow: 0 28px 80px rgba(0, 0, 0, 0.28);
} }
@ -275,6 +292,7 @@
box-shadow: box-shadow:
0 0 0 34px rgba(83, 213, 205, 0.035), 0 0 0 34px rgba(83, 213, 205, 0.035),
0 0 0 68px rgba(83, 213, 205, 0.02); 0 0 0 68px rgba(83, 213, 205, 0.02);
pointer-events: none;
} }
.hero-card-mark { .hero-card-mark {
@ -297,6 +315,11 @@
color: var(--muted); color: var(--muted);
} }
.hero-card > div {
position: relative;
z-index: 1;
}
.section { .section {
padding: 96px 0; padding: 96px 0;
} }
@ -376,6 +399,26 @@
font-size: clamp(2.5rem, 5vw, 4.7rem); font-size: clamp(2.5rem, 5vw, 4.7rem);
} }
.knowledge-image-frame {
width: 100%;
transform: translateX(-18px);
margin-top: 28px;
padding: 9px;
overflow: hidden;
border: 1px solid rgba(248, 250, 252, 0.18);
border-radius: 22px;
background: linear-gradient(145deg, #273135, #151d22);
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.3);
}
.knowledge-image-frame img {
display: block;
width: 100%;
aspect-ratio: 2.58 / 1;
border-radius: 14px;
object-fit: cover;
}
.knowledge-copy { .knowledge-copy {
color: var(--muted); color: var(--muted);
line-height: 1.85; line-height: 1.85;
@ -698,6 +741,7 @@
.hero-card { .hero-card {
min-height: 330px; min-height: 330px;
transform: none;
} }
} }
@ -885,6 +929,13 @@
<h2 style="font-family: &quot;Inter&quot;, sans-serif"> <h2 style="font-family: &quot;Inter&quot;, sans-serif">
Wissen,<br />das dich<br />weiterbringt. Wissen,<br />das dich<br />weiterbringt.
</h2> </h2>
<div class="knowledge-image-frame">
<img
src="/images/exttraBild.jpeg"
alt="Ergänzendes Bild zur Ernährungsberatung"
loading="lazy"
/>
</div>
</div> </div>
<div> <div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@ -62,7 +62,7 @@
<a href="https://tri-hub.de/widerruf">Widerrufsbelehrung</a> <a href="https://tri-hub.de/widerruf">Widerrufsbelehrung</a>
<a href="https://tri-hub.de/datenschutz">Datenschutz</a> <a href="https://tri-hub.de/datenschutz">Datenschutz</a>
<a href="https://tri-hub.de/impressum">Impressum</a> <a href="https://tri-hub.de/impressum">Impressum</a>
<a class="trihub-cookie-link" href="https://tri-hub.de/">Cookie-Einstellungen öffnen</a> <a class="trihub-cookie-link" href="#cookie-einstellungen" aria-haspopup="dialog">Cookie-Einstellungen öffnen</a>
</nav> </nav>
</section> </section>
</div> </div>

View File

@ -8,8 +8,84 @@ export function initFooter(placeholderSelector = "#footer-placeholder") {
return; return;
} }
placeholder.outerHTML = footerHtml; placeholder.outerHTML = `${footerHtml}
<dialog class="cookie-settings-dialog" aria-labelledby="cookie-settings-title">
<div class="cookie-settings-heading">
<div>
<p class="cookie-settings-eyebrow">DATENSCHUTZ &amp; REICHWEITENMESSUNG</p>
<h2 id="cookie-settings-title">Cookie-Einstellungen</h2>
</div>
<button class="cookie-settings-close" type="button" aria-label="Cookie-Einstellungen schließen">×</button>
</div>
<div class="cookie-settings-options">
<label class="cookie-option">
<span class="cookie-option-copy"><strong>Notwendig</strong><span>Halten den Laden am Laufen und sind notwendig für den Betrieb.</span></span>
<input type="checkbox" name="necessary" checked disabled aria-label="Notwendige Cookies immer aktiv">
<span class="cookie-toggle" aria-hidden="true"></span>
</label>
<label class="cookie-option">
<span class="cookie-option-copy"><strong>Komfort</strong><span>Machen dein Erlebnis angenehmer, zum Beispiel durch Terminbuchung, Kundenbewertungen oder externe Videoinhalte.</span></span>
<input type="checkbox" name="comfort">
<span class="cookie-toggle" aria-hidden="true"></span>
</label>
<label class="cookie-option">
<span class="cookie-option-copy"><strong>Analyse</strong><span>Helfen uns, die Nutzung der Website auszuwerten und Inhalte zu verbessern.</span></span>
<input type="checkbox" name="analysis">
<span class="cookie-toggle" aria-hidden="true"></span>
</label>
<label class="cookie-option">
<span class="cookie-option-copy"><strong>Marketing</strong><span>Helfen uns, Angebote zu verbessern und relevante Inhalte zu zeigen.</span></span>
<input type="checkbox" name="marketing">
<span class="cookie-toggle" aria-hidden="true"></span>
</label>
</div>
<div class="cookie-settings-actions">
<button class="cookie-settings-back" type="button">Zurück</button>
<button class="cookie-settings-save" type="button">Einstellungen speichern</button>
</div>
</dialog>`;
const dialog = document.querySelector(".cookie-settings-dialog");
const cookieLink = document.querySelector(".trihub-cookie-link");
const preferenceKey = "triHubCookiePreferences";
const loadPreferences = () => {
try {
return JSON.parse(localStorage.getItem(preferenceKey) || "{}");
} catch {
return {};
}
};
cookieLink?.addEventListener("click", (event) => {
event.preventDefault();
const preferences = loadPreferences();
for (const category of ["comfort", "analysis", "marketing"]) {
const input = dialog.querySelector(`input[name="${category}"]`);
input.checked = preferences[category] === true;
}
dialog.showModal();
});
const closeDialog = () => dialog.close();
dialog.querySelector(".cookie-settings-close").addEventListener("click", closeDialog);
dialog.querySelector(".cookie-settings-back").addEventListener("click", closeDialog);
dialog.querySelector(".cookie-settings-save").addEventListener("click", () => {
const preferences = { necessary: true };
for (const category of ["comfort", "analysis", "marketing"]) {
preferences[category] = dialog.querySelector(`input[name="${category}"]`).checked;
}
try {
localStorage.setItem(preferenceKey, JSON.stringify(preferences));
} catch {
// Der Dialog bleibt auch ohne verfügbaren Speicher bedienbar.
}
closeDialog();
});
dialog.addEventListener("click", (event) => {
if (event.target === dialog) closeDialog();
});
} }
document.addEventListener("DOMContentLoaded", () => initFooter()); document.addEventListener("DOMContentLoaded", () => initFooter());

View File

@ -35,16 +35,22 @@
<a href="/index.html" class="navbar__link">Ernährung</a> <a href="/index.html" class="navbar__link">Ernährung</a>
</li> </li>
<li> <li>
<a href="/berater.html" class="navbar__link">Beraterprofil</a> <a href="/berater.html" class="navbar__link"
>Beraterprofil</a
>
</li> </li>
<li> <li>
<a href="/index.html" class="navbar__link">FAQ</a> <a href="/FAQ.html" class="navbar__link">FAQ</a>
</li> </li>
<li> <li>
<a href="/index.html#erfahrungen" class="navbar__link">Rezensionen</a> <a href="/index.html#erfahrungen" class="navbar__link"
>Rezensionen</a
>
</li> </li>
<li> <li>
<a href="/index.html#kontakt" class="navbar__link">Kontakt</a> <a href="/index.html#kontakt" class="navbar__link"
>Kontakt</a
>
</li> </li>
<li> <li>
<a <a

View File

@ -15,9 +15,24 @@ export function renderAngebotsuebersicht() {
? `<span class="package-highlight">${pkg.highlight}</span>` ? `<span class="package-highlight">${pkg.highlight}</span>`
: ""; : "";
const cardHtml = ` const packageImage = {
<div class="package-card"> "ernaehrung-starter": {
src: "/images/Starter_bild.webp",
alt: "Triathlon-Einsteiger im Gespräch mit ihrem Coach am See",
},
"ernaehrung-standard": {
src: "/images/standard_bild.webp",
alt: "Triathlet im Radtrikot bespricht sein Training mit dem Coach",
},
"ernaehrung-premium": {
src: "/images/premium_bild.webp",
alt: "Triathlon-Athleten planen gemeinsam am Seeufer",
},
}[pkg.id];
const cardHtml = `
<article class="package-card">
<img class="package-image" src="${packageImage.src}" alt="${packageImage.alt}" loading="lazy" />
<div class="package-type-container"> <div class="package-type-container">
<span class="package-type">${pkg.type}</span> <span class="package-type">${pkg.type}</span>
${highlightHtml} ${highlightHtml}
@ -43,7 +58,7 @@ export function renderAngebotsuebersicht() {
<a href="/paket-details.html?id=${pkg.id}" class="package-btn">${pkg.buttonText} <span aria-hidden="true">→</span></a> <a href="/paket-details.html?id=${pkg.id}" class="package-btn">${pkg.buttonText} <span aria-hidden="true">→</span></a>
</div> </article>
`; `;
container.innerHTML += cardHtml; container.innerHTML += cardHtml;

View File

@ -0,0 +1,137 @@
/**
* Tri-hub FAQ
* Suche, Kategorien, Accordion und Footer-Jahr
*/
document.addEventListener("DOMContentLoaded", () => {
const searchInput = document.getElementById("search");
const chipsContainer = document.getElementById("chips");
const sections = Array.from(document.querySelectorAll(".faq-section"));
const faqItems = Array.from(document.querySelectorAll(".faq-item"));
const emptyMessage = document.getElementById("empty");
const status = document.getElementById("status");
const yearElement = document.getElementById("year");
// Aktuelles Jahr im Footer
if (yearElement) {
yearElement.textContent = new Date().getFullYear();
}
// Aktiver Kategorie-Filter
let activeFilter = "all";
// Text für die Suche vereinheitlichen
function normalizeText(text) {
return text
.toLocaleLowerCase("de")
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.trim();
}
// FAQ-Suche und Kategorie-Filter anwenden
function filterFAQs() {
const searchTerm = normalizeText(searchInput?.value || "");
let visibleCount = 0;
sections.forEach((section) => {
const category = section.dataset.cat;
const categoryMatches =
activeFilter === "all" || category === activeFilter;
const items = Array.from(section.querySelectorAll(".faq-item"));
let visibleInSection = 0;
items.forEach((item) => {
const searchableText = normalizeText(item.textContent);
const searchMatches =
searchTerm === "" || searchableText.includes(searchTerm);
const isVisible = categoryMatches && searchMatches;
item.hidden = !isVisible;
if (isVisible) {
visibleInSection++;
visibleCount++;
}
});
// Kategorie nur anzeigen, wenn Fragen passen
section.hidden = visibleInSection === 0;
});
// Hinweis anzeigen, wenn nichts gefunden wurde
if (emptyMessage) {
emptyMessage.classList.toggle("hidden", visibleCount > 0);
}
// Screenreader über das Suchergebnis informieren
if (status) {
status.textContent =
visibleCount === 1
? "Eine Frage gefunden."
: `${visibleCount} Fragen gefunden.`;
}
}
// Kategorie-Buttons initialisieren
if (chipsContainer) {
const chips = Array.from(
chipsContainer.querySelectorAll("[data-filter]"),
);
function updateActiveChip() {
chips.forEach((chip) => {
const isActive = chip.dataset.filter === activeFilter;
chip.classList.toggle("is-active", isActive);
chip.setAttribute("aria-pressed", String(isActive));
});
}
chips.forEach((chip) => {
chip.addEventListener("click", () => {
activeFilter = chip.dataset.filter;
updateActiveChip();
filterFAQs();
});
});
updateActiveChip();
}
// Suche bei jeder Eingabe aktualisieren
if (searchInput) {
searchInput.addEventListener("input", filterFAQs);
}
// Accordion: Immer nur eine Frage gleichzeitig öffnen
faqItems.forEach((item) => {
item.addEventListener("toggle", () => {
const isOpen = item.open;
item.dataset.state = isOpen ? "open" : "closed";
if (!isOpen) return;
faqItems.forEach((otherItem) => {
if (otherItem !== item && otherItem.open) {
otherItem.open = false;
}
});
});
});
// Initialzustand setzen
faqItems.forEach((item) => {
item.dataset.state = item.open ? "open" : "closed";
});
filterFAQs();
});

View File

@ -227,3 +227,206 @@
align-items: flex-start; align-items: flex-start;
} }
} }
.cookie-settings-dialog,
.cookie-settings-dialog * {
box-sizing: border-box;
}
.cookie-settings-dialog {
width: min(58rem, calc(100% - 2rem));
max-width: none;
max-height: calc(100% - 2rem);
margin: auto;
padding: clamp(1.25rem, 3vw, 2.1rem);
overflow-y: auto;
border: 1px solid rgba(255, 255, 255, 0.14);
border-radius: 1.4rem;
background: #071217;
color: #f8fafc;
box-shadow: 0 28px 90px rgba(0, 0, 0, 0.55);
font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.cookie-settings-dialog::backdrop {
background: rgba(0, 0, 0, 0.72);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.cookie-settings-heading {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 1.5rem;
margin-bottom: 1.75rem;
}
.cookie-settings-eyebrow {
margin: 0 0 0.45rem;
color: rgba(255, 255, 255, 0.52);
font-size: 0.72rem;
letter-spacing: 0.22em;
}
.cookie-settings-heading h2 {
margin: 0;
font-family: inherit;
color: #fff;
font-size: clamp(1.6rem, 4vw, 2.15rem);
line-height: 1.15;
}
.cookie-settings-close {
flex: 0 0 auto;
padding: 0;
border: 0;
background: transparent;
color: #fff;
font: inherit;
font-size: 2.1rem;
line-height: 1;
cursor: pointer;
}
.cookie-settings-options {
display: grid;
gap: 0.9rem;
}
.cookie-option {
position: relative;
display: flex;
min-height: 5.25rem;
align-items: center;
justify-content: space-between;
gap: 3.5rem;
padding: 1.1rem 1.25rem;
border: 1px solid rgba(255, 255, 255, 0.11);
border-radius: 1.2rem;
background: rgba(255, 255, 255, 0.065);
cursor: pointer;
}
.cookie-option-copy {
display: grid;
gap: 0.35rem;
}
.cookie-option-copy strong {
color: #fff;
font-size: 1.05rem;
font-weight: 600;
}
.cookie-option-copy > span {
color: rgba(255, 255, 255, 0.66);
font-size: 0.94rem;
line-height: 1.55;
}
.cookie-option input {
position: absolute;
top: 1.15rem;
right: 1.25rem;
z-index: 1;
width: 3.25rem;
height: 1.75rem;
margin: 0;
opacity: 0;
cursor: pointer;
}
.cookie-toggle {
position: absolute;
top: 1.1rem;
right: 1.15rem;
width: 3.25rem;
height: 1.75rem;
border-radius: 999px;
background: #465057;
transition: background-color 0.18s ease;
}
.cookie-toggle::before {
content: "";
position: absolute;
top: 0.2rem;
left: 0.2rem;
width: 1.35rem;
height: 1.35rem;
border-radius: 50%;
background: #fff;
transition: transform 0.18s ease;
}
.cookie-option input:checked + .cookie-toggle {
background: #00bfd2;
}
.cookie-option input:checked + .cookie-toggle::before {
transform: translateX(1.5rem);
}
.cookie-option input:focus-visible + .cookie-toggle,
.cookie-settings-dialog button:focus-visible {
outline: 3px solid #4edbdc;
outline-offset: 3px;
}
.cookie-option input:disabled {
cursor: not-allowed;
}
.cookie-settings-actions {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 0.75rem;
margin-top: 1.5rem;
}
.cookie-settings-actions button {
min-height: 3rem;
padding: 0.7rem 1.2rem;
border: 1px solid rgba(255, 255, 255, 0.16);
border-radius: 999px;
background: transparent;
color: #f8fafc;
font: inherit;
font-weight: 600;
cursor: pointer;
}
.cookie-settings-actions .cookie-settings-save {
border-color: #fff;
background: #fff;
color: #102027;
}
@media (max-width: 600px) {
.cookie-settings-dialog {
width: calc(100% - 1.25rem);
padding: 1.2rem;
border-radius: 1.1rem;
}
.cookie-option {
align-items: flex-start;
padding: 1rem 4rem 1rem 1rem;
}
.cookie-option input,
.cookie-toggle {
top: 1rem;
right: 0.85rem;
}
.cookie-settings-actions {
flex-direction: column-reverse;
}
.cookie-settings-actions button {
width: 100%;
}
}

View File

@ -72,6 +72,15 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.package-image {
display: block;
width: 100%;
aspect-ratio: 1.42 / 1;
margin: 0 0 1.5rem;
border: 1px solid #f8fafc1f;
border-radius: 1.1rem;
object-fit: cover;
}
.package-type-container { .package-type-container {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;