diff --git a/assets/antrag/darc-antrag.css b/assets/antrag/darc-antrag.css new file mode 100644 index 0000000..38671f2 --- /dev/null +++ b/assets/antrag/darc-antrag.css @@ -0,0 +1,51 @@ +/* Minimal CSS for floating CTA positioning/animation only. Uses Bootstrap button styles. */ + +.darc-floating { + position: fixed; + bottom: 1.25rem; + z-index: 9999; + transform: translateY(140%); + opacity: 0; + transition: transform .35s cubic-bezier(.2, .8, .2, 1), opacity .35s ease; +} + +.darc-floating--right { right: 1.25rem; } +.darc-floating--left { left: 1.25rem; } + +.darc-floating.is-visible { + transform: translateY(0); + opacity: 1; +} + +.darc-floating[hidden] { display: none; } + +.darc-floating__link { + display: inline-flex; + align-items: center; + gap: .5rem; +} + +.darc-floating__icon { + display: inline-flex; +} + +.darc-floating__icon svg { + width: 1.1rem; + height: 1.1rem; +} + +.darc-floating__close { + min-width: 2.5rem; + line-height: 1; +} + +@media (max-width: 480px) { + .darc-floating { left: 1rem; right: 1rem; } + .darc-floating .btn-group { width: 100%; } + .darc-floating .btn { flex: 1 1 auto; } + .darc-floating__close { flex: 0 0 auto; } +} + +@media (prefers-reduced-motion: reduce) { + .darc-floating { transition: none; } +} diff --git a/assets/antrag/floating-cta.js b/assets/antrag/floating-cta.js new file mode 100644 index 0000000..3a61641 --- /dev/null +++ b/assets/antrag/floating-cta.js @@ -0,0 +1,98 @@ +/** + * DARC Mitgliedsantrag – Floating CTA + * + * Blendet den mitlaufenden Button automatisch nach kurzer Verzögerung ein, + * damit er auch auf großen Bildschirmen / kurzen Seiten ohne Scrollen sichtbar + * ist. Wird vorher gescrollt, erscheint er sofort. + * + * Es werden KEINE personenbezogenen Daten und keine dauerhaften Marker + * gespeichert – nur ein sessionStorage-Flag pro Element, das beim Schließen des + * Tabs verfällt. + */ +(function () { + 'use strict'; + + var REVEAL_DELAY = 800; // ms: spätestens nach dieser Zeit einblenden. + var REVEAL_AFTER = 200; // px Scroll-Tiefe, ab der sofort eingeblendet wird. + + function storageKey(el) { + return 'darcFloatingDismissed_' + (el.getAttribute('data-uid') || '0'); + } + + function isDismissed(el) { + if (el.getAttribute('data-dismissible') !== '1') { + return false; + } + try { + return window.sessionStorage.getItem(storageKey(el)) === '1'; + } catch (e) { + return false; + } + } + + function dismiss(el) { + el.classList.remove('is-visible'); + window.setTimeout(function () { el.setAttribute('hidden', 'hidden'); }, 350); + try { + window.sessionStorage.setItem(storageKey(el), '1'); + } catch (e) { /* sessionStorage nicht verfügbar – egal */ } + } + + function reveal(el) { + el.removeAttribute('hidden'); + // Doppeltes rAF, damit der Display-Wechsel die Transition auslöst. + window.requestAnimationFrame(function () { + window.requestAnimationFrame(function () { el.classList.add('is-visible'); }); + }); + } + + function setup(el) { + if (isDismissed(el)) { + return; + } + + var closeBtn = el.querySelector('.darc-floating__close'); + if (closeBtn) { + closeBtn.addEventListener('click', function () { dismiss(el); }); + } + + var shown = false; + var timer = null; + + function show() { + if (shown) { + return; + } + shown = true; + window.removeEventListener('scroll', onScroll); + if (timer) { + window.clearTimeout(timer); + } + reveal(el); + } + + function onScroll() { + if ((window.pageYOffset || document.documentElement.scrollTop) > REVEAL_AFTER) { + show(); + } + } + + // Garantierte Einblendung nach kurzer Verzögerung (auch ohne Scrollen). + timer = window.setTimeout(show, REVEAL_DELAY); + // Früher einblenden, sobald der Besucher scrollt. + window.addEventListener('scroll', onScroll, { passive: true }); + } + + function init() { + var elements = Array.prototype.slice.call( + document.querySelectorAll('[data-darc-floating]') + ); + elements.forEach(setup); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } +})(); diff --git a/templates/html/index.html b/templates/html/index.html index 592ea22..e9d3cad 100644 --- a/templates/html/index.html +++ b/templates/html/index.html @@ -108,8 +108,8 @@
Mitglied werden

Der DARC e. V. unterstützt Dich auf deinem Weg zum Amateurfunkzeugnis und ist die größte Interessensvertretung der Funkamateure in Deutschland.

-
Mitglied werden
-
Gastmitgliedschaft
+
Mitglied werden
+
Gastmitgliedschaft
@@ -121,9 +121,9 @@

Videokurse

In Zusammenarbeit mit DL2YMR ist ein Videokurs für die Klasse N entstanden, der auf seinem YouTube-Kanal abrufbar ist. Weiterhin gibt es noch Vorlesungen für N+E sowie A.

- Zum Videokurs Klasse N - Vorlesung Klasse N+E - Vorlesung Klasse A + Zum Videokurs Klasse N + Vorlesung Klasse N+E + Vorlesung Klasse A
@@ -134,8 +134,8 @@

Buch Klasse N

Die Lernhinhalte für die Klasse N gibt es auch als gedrucktes Buch. Es ist passend zum Online-Kurs ausgelegt.

- Beim DARC-Verlag kaufen - Amazon + Beim DARC-Verlag kaufen + Amazon
@@ -145,8 +145,8 @@

Kurse

Einige unserer Ortsverbände bieten Präsenz- oder Onlinekurse mit erfahrenen Ausbildern an. Finde heraus, ob es einen für dich passenden Kurs bei dir in der Nähe gibt!

- Präsenz - Online + Präsenz + Online
@@ -156,7 +156,7 @@

Ausbildungs­paten

Unsere Ausbildungspaten sind erfahrene Funkamateure, die dich gerne unterstützen. Sie können mit dir auch praktisch üben und nützliche Tipps für die Praxis geben.

- Zur Patenkarte + Zur Patenkarte
@@ -166,7 +166,7 @@

Fragenkatalog

Den Fragenkatalog mit den amtlichen Prüfungsfragen gibt es digital bei der Bundesnetzagentur. Beim DARC-Verlag kann man auch eine gedruckte Version bestellen.

- Beim DARC-Verlag kaufen + Beim DARC-Verlag kaufen
@@ -176,8 +176,8 @@

Trainings App

Zum Trainieren der Fragen gibt es die 50Ohm App. Sie ist passend zum Online-Kurs ausgelegt.

- Android - iOS + Android + iOS
diff --git a/templates/html/page.html b/templates/html/page.html index d05dc54..0958d72 100644 --- a/templates/html/page.html +++ b/templates/html/page.html @@ -9,6 +9,7 @@ + @@ -16,6 +17,7 @@ + @@ -164,7 +166,27 @@ - +
+
+ +
+
+