diff --git a/assets/css/styles.css b/assets/css/styles.css index 9fcf2fa..eb1c112 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -303,7 +303,7 @@ a { } .site-footer { - padding: 1.4rem 0 2.4rem; + padding: 1.4rem 0 6rem; background: #f4eee5; } @@ -324,6 +324,100 @@ a { gap: 1rem; } +.consent-panel { + position: fixed; + right: 1rem; + bottom: 1rem; + width: min(28rem, calc(100vw - 2rem)); + z-index: 2000; + padding: 1.2rem; + border-radius: 1rem; + background: rgba(36, 52, 45, 0.96); + color: #fff; + box-shadow: var(--shadow-soft); + transform: translateY(120%); + transition: transform 0.25s ease; +} + +.consent-panel.is-visible { + transform: translateY(0); +} + +.consent-panel h2 { + margin: 0 0 0.75rem; + font-size: 1.2rem; +} + +.consent-panel p { + margin: 0 0 0.9rem; + font-size: 0.95rem; + line-height: 1.55; + color: rgba(255, 255, 255, 0.88); +} + +.consent-options { + margin-bottom: 1rem; +} + +.consent-option { + display: flex; + align-items: center; + gap: 0.6rem; + font-size: 0.95rem; +} + +.consent-actions { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.consent-open-button { + position: fixed; + left: 1rem; + bottom: 1rem; + z-index: 1990; + border: 0; + border-radius: 999px; + padding: 0.55rem 0.95rem; + background: rgba(116, 89, 72, 0.95); + color: #fff; + font-size: 0.85rem; +} + +.consent-open-button:hover, +.consent-open-button:focus { + background: #5f4739; +} + +.top-link-button { + position: fixed; + right: 1.5rem; + bottom: 1rem; + z-index: 1985; + border: 0; + border-radius: 999px; + padding: 0.5rem 0.9rem; + background: rgba(49, 69, 59, 0.92); + color: #fff; + font-size: 0.82rem; + opacity: 0; + pointer-events: none; + transform: translateY(8px); + transition: opacity 0.2s ease, transform 0.2s ease; +} + +.top-link-button.is-visible { + opacity: 1; + pointer-events: auto; + transform: translateY(0); +} + +.top-link-button:hover, +.top-link-button:focus { + background: #24342d; +} + @media (max-width: 991.98px) { .navbar-collapse { margin-top: 1rem; @@ -368,4 +462,12 @@ a { .hero-section { padding-bottom: 4rem; } + + .consent-actions { + flex-direction: column; + } + + .top-link-button { + bottom: 1rem; + } } \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index afabe70..d1e0dea 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -5,19 +5,165 @@ document.addEventListener("DOMContentLoaded", () => { } const navbar = document.getElementById("mainNav"); - if (!navbar) { + if (navbar) { + const collapseElement = navbar.querySelector(".navbar-collapse"); + const navLinks = navbar.querySelectorAll(".nav-link"); + const collapse = collapseElement ? bootstrap.Collapse.getOrCreateInstance(collapseElement, { toggle: false }) : null; + + navLinks.forEach((link) => { + link.addEventListener("click", () => { + if (window.innerWidth < 992 && collapse) { + collapse.hide(); + } + }); + }); + } + + setupConsentManager(); + setupTopLink(); +}); + +const consentStorageKey = "paConsentPreferencesV1"; + +function getStoredConsent() { + try { + const raw = localStorage.getItem(consentStorageKey); + return raw ? JSON.parse(raw) : null; + } catch { + return null; + } +} + +function storeConsent(consent) { + localStorage.setItem(consentStorageKey, JSON.stringify(consent)); +} + +function loadMatomo() { + if (window.__matomoLoaded) { return; } - const collapseElement = navbar.querySelector(".navbar-collapse"); - const navLinks = navbar.querySelectorAll(".nav-link"); - const collapse = collapseElement ? bootstrap.Collapse.getOrCreateInstance(collapseElement, { toggle: false }) : null; + window.__matomoLoaded = true; + const _paq = (window._paq = window._paq || []); + _paq.push(["trackPageView"]); + _paq.push(["enableLinkTracking"]); - navLinks.forEach((link) => { - link.addEventListener("click", () => { - if (window.innerWidth < 992 && collapse) { - collapse.hide(); - } - }); + const u = "https://piwik.webfarben.net/"; + _paq.push(["setTrackerUrl", u + "matomo.php"]); + _paq.push(["setSiteId", "5"]); + + const d = document; + const g = d.createElement("script"); + const s = d.getElementsByTagName("script")[0]; + g.async = true; + g.src = u + "matomo.js"; + s.parentNode.insertBefore(g, s); +} + +function setupConsentManager() { + const existingConsent = getStoredConsent(); + if (existingConsent?.analytics) { + loadMatomo(); + } + + injectConsentUi(); + + if (!existingConsent) { + openConsentBanner(); + } +} + +function injectConsentUi() { + const panel = document.createElement("aside"); + panel.id = "consentPanel"; + panel.className = "consent-panel"; + panel.innerHTML = + '

Datenschutz-Einstellungen

' + + '

Wir verwenden Matomo zur anonymisierten Reichweitenmessung. Sie entscheiden, ob Statistik-Cookies gesetzt werden.

' + + '" + + '"; + + const trigger = document.createElement("button"); + trigger.type = "button"; + trigger.id = "consentOpenButton"; + trigger.className = "consent-open-button"; + trigger.textContent = "Cookie-Einstellungen"; + + document.body.append(panel, trigger); + + const analyticsInput = document.getElementById("consentAnalytics"); + const consent = getStoredConsent(); + if (consent?.analytics && analyticsInput) { + analyticsInput.checked = true; + } + + trigger.addEventListener("click", openConsentBanner); + + document.getElementById("consentAcceptAll")?.addEventListener("click", () => { + saveConsent({ analytics: true }); + if (analyticsInput) { + analyticsInput.checked = true; + } }); -}); \ No newline at end of file + + document.getElementById("consentEssential")?.addEventListener("click", () => { + saveConsent({ analytics: false }); + if (analyticsInput) { + analyticsInput.checked = false; + } + }); + + document.getElementById("consentSave")?.addEventListener("click", () => { + saveConsent({ analytics: Boolean(analyticsInput?.checked) }); + }); +} + +function openConsentBanner() { + document.getElementById("consentPanel")?.classList.add("is-visible"); +} + +function closeConsentBanner() { + document.getElementById("consentPanel")?.classList.remove("is-visible"); +} + +function saveConsent(consent) { + storeConsent(consent); + if (consent.analytics) { + loadMatomo(); + } + closeConsentBanner(); +} + +function setupTopLink() { + const topLink = document.createElement("button"); + topLink.type = "button"; + topLink.className = "top-link-button"; + topLink.setAttribute("aria-label", "Nach oben"); + topLink.textContent = "Nach oben"; + + topLink.addEventListener("click", () => { + window.scrollTo({ top: 0, behavior: "smooth" }); + }); + + document.body.append(topLink); + + const toggleTopLink = () => { + if (window.scrollY > 320) { + topLink.classList.add("is-visible"); + } else { + topLink.classList.remove("is-visible"); + } + }; + + toggleTopLink(); + window.addEventListener("scroll", toggleTopLink, { passive: true }); +} \ No newline at end of file diff --git a/datenschutz.html b/datenschutz.html index d8b99f2..fea304a 100644 --- a/datenschutz.html +++ b/datenschutz.html @@ -170,27 +170,6 @@ - - - - + diff --git a/impressum.html b/impressum.html index 7cf95f6..b387892 100644 --- a/impressum.html +++ b/impressum.html @@ -148,27 +148,6 @@ - - - - + diff --git a/index.html b/index.html index a7a327d..4a28c1c 100644 --- a/index.html +++ b/index.html @@ -279,24 +279,5 @@ - - - \ No newline at end of file