{"id":1248,"date":"2026-07-15T13:40:09","date_gmt":"2026-07-15T13:40:09","guid":{"rendered":"https:\/\/ff-willmatshofen.de\/?page_id=1248"},"modified":"2026-07-15T14:28:10","modified_gmt":"2026-07-15T14:28:10","slug":"spiele","status":"publish","type":"page","link":"https:\/\/ff-willmatshofen.de\/spiele\/","title":{"rendered":"Spiele"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1248\" class=\"elementor elementor-1248\">\n\t\t\t\t<div class=\"elementor-element elementor-element-926171b e-con e-atomic-element e-flexbox-base e-a1932be \" data-id=\"926171b\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"926171b\">\n    \t\t<div class=\"elementor-element elementor-element-dc54006 elementor-widget elementor-widget-shortcode\" data-id=\"dc54006\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\">    <style>\n        .ffss-hero {\n            background: linear-gradient(135deg, var(--ff-blue-dark, #1C2B4B), var(--ff-blue-darker, #0f1e38));\n            border-radius: 8px;\n            padding: 44px 20px;\n            text-align: center;\n            color: #fff !important;\n            margin-bottom: 24px;\n            border-top: 4px solid var(--ff-red, #CC0000);\n        }\n        .ffss-hero h1 { font-size: 32px; font-weight: 900; margin-bottom: 12px; color: #fff !important; }\n        .ffss-hero p { font-size: 15px; color: var(--ff-text-muted, #c8d4e0) !important; max-width: 560px; margin: 0 auto; line-height: 1.7; }\n\n        .ffss-auswahl { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; max-width: 640px; margin: 0 auto 30px; }\n        .ffss-kachel {\n            background: var(--ff-blue-dark, #1C2B4B); border: 2px solid rgba(255,255,255,0.12);\n            border-radius: 10px; padding: 18px 10px; text-align: center; cursor: pointer;\n            color: #fff !important; font-family: inherit; -webkit-tap-highlight-color: transparent;\n            transition: border-color 0.2s, transform 0.1s;\n        }\n        .ffss-kachel:active { transform: scale(0.97); }\n        .ffss-kachel .icon { font-size: 32px; display: block; margin-bottom: 8px; }\n        .ffss-kachel .titel { font-size: 13px; font-weight: 700; color: #fff !important; line-height: 1.3; }\n        .ffss-kachel.aktiv { border-color: var(--ff-red, #CC0000) !important; background: #ffffff !important; }\n        .ffss-kachel.aktiv .titel { color: #1C2B4B !important; }\n\n        .ffss-spiel { display: none; }\n        .ffss-spiel.aktiv { display: block; }\n\n        @media (max-width: 768px) {\n            .ffss-hero { padding: 32px 16px; }\n            .ffss-hero h1 { font-size: 24px; }\n            .ffss-auswahl { gap: 8px; }\n            .ffss-kachel { padding: 14px 6px; }\n            .ffss-kachel .icon { font-size: 26px; }\n            .ffss-kachel .titel { font-size: 11px; }\n        }\n    <\/style>\n\n    <div class=\"ffss-hero\">\n        <h1>\ud83d\udd25 Unsere Feuerwehr-Spiele<\/h1>\n        <p>Testet euer Wissen und K\u00f6nnen, sammelt Abzeichen und r\u00fcckt virtuell aus \u2013\n        zehn Spiele und Features f\u00fcr alle Altersgruppen, jederzeit kostenlos spielbar.<\/p>\n    <\/div>\n\n    <div class=\"ffss-auswahl\" id=\"ffss-auswahl\">\n        <button class=\"ffss-kachel aktiv\" data-spiel=\"loeschangriff\" onclick=\"ffssWaehlen('loeschangriff')\">\n            <span class=\"icon\">\ud83d\udd25<\/span>\n            <span class=\"titel\">L\u00f6schangriff<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"notruf\" onclick=\"ffssWaehlen('notruf')\">\n            <span class=\"icon\">\ud83d\udcde<\/span>\n            <span class=\"titel\">Notruf-Reihenfolge<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"memory\" onclick=\"ffssWaehlen('memory')\">\n            <span class=\"icon\">\ud83e\udde0<\/span>\n            <span class=\"titel\">FF-Willmatshofen Memory<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"quiz\" onclick=\"ffssWaehlen('quiz')\">\n            <span class=\"icon\">\ud83e\uddef<\/span>\n            <span class=\"titel\">Feuerwehr-Quiz<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"schlauch\" onclick=\"ffssWaehlen('schlauch')\">\n            <span class=\"icon\">\ud83d\udebf<\/span>\n            <span class=\"titel\">Schlauch-Verbindung<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"fahrsimulator\" onclick=\"ffssWaehlen('fahrsimulator')\">\n            <span class=\"icon\">\ud83d\ude92<\/span>\n            <span class=\"titel\">Einsatzfahrt-Simulator<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"strahlrohr\" onclick=\"ffssWaehlen('strahlrohr')\">\n            <span class=\"icon\">\ud83c\udfaf<\/span>\n            <span class=\"titel\">Strahlrohr-Ziel<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"deich\" onclick=\"ffssWaehlen('deich')\">\n            <span class=\"icon\">\ud83c\udf0a<\/span>\n            <span class=\"titel\">Deich-Verteidigung<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"einsatzfahrt\" onclick=\"ffssWaehlen('einsatzfahrt')\">\n            <span class=\"icon\">\ud83d\udea8<\/span>\n            <span class=\"titel\">Einsatzfahrt 3D<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"escape\" onclick=\"ffssWaehlen('escape')\">\n            <span class=\"icon\">\ud83d\udeaa<\/span>\n            <span class=\"titel\">Escape-Room<\/span>\n        <\/button>\n        <button class=\"ffss-kachel\" data-spiel=\"sammelalbum\" onclick=\"ffssWaehlen('sammelalbum')\">\n            <span class=\"icon\">\ud83c\udfc5<\/span>\n            <span class=\"titel\">Sammelalbum<\/span>\n        <\/button>\n    <\/div>\n\n    <div class=\"ffss-spiel aktiv\" id=\"ffss-spiel-loeschangriff\">\n            <div class=\"ffs-wrap\" id=\"ff-spiel-anker\">\n        <style>\n            .ffs-wrap { max-width: 420px; margin: 20px auto; font-family: 'Oswald', sans-serif; scroll-margin-top: 90px; }\n            .ffs-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 20px; color: #fff !important; text-align: center; position: relative; overflow: hidden; }\n            .ffs-title { font-size: 22px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffs-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 10px; }\n            .ffs-rang-btn { background: none; border: 1px solid gold; color: gold !important; padding: 6px 16px; border-radius: 20px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; margin-bottom: 4px; }\n            .ffs-rang-btn:hover { background: gold; color: #1C2B4B !important; }\n            .ffs-mini-rang { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,215,0,0.3); border-radius: 8px; padding: 10px 14px; margin-bottom: 14px; text-align: left; }\n            .ffs-mini-rang-titel { font-size: 12px; font-weight: 700; color: gold !important; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 6px; text-align: center; }\n            .ffs-mini-rang-zeile { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; color: #fff !important; }\n            .ffs-mini-rang-platz { width: 18px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffs-mini-rang-name { flex: 1; }\n            .ffs-mini-rang-score { font-weight: 700; }\n            .ffs-mini-rang-leer { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; text-align: center; }\n            .ffs-spielfeld { position: relative; }\n            .ffs-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; font-size: 15px; font-weight: 700; color: #fff !important; }\n            .ffs-hud span { color: #fff !important; }\n            .ffs-leben { font-size: 18px; letter-spacing: 2px; color: #fff !important; }\n            .ffs-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 6px; }\n            .ffs-zelle { position: relative; aspect-ratio: 1 \/ 1; background: rgba(255,255,255,0.06); border: 2px solid rgba(255,255,255,0.12); border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 30px; cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent; transition: transform 0.1s; }\n            .ffs-zelle:active { transform: scale(0.92); }\n            .ffs-zelle.brennt { border-color: var(--ff-red, #CC0000); animation: ffs-flacker 0.5s infinite alternate; }\n            .ffs-zelle.bonus { border-color: gold; animation: ffs-bonus-puls 0.4s infinite alternate; }\n            .ffs-zelle.geloescht { animation: ffs-pop 0.35s ease; }\n            .ffs-zelle.abgebrannt { border-color: #555; }\n            @keyframes ffs-bonus-puls { from { box-shadow: 0 0 0 gold; } to { box-shadow: 0 0 14px gold; } }\n            @keyframes ffs-flacker { from { filter: brightness(1); } to { filter: brightness(1.3); } }\n            @keyframes ffs-pop { 0% { transform: scale(1); } 40% { transform: scale(1.25); } 100% { transform: scale(1); } }\n\n            .ffs-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px; border-radius: 12px; z-index: 3; color: #fff !important; }\n            .ffs-overlay h3 { font-size: 22px; margin-bottom: 8px; color: #fff !important; }\n            .ffs-overlay p { font-size: 14px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 18px; line-height: 1.6; }\n            .ffs-overlay p strong { color: gold !important; }\n            .ffs-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .ffs-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffs-btn:disabled { opacity: 0.5; cursor: default; }\n            .ffs-score-gro\u00df { font-size: 40px; font-weight: 900; margin: 6px 0; color: #fff !important; }\n            .ffs-highscore { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 16px; }\n            .ffs-bonus-img { width: 70%; height: 70%; object-fit: contain; filter: drop-shadow(0 2px 6px rgba(0,0,0,0.5)); }\n\n            .ffs-eintrag-wrap { width: 100%; margin-bottom: 16px; }\n            .ffs-name-input { width: 100%; box-sizing: border-box; padding: 10px 14px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.25) !important; background: rgba(255,255,255,0.08) !important; background-color: rgba(255,255,255,0.08) !important; color: #fff !important; font-size: 14px; font-family: inherit; margin-bottom: 10px; text-align: center; }\n            .ffs-name-input::placeholder { color: var(--ff-text-muted, #a0b0c8) !important; }\n            .ffs-btn-klein { padding: 8px 22px; font-size: 13px; }\n            .ffs-eintrag-status { font-size: 12px; color: gold !important; margin-top: 8px; min-height: 16px; }\n\n            .ffs-rang-liste { width: 100%; max-height: 300px; overflow-y: auto; margin-bottom: 16px; }\n            .ffs-rang-zeile { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 6px; font-size: 14px; color: #fff !important; }\n            .ffs-rang-zeile:nth-child(odd) { background: rgba(255,255,255,0.05); }\n            .ffs-rang-platz { width: 24px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffs-rang-name { flex: 1; text-align: left; color: #fff !important; }\n            .ffs-rang-score { font-weight: 700; color: #fff !important; }\n            .ffs-rang-leer { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; }\n\n            .ffs-alter-buttons { display: flex; flex-direction: column; gap: 8px; width: 100%; margin-bottom: 4px; }\n            .ffs-alter-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: #fff !important; padding: 10px 16px; border-radius: 8px; font-size: 14px; font-weight: 700; cursor: pointer; font-family: inherit; text-align: left; display: flex; align-items: center; justify-content: space-between; }\n            .ffs-alter-btn:hover { border-color: var(--ff-red, #CC0000); background: rgba(204,0,0,0.15); }\n            .ffs-alter-btn span.ffs-alter-sub { font-size: 12px; font-weight: 400; color: var(--ff-text-muted, #a0b0c8) !important; }\n\n            .ffs-tab-reihe { display: flex; gap: 6px; margin-bottom: 10px; justify-content: center; flex-wrap: wrap; }\n            .ffs-tab-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: var(--ff-text-muted, #a0b0c8) !important; padding: 5px 10px; border-radius: 20px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit; }\n            .ffs-tab-btn.aktiv { background: gold; border-color: gold; color: #1C2B4B !important; }\n        <\/style>\n\n        <div class=\"ffs-box\">\n            <div class=\"ffs-title\">\ud83d\udd25 L\u00f6schangriff<\/div>\n            <div class=\"ffs-untertitel\">Tipp auf die Flammen, bevor das Haus abbrennt!<\/div>\n\n            <div class=\"ffs-mini-rang\">\n                <div class=\"ffs-mini-rang-titel\">\ud83c\udfc6 Bestenliste<\/div>\n                <div class=\"ffs-tab-reihe\" id=\"ffs-mini-tabs\">\n                    <button class=\"ffs-tab-btn\" data-stufe=\"loeschzwerg\" onclick=\"ffsMiniTabWaehlen('loeschzwerg')\">\ud83d\udc76<\/button>\n                    <button class=\"ffs-tab-btn\" data-stufe=\"jugend\" onclick=\"ffsMiniTabWaehlen('jugend')\">\ud83e\uddd2<\/button>\n                    <button class=\"ffs-tab-btn\" data-stufe=\"erwachsene\" onclick=\"ffsMiniTabWaehlen('erwachsene')\">\ud83d\ude92<\/button>\n                <\/div>\n                <div id=\"ffs-mini-rang-inhalt\">L\u00e4dt \u2026<\/div>\n            <\/div>\n            <button class=\"ffs-rang-btn\" onclick=\"ffsRanglisteAnzeigen()\">Komplette Rangliste<\/button>\n\n            <div class=\"ffs-spielfeld\">\n                <div class=\"ffs-hud\">\n                    <span>Punkte: <span id=\"ffs-score\">0<\/span><\/span>\n                    <span class=\"ffs-leben\" id=\"ffs-leben\">\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f<\/span>\n                <\/div>\n\n                <div class=\"ffs-grid\" id=\"ffs-grid\"><\/div>\n\n                <div class=\"ffs-overlay\" id=\"ffs-start\">\n                    <h3>Bereit zum L\u00f6schangriff?<\/h3>\n                    <p>3 Leben. Tippe die Flammen weg, bevor sie durchbrennen \u2013 je mehr Punkte, desto schneller wird's.<br>\n                    Taucht das <strong>L\u00f6schzwerge-Logo<\/strong> auf, gibt's <strong>2 Punkte statt 1<\/strong> \u2013 und verpasst du es, kostet das kein Leben! \u2b50<\/p>\n                    <p style=\"margin-bottom:10px; font-weight:700; color:#fff;\">Wie alt bist du?<\/p>\n                    <div class=\"ffs-alter-buttons\">\n                        <button class=\"ffs-alter-btn\" onclick=\"ffsSpielStart('loeschzwerg')\">\ud83d\udc76 L\u00f6schzwerg <span class=\"ffs-alter-sub\">bis 9 Jahre<\/span><\/button>\n                        <button class=\"ffs-alter-btn\" onclick=\"ffsSpielStart('jugend')\">\ud83e\uddd2 Jugend <span class=\"ffs-alter-sub\">10\u201315 Jahre<\/span><\/button>\n                        <button class=\"ffs-alter-btn\" onclick=\"ffsSpielStart('erwachsene')\">\ud83d\ude92 Erwachsene <span class=\"ffs-alter-sub\">16+<\/span><\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"ffs-overlay\" id=\"ffs-ende\" style=\"display:none;\">\n                    <h3>Einsatz beendet!<\/h3>\n                <div class=\"ffs-score-gro\u00df\" id=\"ffs-endscore\">0<\/div>\n                <div class=\"ffs-highscore\" id=\"ffs-highscore-text\"><\/div>\n                <div class=\"ffs-eintrag-wrap\">\n                    <input type=\"text\" class=\"ffs-name-input\" id=\"ffs-name-input\" maxlength=\"20\" placeholder=\"Dein Name f\u00fcr die Rangliste\">\n                    <button class=\"ffs-btn ffs-btn-klein\" id=\"ffs-eintrag-btn\" onclick=\"ffsScoreEintragen()\">In Rangliste eintragen<\/button>\n                    <div class=\"ffs-eintrag-status\" id=\"ffs-eintrag-status\"><\/div>\n                <\/div>\n                <button class=\"ffs-btn\" onclick=\"ffsZeigeStart()\">Nochmal l\u00f6schen<\/button>\n                <\/div>\n            <\/div>\n\n            <div class=\"ffs-overlay\" id=\"ffs-rangliste-overlay\" style=\"display:none;\">\n                <h3>\ud83c\udfc6 Rangliste<\/h3>\n                <div class=\"ffs-tab-reihe\" id=\"ffs-voll-tabs\">\n                    <button class=\"ffs-tab-btn\" data-stufe=\"loeschzwerg\" onclick=\"ffsVollTabWaehlen('loeschzwerg')\">\ud83d\udc76 L\u00f6schzwerge<\/button>\n                    <button class=\"ffs-tab-btn\" data-stufe=\"jugend\" onclick=\"ffsVollTabWaehlen('jugend')\">\ud83e\uddd2 Jugend<\/button>\n                    <button class=\"ffs-tab-btn\" data-stufe=\"erwachsene\" onclick=\"ffsVollTabWaehlen('erwachsene')\">\ud83d\ude92 Erwachsene<\/button>\n                <\/div>\n                <div class=\"ffs-rang-liste\" id=\"ffs-rang-liste-inhalt\">L\u00e4dt \u2026<\/div>\n                <button class=\"ffs-btn\" onclick=\"ffsRanglisteSchliessen()\">Schlie\u00dfen<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var LZ_LOGO      = 'https:\/\/ff-willmatshofen.de\/wp-content\/uploads\/2026\/04\/Loeschzwerge_Logo.png';\n        var NONCE        = 'f42d298544';\n        var AJAXURL      = 'https:\/\/ff-willmatshofen.de\/wp-admin\/admin-ajax.php';\n        var BONUS_CHANCE = 0.15; \/\/ ca. jede 6.-7. Flamme ist stattdessen ein L\u00f6schzwerge-Bonus\n        var FELDER       = 12;\n\n        var grid = document.getElementById('ffs-grid');\n        var zellen = [];\n        for (var i = 0; i < FELDER; i++) {\n            var z = document.createElement('div');\n            z.className = 'ffs-zelle';\n            z.dataset.index = i;\n            grid.appendChild(z);\n            zellen.push({ el: z, status: 'leer', timeout: null });\n        }\n        grid.addEventListener('click', function(e) {\n            var zelleEl = e.target.closest('.ffs-zelle');\n            if (!zelleEl) return;\n            ffsTippen(parseInt(zelleEl.dataset.index));\n        });\n\n        var score = 0, leben = 3, laeuft = false, spawnTimer = null;\n        var aktuelleAltersstufe = 'erwachsene';\n\n        \/\/ Schwierigkeit pro Altersstufe: eigene Start-\/Endwerte statt nur ein\n        \/\/ pauschaler Faktor. rampStart = wie viele Punkte lang bleibt es\n        \/\/ konstant langsam, bevor es \u00fcberhaupt anf\u00e4ngt schneller zu werden.\n        var SCHWIERIGKEIT = {\n            loeschzwerg: { rampStart: 6, spawnStart: 2400, spawnStep: 20, spawnMin: 1500, brennStart: 3400, brennStep: 20, brennMin: 2200 },\n            jugend:      { rampStart: 3, spawnStart: 1700, spawnStep: 30, spawnMin: 800,  brennStart: 2100, brennStep: 30, brennMin: 1100 },\n            erwachsene:  { rampStart: 0, spawnStart: 1400, spawnStep: 40, spawnMin: 500,  brennStart: 1700, brennStep: 30, brennMin: 700 }\n        };\n\n        function ffsSpielerId() {\n            var id = null;\n            try { id = localStorage.getItem('ffs_player_id'); } catch (e) {}\n            if (!id) {\n                id = (window.crypto && crypto.randomUUID)\n                    ? crypto.randomUUID()\n                    : ('id-' + Date.now() + '-' + Math.random().toString(16).slice(2));\n                try { localStorage.setItem('ffs_player_id', id); } catch (e) {}\n            }\n            return id;\n        }\n\n        window.ffsZeigeStart = function() {\n            document.getElementById('ffs-ende').style.display = 'none';\n            document.getElementById('ffs-start').style.display = 'flex';\n        };\n\n        window.ffsSpielStart = function(altersstufe) {\n            if (altersstufe) {\n                aktuelleAltersstufe = altersstufe;\n                try { localStorage.setItem('ffs_last_bracket', altersstufe); } catch (e) {}\n            }\n\n            score = 0; leben = 3; laeuft = true;\n            document.getElementById('ffs-score').textContent = score;\n            document.getElementById('ffs-leben').textContent = '\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f';\n            document.getElementById('ffs-start').style.display = 'none';\n            document.getElementById('ffs-ende').style.display = 'none';\n            document.getElementById('ffs-rangliste-overlay').style.display = 'none';\n\n            var nameInput = document.getElementById('ffs-name-input');\n            nameInput.value = '';\n            document.getElementById('ffs-eintrag-btn').disabled = false;\n            document.getElementById('ffs-eintrag-status').textContent = '';\n\n            zellen.forEach(function(z) {\n                z.status = 'leer';\n                z.el.className = 'ffs-zelle';\n                z.el.textContent = '';\n                if (z.timeout) clearTimeout(z.timeout);\n            });\n            ffsNaechsteFlamme();\n        };\n\n        function ffsSpawnIntervall() {\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n            var eff = Math.max(0, score - c.rampStart);\n            return Math.max(c.spawnMin, c.spawnStart - eff * c.spawnStep);\n        }\n        function ffsBrenndauer() {\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n            var eff = Math.max(0, score - c.rampStart);\n            return Math.max(c.brennMin, c.brennStart - eff * c.brennStep);\n        }\n\n        function ffsNaechsteFlamme() {\n            if (!laeuft) return;\n            var leere = zellen.filter(function(z) { return z.status === 'leer'; });\n            if (leere.length) {\n                var z = leere[Math.floor(Math.random() * leere.length)];\n                if (Math.random() < BONUS_CHANCE) {\n                    ffsBonusAn(z);\n                } else {\n                    ffsFlammeAn(z);\n                }\n            }\n            spawnTimer = setTimeout(ffsNaechsteFlamme, ffsSpawnIntervall());\n        }\n\n        function ffsFlammeAn(z) {\n            z.status = 'brennt';\n            z.el.className = 'ffs-zelle brennt';\n            z.el.textContent = '\ud83d\udd25';\n            var dauer = ffsBrenndauer();\n            z.timeout = setTimeout(function() { ffsAbgebrannt(z); }, dauer);\n        }\n\n        function ffsBonusAn(z) {\n            z.status = 'bonus';\n            z.el.className = 'ffs-zelle bonus';\n            z.el.innerHTML = '<img decoding=\"async\" class=\"ffs-bonus-img\" src=\"' + LZ_LOGO + '\" alt=\"L\u00f6schzwerge Bonus\">';\n            \/\/ Bonus bleibt etwas k\u00fcrzer sichtbar als eine normale Flamme und\n            \/\/ kostet beim Verpassen KEIN Leben - reiner Bonus, kein Risiko.\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n            var dauer = Math.max(c.brennMin - 300, ffsBrenndauer() - 300);\n            z.timeout = setTimeout(function() { ffsBonusVerpasst(z); }, dauer);\n        }\n\n        function ffsBonusVerpasst(z) {\n            if (z.status !== 'bonus') return;\n            z.status = 'leer';\n            z.el.className = 'ffs-zelle';\n            z.el.textContent = '';\n        }\n\n        function ffsTippen(index) {\n            if (!laeuft) return;\n            var z = zellen[index];\n            if (z.status !== 'brennt' && z.status !== 'bonus') return;\n            clearTimeout(z.timeout);\n\n            if (z.status === 'bonus') {\n                z.status = 'leer';\n                z.el.className = 'ffs-zelle geloescht';\n                z.el.textContent = '\u2b50';\n                score += 2;\n            } else {\n                z.status = 'leer';\n                z.el.className = 'ffs-zelle geloescht';\n                z.el.textContent = '\ud83d\udca6';\n                score++;\n            }\n\n            document.getElementById('ffs-score').textContent = score;\n            setTimeout(function() {\n                if (z.status === 'leer') { z.el.className = 'ffs-zelle'; z.el.textContent = ''; }\n            }, 350);\n        }\n\n        function ffsAbgebrannt(z) {\n            z.status = 'abgebrannt';\n            z.el.className = 'ffs-zelle abgebrannt';\n            z.el.textContent = '\ud83c\udfda\ufe0f';\n            leben--;\n            document.getElementById('ffs-leben').textContent = '\u2764\ufe0f'.repeat(Math.max(0, leben)) + '\ud83d\udda4'.repeat(3 - Math.max(0, leben));\n            setTimeout(function() {\n                if (z.status === 'abgebrannt') { z.status = 'leer'; z.el.className = 'ffs-zelle'; z.el.textContent = ''; }\n            }, 500);\n            if (leben <= 0) ffsSpielEnde();\n        }\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n\n        function ffsSpielEnde() {\n            laeuft = false;\n            clearTimeout(spawnTimer);\n            zellen.forEach(function(z) { clearTimeout(z.timeout); });\n\n            var abzeichen = score >= 20 ? 'gold' : (score >= 10 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('loeschangriff', abzeichen);\n\n            var highscore = parseInt(localStorage.getItem('ffs_highscore') || '0');\n            var neuerRekord = score > highscore;\n            if (neuerRekord) {\n                highscore = score;\n                try { localStorage.setItem('ffs_highscore', highscore); } catch (e) {}\n            }\n\n            document.getElementById('ffs-endscore').textContent = score;\n            document.getElementById('ffs-highscore-text').textContent = neuerRekord\n                ? '\ud83c\udfc6 Neuer eigener Rekord!'\n                : 'Eigener Rekord: ' + highscore + ' Punkte';\n            document.getElementById('ffs-ende').style.display = 'flex';\n        }\n\n        \/\/ ---------- Rangliste: gemeinsame Zeilen-Erzeugung ----------\n        function ffsRangZeilenHtml(liste, klassenPrefix) {\n            var html = '';\n            liste.forEach(function(eintrag, i) {\n                html += '<div class=\"' + klassenPrefix + '-zeile\">' +\n                    '<span class=\"' + klassenPrefix + '-platz\">' + (i + 1) + '.<\/span>' +\n                    '<span class=\"' + klassenPrefix + '-name\">' + ffsEscapeHtml(eintrag.name) + '<\/span>' +\n                    '<span class=\"' + klassenPrefix + '-score\">' + eintrag.score + '<\/span>' +\n                '<\/div>';\n            });\n            return html;\n        }\n\n        function ffsRanglisteHolen(altersstufe, callback) {\n            var formData = new FormData();\n            formData.append('action', 'ff_spiel_rangliste_holen');\n            formData.append('nonce', NONCE);\n            formData.append('altersstufe', altersstufe);\n            fetch(AJAXURL, { method: 'POST', body: formData })\n                .then(function(r) { return r.json(); })\n                .then(function(data) { callback((data.success && data.data) ? data.data : []); })\n                .catch(function() { callback(null); });\n        }\n\n        function ffsLetzteAltersstufe() {\n            var stufe = null;\n            try { stufe = localStorage.getItem('ffs_last_bracket'); } catch (e) {}\n            return (stufe === 'loeschzwerg' || stufe === 'jugend' || stufe === 'erwachsene') ? stufe : 'erwachsene';\n        }\n\n        function ffsTabsAktualisieren(containerId, aktiveStufe) {\n            document.querySelectorAll('#' + containerId + ' .ffs-tab-btn').forEach(function(btn) {\n                btn.classList.toggle('aktiv', btn.dataset.stufe === aktiveStufe);\n            });\n        }\n\n        \/\/ ---------- Mini-Bestenliste: automatisch beim Laden der Seite ----------\n        var ffsMiniStufe = ffsLetzteAltersstufe();\n\n        function ffsMiniRanglisteLaden() {\n            var inhalt = document.getElementById('ffs-mini-rang-inhalt');\n            ffsTabsAktualisieren('ffs-mini-tabs', ffsMiniStufe);\n            inhalt.innerHTML = 'L\u00e4dt \u2026';\n            ffsRanglisteHolen(ffsMiniStufe, function(liste) {\n                if (liste === null) {\n                    inhalt.innerHTML = '<div class=\"ffs-mini-rang-leer\">Rangliste konnte nicht geladen werden.<\/div>';\n                    return;\n                }\n                if (!liste.length) {\n                    inhalt.innerHTML = '<div class=\"ffs-mini-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/div>';\n                    return;\n                }\n                inhalt.innerHTML = ffsRangZeilenHtml(liste.slice(0, 5), 'ffs-mini-rang');\n            });\n        }\n        window.ffsMiniTabWaehlen = function(stufe) {\n            ffsMiniStufe = stufe;\n            ffsMiniRanglisteLaden();\n        };\n        ffsMiniRanglisteLaden();\n\n        \/\/ ---------- Rangliste: Eintragen ----------\n        window.ffsScoreEintragen = function() {\n            var input  = document.getElementById('ffs-name-input');\n            var btn    = document.getElementById('ffs-eintrag-btn');\n            var status = document.getElementById('ffs-eintrag-status');\n            var name   = input.value.trim();\n\n            if (!name) { status.textContent = 'Bitte einen Namen eingeben.'; return; }\n\n            btn.disabled = true;\n            status.textContent = 'Wird gespeichert \u2026';\n\n            var formData = new FormData();\n            formData.append('action', 'ff_spiel_score_speichern');\n            formData.append('nonce', NONCE);\n            formData.append('name', name);\n            formData.append('score', score);\n            formData.append('spieler_id', ffsSpielerId());\n            formData.append('altersstufe', aktuelleAltersstufe);\n\n            fetch(AJAXURL, { method: 'POST', body: formData })\n                .then(function(r) { return r.json(); })\n                .then(function(data) {\n                    if (data.success) {\n                        if (data.data && data.data.verbessert === false) {\n                            status.textContent = 'Dein bisheriger Eintrag war schon besser oder gleich gut \u2013 bleibt unver\u00e4ndert.';\n                        } else {\n                            status.textContent = '\u2705 In der Rangliste eingetragen!';\n                        }\n                        ffsMiniStufe = aktuelleAltersstufe;\n                        ffsMiniRanglisteLaden(); \/\/ Mini-Liste direkt aktualisieren, passenden Reiter zeigen\n                    } else if (data.data && data.data.grund === 'name_vergeben') {\n                        status.textContent = '\u26a0\ufe0f Dieser Name ist schon vergeben \u2013 bitte einen anderen w\u00e4hlen.';\n                        btn.disabled = false;\n                    } else {\n                        status.textContent = 'Konnte nicht gespeichert werden.';\n                        btn.disabled = false;\n                    }\n                })\n                .catch(function() {\n                    status.textContent = 'Konnte nicht gespeichert werden.';\n                    btn.disabled = false;\n                });\n        };\n\n        \/\/ ---------- Rangliste: Anzeigen (unabh\u00e4ngig vom Spielstand) ----------\n        var ffsVollStufe = ffsLetzteAltersstufe();\n\n        function ffsVollRanglisteLaden() {\n            var inhalt = document.getElementById('ffs-rang-liste-inhalt');\n            ffsTabsAktualisieren('ffs-voll-tabs', ffsVollStufe);\n            inhalt.innerHTML = 'L\u00e4dt \u2026';\n\n            ffsRanglisteHolen(ffsVollStufe, function(liste) {\n                if (liste === null) {\n                    inhalt.innerHTML = '<p class=\"ffs-rang-leer\">Rangliste konnte nicht geladen werden.<\/p>';\n                    return;\n                }\n                if (!liste.length) {\n                    inhalt.innerHTML = '<p class=\"ffs-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/p>';\n                    return;\n                }\n                inhalt.innerHTML = ffsRangZeilenHtml(liste, 'ffs-rang');\n            });\n        }\n\n        window.ffsVollTabWaehlen = function(stufe) {\n            ffsVollStufe = stufe;\n            ffsVollRanglisteLaden();\n        };\n\n        window.ffsRanglisteAnzeigen = function() {\n            document.getElementById('ffs-rangliste-overlay').style.display = 'flex';\n            ffsVollRanglisteLaden();\n        };\n\n        window.ffsRanglisteSchliessen = function() {\n            document.getElementById('ffs-rangliste-overlay').style.display = 'none';\n        };\n\n        function ffsEscapeHtml(str) {\n            var div = document.createElement('div');\n            div.textContent = str;\n            return div.innerHTML;\n        }\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-notruf\">\n            <div class=\"ffn-wrap\">\n        <style>\n            .ffn-wrap { max-width: 420px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffn-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 24px; color: #fff !important; text-align: center; position: relative; overflow: hidden; min-height: 480px !important; }\n            .ffn-title { font-size: 22px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffn-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; }\n            .ffn-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; font-size: 14px; font-weight: 700; color: #fff !important; }\n            .ffn-spielfeld { position: relative; min-height: 320px !important; }\n\n            .ffn-liste { display: flex; flex-direction: column; gap: 10px; margin-bottom: 6px; }\n            .ffn-karte { background: rgba(255,255,255,0.06); border: 2px solid rgba(255,255,255,0.15); border-radius: 10px; padding: 18px 18px; display: flex; align-items: center; gap: 16px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform 0.1s, border-color 0.2s, background 0.2s; text-align: left; }\n            .ffn-karte:active { transform: scale(0.98); }\n            .ffn-karte .icon { font-size: 30px; flex-shrink: 0; }\n            .ffn-karte .text { font-size: 16px; font-weight: 600; color: #fff !important; flex: 1; }\n            .ffn-karte .platz { font-size: 20px; font-weight: 900; color: gold !important; width: 24px; text-align: center; flex-shrink: 0; }\n            .ffn-karte.richtig { border-color: #3fae4a; background: rgba(63,174,74,0.15); cursor: default; }\n            .ffn-karte.falsch { animation: ffn-shake 0.4s ease; border-color: var(--ff-red, #CC0000); }\n            @keyframes ffn-shake { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-6px); } 75% { transform: translateX(6px); } }\n\n            .ffn-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px; border-radius: 12px; z-index: 3; color: #fff !important; overflow-y: auto; }\n            .ffn-overlay h3 { font-size: 22px; margin-bottom: 8px; color: #fff !important; }\n            .ffn-overlay p { font-size: 14px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; line-height: 1.6; }\n            .ffn-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .ffn-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffn-ergebnis { font-size: 15px; margin-bottom: 16px; color: #fff !important; }\n            .ffn-ergebnis strong { color: gold !important; }\n            .ffn-merkzettel { text-align: left; background: rgba(255,255,255,0.06); border-radius: 8px; padding: 14px 16px; margin-bottom: 18px; font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; line-height: 1.8; }\n            .ffn-merkzettel strong { color: #fff !important; }\n        <\/style>\n\n        <div class=\"ffn-box\">\n            <div class=\"ffn-title\">\ud83d\udcde Notruf-Reihenfolge<\/div>\n            <div class=\"ffn-untertitel\">Tippt die 5 W-Fragen in der richtigen Reihenfolge an!<\/div>\n\n            <div class=\"ffn-spielfeld\">\n                <div class=\"ffn-hud\">\n                    <span>\u23f1\ufe0f <span id=\"ffn-zeit\">0<\/span>s<\/span>\n                    <span>\u274c Fehler: <span id=\"ffn-fehler\">0<\/span><\/span>\n                <\/div>\n\n                <div class=\"ffn-liste\" id=\"ffn-liste\"><\/div>\n\n                <div class=\"ffn-overlay\" id=\"ffn-start\">\n                    <h3>Bereit f\u00fcr den Notruf?<\/h3>\n                    <p>Beim Absetzen eines Notrufs kommt es auf die richtige Reihenfolge an.\n                    Bringt die 5 W-Fragen in die korrekte Ordnung - so schnell und fehlerfrei wie m\u00f6glich!<\/p>\n                    <button class=\"ffn-btn\" onclick=\"ffnSpielStart()\">\ud83d\udcde Los geht's<\/button>\n                <\/div>\n\n                <div class=\"ffn-overlay\" id=\"ffn-ende\" style=\"display:none;\">\n                    <h3>Notruf abgesetzt! \u2705<\/h3>\n                    <div class=\"ffn-ergebnis\">\n                        Zeit: <strong><span id=\"ffn-endzeit\">0<\/span> Sekunden<\/strong><br>\n                        Fehler: <strong><span id=\"ffn-endfehler\">0<\/span><\/strong>\n                    <\/div>\n                    <div class=\"ffn-merkzettel\">\n                        <strong>Die 5 W's im Notruf:<\/strong><br>\n                        1. Wo ist der Notfall?<br>\n                        2. Was ist geschehen?<br>\n                        3. Wie viele Betroffene?<br>\n                        4. Welche Art von Verletzung\/Gefahr?<br>\n                        5. Warten auf R\u00fcckfragen!\n                    <\/div>\n                    <button class=\"ffn-btn\" onclick=\"ffnSpielStart()\">Nochmal \u00fcben<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var FRAGEN = [\n            { id: 0, icon: '\ud83d\udccd', text: 'Wo ist der Notfall?' },\n            { id: 1, icon: '\u2757', text: 'Was ist geschehen?' },\n            { id: 2, icon: '\ud83d\udd22', text: 'Wie viele Betroffene?' },\n            { id: 3, icon: '\ud83e\ude79', text: 'Welche Art von Verletzung\/Gefahr?' },\n            { id: 4, icon: '\u23f3', text: 'Warten auf R\u00fcckfragen!' }\n        ];\n\n        var liste = document.getElementById('ffn-liste');\n        var naechsterIndex = 0;\n        var fehler = 0;\n        var startZeit = null;\n        var zeitTimer = null;\n        var laeuft = false;\n\n        function ffnMischen(arr) {\n            var kopie = arr.slice();\n            for (var i = kopie.length - 1; i > 0; i--) {\n                var j = Math.floor(Math.random() * (i + 1));\n                var tmp = kopie[i]; kopie[i] = kopie[j]; kopie[j] = tmp;\n            }\n            return kopie;\n        }\n\n        function ffnAufbauen() {\n            liste.innerHTML = '';\n            var gemischt = ffnMischen(FRAGEN);\n            gemischt.forEach(function(frage) {\n                var el = document.createElement('div');\n                el.className = 'ffn-karte';\n                el.dataset.id = frage.id;\n                el.innerHTML = '<span class=\"icon\">' + frage.icon + '<\/span>' +\n                    '<span class=\"text\">' + frage.text + '<\/span>' +\n                    '<span class=\"platz\"><\/span>';\n                el.addEventListener('click', function() { ffnTippen(el); });\n                liste.appendChild(el);\n            });\n        }\n\n        function ffnTippen(el) {\n            if (!laeuft) return;\n            if (el.classList.contains('richtig')) return;\n            var id = parseInt(el.dataset.id);\n\n            if (id === naechsterIndex) {\n                naechsterIndex++;\n                el.classList.add('richtig');\n                el.querySelector('.platz').textContent = naechsterIndex;\n                if (naechsterIndex === FRAGEN.length) ffnSpielEnde();\n            } else {\n                fehler++;\n                document.getElementById('ffn-fehler').textContent = fehler;\n                el.classList.remove('falsch');\n                void el.offsetWidth; \/\/ Animation neu triggern\n                el.classList.add('falsch');\n            }\n        }\n\n        window.ffnSpielStart = function() {\n            naechsterIndex = 0;\n            fehler = 0;\n            laeuft = true;\n            document.getElementById('ffn-fehler').textContent = '0';\n            document.getElementById('ffn-zeit').textContent = '0';\n            document.getElementById('ffn-start').style.display = 'none';\n            document.getElementById('ffn-ende').style.display = 'none';\n            ffnAufbauen();\n\n            startZeit = Date.now();\n            clearInterval(zeitTimer);\n            zeitTimer = setInterval(function() {\n                document.getElementById('ffn-zeit').textContent = Math.floor((Date.now() - startZeit) \/ 1000);\n            }, 1000);\n        };\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n\n        function ffnSpielEnde() {\n            laeuft = false;\n            clearInterval(zeitTimer);\n            var sekunden = Math.floor((Date.now() - startZeit) \/ 1000);\n            document.getElementById('ffn-endzeit').textContent = sekunden;\n            document.getElementById('ffn-endfehler').textContent = fehler;\n            document.getElementById('ffn-ende').style.display = 'flex';\n\n            var abzeichen = fehler === 0 ? 'gold' : (fehler <= 2 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('notruf', abzeichen);\n        }\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-memory\">\n            <div class=\"ffm-wrap\" id=\"ffm-wrap-1\" data-bildpool=\"[{&quot;name&quot;:&quot;Tragkraftspritzenfahrzeug\\u00a0(TSF)&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/20260418_112633335_iOS-scaled.jpg&quot;},{&quot;name&quot;:&quot;Mehrzweckfahrzeug (MZF)&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/20260418_110657780_iOS-scaled.jpg&quot;},{&quot;name&quot;:&quot;Tierrettung&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/20260502_194643-scaled.jpg&quot;},{&quot;name&quot;:&quot;THL TRAGEHILFE HERZ-KREISLAUF-Vitale Bedrohung&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/images.jpeg&quot;},{&quot;name&quot;:&quot;Garagenbrand&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/2025-12.png&quot;},{&quot;name&quot;:&quot;Verkehrsunfall&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/2025-11.png&quot;},{&quot;name&quot;:&quot;Verkehrsunfall&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/VU_Dummy.png&quot;},{&quot;name&quot;:&quot;Rauchmelder&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/Feuerwehr_Dummy_Einsatz.png&quot;},{&quot;name&quot;:&quot;Technische Hilfe&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/2025-7.png&quot;},{&quot;name&quot;:&quot;Garagenbrand&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/20260407_1947091-1-scaled.jpg&quot;},{&quot;name&quot;:&quot;eCall Alarm&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/IMG_2578.jpeg&quot;},{&quot;name&quot;:&quot;Kaminbrand&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/Einsatz2-2026.png&quot;},{&quot;name&quot;:&quot;Scheunenbrand in Siegertshofen&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/1_1.png&quot;},{&quot;name&quot;:&quot;Besichtigung unserer Feuerwehr&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/06\\\/IMG-20260616-WA0012-1024x768.jpg&quot;},{&quot;name&quot;:&quot;Nachlese Jahreshauptversammlung 2025 vom 31.1.26&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/jvh_demo.png&quot;},{&quot;name&quot;:&quot;Maibaum 2026&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/72e342f8-3f0c-4592-b00c-9c48e75136d5-768x1024.jpg&quot;}]\" data-bildpool-lz=\"[{&quot;name&quot;:&quot;L\\u00f6schzwergen \\u00dcbung&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/20260710_161424-768x1024.jpg&quot;},{&quot;name&quot;:&quot;L\\u00f6schzwergen \\u00dcbung&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/1000107866-768x1024.jpg&quot;},{&quot;name&quot;:&quot;L\\u00f6schzwergen \\u00dcbung&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/IMG-20260710-WA0111-768x1024.jpg&quot;},{&quot;name&quot;:&quot;Maifeier&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/IMG_2237-887x1024.jpeg&quot;},{&quot;name&quot;:&quot;Maibaum Vorbereitungen Tag 1&quot;,&quot;bild&quot;:&quot;https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/IMG_2236-737x1024.jpeg&quot;}]\">\n        <style>\n            .ffm-wrap { max-width: 480px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffm-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 20px; color: #fff !important; text-align: center; position: relative; overflow: hidden; }\n            .ffm-spielfeld { position: relative; min-height: 460px !important; }\n            .ffm-title { font-size: 22px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffm-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; }\n            .ffm-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; font-size: 14px; font-weight: 700; color: #fff !important; }\n\n            .ffm-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 6px; perspective: 800px; }\n            .ffm-karte { position: relative; aspect-ratio: 3 \/ 4; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n            .ffm-karte-inner { position: relative; width: 100%; height: 100%; transition: transform 0.5s; transform-style: preserve-3d; }\n            .ffm-karte.aufgedeckt .ffm-karte-inner, .ffm-karte.gefunden .ffm-karte-inner { transform: rotateY(180deg); }\n            .ffm-vorder, .ffm-rueck { position: absolute; inset: 0; backface-visibility: hidden; border-radius: 8px; display: flex; align-items: center; justify-content: center; overflow: hidden; }\n            .ffm-vorder { background: rgba(255,255,255,0.08); border: 2px solid rgba(255,255,255,0.15); font-size: 24px; }\n            .ffm-rueck { background: var(--ff-blue-darker, #0f1e38); border: 2px solid var(--ff-red, #CC0000); transform: rotateY(180deg); }\n            .ffm-rueck img { width: 100%; height: 100%; object-fit: cover; }\n            .ffm-karte.gefunden .ffm-rueck { border-color: #3fae4a; }\n            .ffm-karte.gefunden { cursor: default; }\n\n            .ffm-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px; border-radius: 12px; z-index: 3; color: #fff !important; overflow-y: auto; }\n            .ffm-overlay h3 { font-size: 22px; margin-bottom: 8px; color: #fff !important; }\n            .ffm-overlay p { font-size: 14px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; line-height: 1.6; }\n            .ffm-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .ffm-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffm-ergebnis { font-size: 15px; margin-bottom: 18px; color: #fff !important; }\n            .ffm-ergebnis strong { color: gold !important; }\n            .ffm-hinweis { font-size: 12px; color: gold !important; margin-bottom: 12px; }\n\n            .ffm-alter-buttons { display: flex; flex-direction: column; gap: 8px; width: 100%; margin-bottom: 4px; }\n            .ffm-alter-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: #fff !important; padding: 10px 16px; border-radius: 8px; font-size: 14px; font-weight: 700; cursor: pointer; font-family: inherit; text-align: left; display: flex; align-items: center; justify-content: space-between; }\n            .ffm-alter-btn:hover { border-color: var(--ff-red, #CC0000); background: rgba(204,0,0,0.15); }\n            .ffm-alter-btn span.ffm-alter-sub { font-size: 12px; font-weight: 400; color: var(--ff-text-muted, #a0b0c8) !important; }\n\n            .ffm-rang-btn { background: none; border: 1px solid gold; color: gold !important; padding: 6px 16px; border-radius: 20px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; margin-bottom: 4px; }\n            .ffm-rang-btn:hover { background: gold; color: #1C2B4B !important; }\n            .ffm-mini-rang { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,215,0,0.3); border-radius: 8px; padding: 10px 14px; margin-bottom: 14px; text-align: left; }\n            .ffm-mini-rang-titel { font-size: 12px; font-weight: 700; color: gold !important; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 6px; text-align: center; }\n            .ffm-mini-rang-zeile { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; color: #fff !important; }\n            .ffm-mini-rang-platz { width: 18px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffm-mini-rang-name { flex: 1; }\n            .ffm-mini-rang-score { font-weight: 700; }\n            .ffm-mini-rang-leer { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; text-align: center; }\n\n            .ffm-tab-reihe { display: flex; gap: 6px; margin-bottom: 10px; justify-content: center; flex-wrap: wrap; }\n            .ffm-tab-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: var(--ff-text-muted, #a0b0c8) !important; padding: 5px 10px; border-radius: 20px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit; }\n            .ffm-tab-btn.aktiv { background: gold; border-color: gold; color: #1C2B4B !important; }\n\n            .ffm-eintrag-wrap { width: 100%; margin-bottom: 16px; }\n            .ffm-name-input { width: 100%; box-sizing: border-box; padding: 10px 14px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.25) !important; background: rgba(255,255,255,0.08) !important; color: #fff !important; font-size: 14px; font-family: inherit; margin-bottom: 10px; text-align: center; }\n            .ffm-name-input::placeholder { color: var(--ff-text-muted, #a0b0c8) !important; }\n            .ffm-btn-klein { padding: 8px 22px; font-size: 13px; }\n            .ffm-btn:disabled { opacity: 0.5; cursor: default; }\n            .ffm-eintrag-status { font-size: 12px; color: gold !important; margin-top: 8px; min-height: 16px; }\n\n            .ffm-rang-liste { width: 100%; max-height: 300px; overflow-y: auto; margin-bottom: 16px; }\n            .ffm-rang-zeile { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 6px; font-size: 14px; color: #fff !important; }\n            .ffm-rang-zeile:nth-child(odd) { background: rgba(255,255,255,0.05); }\n            .ffm-rang-platz { width: 24px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffm-rang-name { flex: 1; text-align: left; color: #fff !important; }\n            .ffm-rang-score { font-weight: 700; color: #fff !important; }\n            .ffm-rang-leer { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; }\n        <\/style>\n\n        <div class=\"ffm-box\">\n            <div class=\"ffm-title\">\ud83d\ude92 Feuerwehr Willmatshofen Memory<\/div>\n            <div class=\"ffm-untertitel\">Findet alle Paare unserer Fahrzeuge & Eins\u00e4tze!<\/div>\n\n            <div class=\"ffm-mini-rang\">\n                <div class=\"ffm-mini-rang-titel\">\ud83c\udfc6 Bestenliste (wenigste Z\u00fcge)<\/div>\n                <div class=\"ffm-tab-reihe ffm-mini-tabs\">\n                    <button class=\"ffm-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76<\/button>\n                    <button class=\"ffm-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2<\/button>\n                    <button class=\"ffm-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92<\/button>\n                <\/div>\n                <div class=\"ffm-mini-rang-inhalt\">L\u00e4dt \u2026<\/div>\n            <\/div>\n            <button class=\"ffm-rang-btn ffm-rang-oeffnen-btn\" type=\"button\">Komplette Rangliste<\/button>\n\n            <div class=\"ffm-spielfeld\">\n                <div class=\"ffm-hud\">\n                    <span>\u23f1\ufe0f <span class=\"ffm-zeit\">0<\/span>s<\/span>\n                    <span>\ud83d\udd04 Z\u00fcge: <span class=\"ffm-zuege\">0<\/span><\/span>\n                <\/div>\n\n                <div class=\"ffm-grid\"><\/div>\n\n                <div class=\"ffm-overlay ffm-start\">\n                    <h3>Bereit zum Merken?<\/h3>\n                    <p>Deckt zwei Karten auf - passen sie zusammen, bleiben sie offen liegen.\n                    Wie alt bist du? Danach richtet sich die Anzahl der Paare.<\/p>\n                    <div class=\"ffm-alter-buttons\">\n                        <button class=\"ffm-alter-btn\" data-paare=\"8\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerg <span class=\"ffm-alter-sub\">8 Paare<\/span><\/button>\n                        <button class=\"ffm-alter-btn\" data-paare=\"15\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend <span class=\"ffm-alter-sub\">15 Paare<\/span><\/button>\n                        <button class=\"ffm-alter-btn\" data-paare=\"20\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene <span class=\"ffm-alter-sub\">20 Paare<\/span><\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"ffm-overlay ffm-ende\" style=\"display:none;\">\n                    <h3>Alle Paare gefunden! \ud83c\udf89<\/h3>\n                    <div class=\"ffm-ergebnis\">\n                        Zeit: <strong><span class=\"ffm-endzeit\">0<\/span> Sekunden<\/strong><br>\n                        Z\u00fcge: <strong><span class=\"ffm-endzuege\">0<\/span><\/strong>\n                    <\/div>\n                    <div class=\"ffm-eintrag-wrap\">\n                        <input type=\"text\" class=\"ffm-name-input\" maxlength=\"20\" placeholder=\"Dein Name f\u00fcr die Rangliste\">\n                        <button class=\"ffm-btn ffm-btn-klein ffm-eintrag-btn\" type=\"button\">In Rangliste eintragen<\/button>\n                        <div class=\"ffm-eintrag-status\"><\/div>\n                    <\/div>\n                    <button class=\"ffm-btn ffm-neustart-btn\" type=\"button\">Nochmal w\u00e4hlen<\/button>\n                <\/div>\n            <\/div>\n\n            <div class=\"ffm-overlay ffm-rangliste-overlay\" style=\"display:none;\">\n                <h3>\ud83c\udfc6 Rangliste<\/h3>\n                <div class=\"ffm-tab-reihe ffm-voll-tabs\">\n                    <button class=\"ffm-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerge<\/button>\n                    <button class=\"ffm-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend<\/button>\n                    <button class=\"ffm-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene<\/button>\n                <\/div>\n                <div class=\"ffm-rang-liste ffm-rang-liste-inhalt\">L\u00e4dt \u2026<\/div>\n                <button class=\"ffm-btn ffm-rang-schliessen-btn\" type=\"button\">Schlie\u00dfen<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var wrap = document.getElementById('ffm-wrap-1');\n        if (!wrap) return;\n\n        var NONCE   = '7bb247d64c';\n        var AJAXURL = 'https:\/\/ff-willmatshofen.de\/wp-admin\/admin-ajax.php';\n\n        function ffmSpielerId() {\n            var id = null;\n            try { id = localStorage.getItem('ffs_player_id'); } catch (e) {}\n            if (!id) {\n                id = (window.crypto && crypto.randomUUID)\n                    ? crypto.randomUUID()\n                    : ('id-' + Date.now() + '-' + Math.random().toString(16).slice(2));\n                try { localStorage.setItem('ffs_player_id', id); } catch (e) {}\n            }\n            return id;\n        }\n\n        \/\/ Bildpool kommt als HTML-Attribut (sauber escaped), nicht als\n        \/\/ roher Text im Script-Tag - robust gegen\u00fcber Plugins\/Filtern,\n        \/\/ die Anf\u00fchrungszeichen in Titeln\/HTML sonst durcheinanderbringen.\n        var BILDPOOL = JSON.parse(wrap.dataset.bildpool);\n        var BILDPOOL_LZ = JSON.parse(wrap.dataset.bildpoolLz || '[]');\n\n        var grid          = wrap.querySelector('.ffm-grid');\n        var startOverlay  = wrap.querySelector('.ffm-start');\n        var endeOverlay   = wrap.querySelector('.ffm-ende');\n        var zeitAnzeige   = wrap.querySelector('.ffm-zeit');\n        var zuegeAnzeige  = wrap.querySelector('.ffm-zuege');\n        var endzeitAnzeige  = wrap.querySelector('.ffm-endzeit');\n        var endzuegeAnzeige = wrap.querySelector('.ffm-endzuege');\n\n        var ranglisteOverlay = wrap.querySelector('.ffm-rangliste-overlay');\n        var miniRangInhalt   = wrap.querySelector('.ffm-mini-rang-inhalt');\n        var vollRangInhalt   = wrap.querySelector('.ffm-rang-liste-inhalt');\n        var nameInput        = wrap.querySelector('.ffm-name-input');\n        var eintragBtn        = wrap.querySelector('.ffm-eintrag-btn');\n        var eintragStatus      = wrap.querySelector('.ffm-eintrag-status');\n\n        var aktuelleAltersstufe = 'erwachsene';\n\n        var aktuellePaare = [];\n        var aufgedeckt = [];\n        var gefundenPaare = 0;\n        var zuege = 0;\n        var laeuft = false;\n        var sperre = false;\n        var startZeit = null;\n        var zeitTimer = null;\n\n        function ffmMischen(arr) {\n            var kopie = arr.slice();\n            for (var i = kopie.length - 1; i > 0; i--) {\n                var j = Math.floor(Math.random() * (i + 1));\n                var tmp = kopie[i]; kopie[i] = kopie[j]; kopie[j] = tmp;\n            }\n            return kopie;\n        }\n\n        \/\/ F\u00fcr \"L\u00f6schzwerg\" zuerst den eigenen Pool (Neuigkeiten-Kategorie\n        \/\/ \"L\u00f6schzwerge\" + markierte Termine) verwenden, nur bei Bedarf mit\n        \/\/ dem allgemeinen Pool auff\u00fcllen. F\u00fcr Jugend\/Erwachsene direkt der\n        \/\/ allgemeine Pool wie bisher.\n        function ffmBildauswahlFuerStufe(altersstufe, ziel) {\n            if (altersstufe === 'loeschzwerg' && BILDPOOL_LZ.length > 0) {\n                var ausgewaehlt = ffmMischen(BILDPOOL_LZ).slice(0, ziel);\n                if (ausgewaehlt.length < ziel) {\n                    var fehlend = ziel - ausgewaehlt.length;\n                    var ergaenzung = BILDPOOL.filter(function(b) {\n                        return !ausgewaehlt.some(function(a) { return a.bild === b.bild; });\n                    });\n                    ausgewaehlt = ausgewaehlt.concat(ffmMischen(ergaenzung).slice(0, fehlend));\n                }\n                return ffmMischen(ausgewaehlt);\n            }\n            return ffmMischen(BILDPOOL).slice(0, ziel);\n        }\n\n        function ffmAufbauen() {\n            grid.innerHTML = '';\n            var paare = [];\n            aktuellePaare.forEach(function(fz, i) {\n                paare.push({ pairId: i, name: fz.name, bild: fz.bild });\n                paare.push({ pairId: i, name: fz.name, bild: fz.bild });\n            });\n            paare = ffmMischen(paare);\n\n            paare.forEach(function(karte) {\n                var el = document.createElement('div');\n                el.className = 'ffm-karte';\n                el.dataset.pair = karte.pairId;\n                el.innerHTML =\n                    '<div class=\"ffm-karte-inner\">' +\n                        '<div class=\"ffm-vorder\">\ud83d\ude92<\/div>' +\n                        '<div class=\"ffm-rueck\"><img decoding=\"async\" src=\"' + karte.bild + '\" alt=\"' + karte.name.replace(\/\"\/g,'&quot;') + '\" loading=\"lazy\"><\/div>' +\n                    '<\/div>';\n                el.addEventListener('click', function() { ffmTippen(el); });\n                grid.appendChild(el);\n            });\n        }\n\n        function ffmTippen(el) {\n            if (!laeuft || sperre) return;\n            if (el.classList.contains('aufgedeckt') || el.classList.contains('gefunden')) return;\n            if (aufgedeckt.length >= 2) return;\n\n            el.classList.add('aufgedeckt');\n            aufgedeckt.push(el);\n\n            if (aufgedeckt.length === 2) {\n                zuege++;\n                zuegeAnzeige.textContent = zuege;\n                var a = aufgedeckt[0], b = aufgedeckt[1];\n\n                if (a.dataset.pair === b.dataset.pair) {\n                    a.classList.add('gefunden');\n                    b.classList.add('gefunden');\n                    a.classList.remove('aufgedeckt');\n                    b.classList.remove('aufgedeckt');\n                    aufgedeckt = [];\n                    gefundenPaare++;\n                    if (gefundenPaare === aktuellePaare.length) ffmSpielEnde();\n                } else {\n                    sperre = true;\n                    setTimeout(function() {\n                        a.classList.remove('aufgedeckt');\n                        b.classList.remove('aufgedeckt');\n                        aufgedeckt = [];\n                        sperre = false;\n                    }, 900);\n                }\n            }\n        }\n\n        function ffmSpielStart(gewuenschtePaare, altersstufe) {\n            aktuelleAltersstufe = altersstufe;\n            try { localStorage.setItem('ffm_last_bracket', altersstufe); } catch (e) {}\n\n            var ziel = Math.min(gewuenschtePaare, BILDPOOL_LZ.length + BILDPOOL.length);\n            aktuellePaare = ffmBildauswahlFuerStufe(altersstufe, ziel);\n\n            aufgedeckt = [];\n            gefundenPaare = 0;\n            zuege = 0;\n            laeuft = true;\n            sperre = false;\n            zuegeAnzeige.textContent = '0';\n            zeitAnzeige.textContent = '0';\n            startOverlay.style.display = 'none';\n            endeOverlay.style.display = 'none';\n            ranglisteOverlay.style.display = 'none';\n\n            nameInput.value = '';\n            eintragBtn.disabled = false;\n            eintragStatus.textContent = '';\n\n            ffmAufbauen();\n\n            startZeit = Date.now();\n            clearInterval(zeitTimer);\n            zeitTimer = setInterval(function() {\n                zeitAnzeige.textContent = Math.floor((Date.now() - startZeit) \/ 1000);\n            }, 1000);\n        }\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n\n        function ffmSpielEnde() {\n            laeuft = false;\n            clearInterval(zeitTimer);\n\n            var faktor = zuege \/ aktuellePaare.length;\n            var abzeichen = faktor <= 1.5 ? 'gold' : (faktor <= 2.2 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('memory', abzeichen);\n            var sekunden = Math.floor((Date.now() - startZeit) \/ 1000);\n            endzeitAnzeige.textContent = sekunden;\n            endzuegeAnzeige.textContent = zuege;\n            setTimeout(function() {\n                endeOverlay.style.display = 'flex';\n            }, 500);\n        }\n\n        \/\/ ---------- Rangliste: gemeinsame Hilfsfunktionen ----------\n        function ffmRangZeilenHtml(liste, klassenPrefix) {\n            var html = '';\n            liste.forEach(function(eintrag, i) {\n                html += '<div class=\"' + klassenPrefix + '-zeile\">' +\n                    '<span class=\"' + klassenPrefix + '-platz\">' + (i + 1) + '.<\/span>' +\n                    '<span class=\"' + klassenPrefix + '-name\">' + ffmEscapeHtml(eintrag.name) + '<\/span>' +\n                    '<span class=\"' + klassenPrefix + '-score\">' + eintrag.zuege + ' Z\u00fcge (' + eintrag.zeit + 's)<\/span>' +\n                '<\/div>';\n            });\n            return html;\n        }\n\n        function ffmEscapeHtml(str) {\n            var div = document.createElement('div');\n            div.textContent = str;\n            return div.innerHTML;\n        }\n\n        function ffmRanglisteHolen(altersstufe, callback) {\n            var formData = new FormData();\n            formData.append('action', 'ff_memory_rangliste_holen');\n            formData.append('nonce', NONCE);\n            formData.append('altersstufe', altersstufe);\n            fetch(AJAXURL, { method: 'POST', body: formData })\n                .then(function(r) { return r.json(); })\n                .then(function(data) { callback((data.success && data.data) ? data.data : []); })\n                .catch(function() { callback(null); });\n        }\n\n        function ffmLetzteAltersstufe() {\n            var stufe = null;\n            try { stufe = localStorage.getItem('ffm_last_bracket'); } catch (e) {}\n            return (stufe === 'loeschzwerg' || stufe === 'jugend' || stufe === 'erwachsene') ? stufe : 'erwachsene';\n        }\n\n        function ffmTabsAktualisieren(selector, aktiveStufe) {\n            wrap.querySelectorAll(selector + ' .ffm-tab-btn').forEach(function(btn) {\n                btn.classList.toggle('aktiv', btn.dataset.stufe === aktiveStufe);\n            });\n        }\n\n        \/\/ ---------- Mini-Bestenliste ----------\n        var ffmMiniStufe = ffmLetzteAltersstufe();\n\n        function ffmMiniRanglisteLaden() {\n            ffmTabsAktualisieren('.ffm-mini-tabs', ffmMiniStufe);\n            miniRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            ffmRanglisteHolen(ffmMiniStufe, function(liste) {\n                if (liste === null) {\n                    miniRangInhalt.innerHTML = '<div class=\"ffm-mini-rang-leer\">Rangliste konnte nicht geladen werden.<\/div>';\n                    return;\n                }\n                if (!liste.length) {\n                    miniRangInhalt.innerHTML = '<div class=\"ffm-mini-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/div>';\n                    return;\n                }\n                miniRangInhalt.innerHTML = ffmRangZeilenHtml(liste.slice(0, 5), 'ffm-mini-rang');\n            });\n        }\n        wrap.querySelectorAll('.ffm-mini-tabs .ffm-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() {\n                ffmMiniStufe = btn.dataset.stufe;\n                ffmMiniRanglisteLaden();\n            });\n        });\n        ffmMiniRanglisteLaden();\n\n        \/\/ ---------- Volle Rangliste ----------\n        var ffmVollStufe = ffmLetzteAltersstufe();\n\n        function ffmVollRanglisteLaden() {\n            ffmTabsAktualisieren('.ffm-voll-tabs', ffmVollStufe);\n            vollRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            ffmRanglisteHolen(ffmVollStufe, function(liste) {\n                if (liste === null) {\n                    vollRangInhalt.innerHTML = '<p class=\"ffm-rang-leer\">Rangliste konnte nicht geladen werden.<\/p>';\n                    return;\n                }\n                if (!liste.length) {\n                    vollRangInhalt.innerHTML = '<p class=\"ffm-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/p>';\n                    return;\n                }\n                vollRangInhalt.innerHTML = ffmRangZeilenHtml(liste, 'ffm-rang');\n            });\n        }\n        wrap.querySelectorAll('.ffm-voll-tabs .ffm-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() {\n                ffmVollStufe = btn.dataset.stufe;\n                ffmVollRanglisteLaden();\n            });\n        });\n        wrap.querySelector('.ffm-rang-oeffnen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'flex';\n            ffmVollRanglisteLaden();\n        });\n        wrap.querySelector('.ffm-rang-schliessen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'none';\n        });\n\n        \/\/ ---------- Ergebnis eintragen ----------\n        eintragBtn.addEventListener('click', function() {\n            var name = nameInput.value.trim();\n            if (!name) { eintragStatus.textContent = 'Bitte einen Namen eingeben.'; return; }\n\n            eintragBtn.disabled = true;\n            eintragStatus.textContent = 'Wird gespeichert \u2026';\n\n            var formData = new FormData();\n            formData.append('action', 'ff_memory_score_speichern');\n            formData.append('nonce', NONCE);\n            formData.append('name', name);\n            formData.append('zuege', zuege);\n            formData.append('zeit', zeitAnzeige.textContent);\n            formData.append('spieler_id', ffmSpielerId());\n            formData.append('altersstufe', aktuelleAltersstufe);\n\n            fetch(AJAXURL, { method: 'POST', body: formData })\n                .then(function(r) { return r.json(); })\n                .then(function(data) {\n                    if (data.success) {\n                        if (data.data && data.data.verbessert === false) {\n                            eintragStatus.textContent = 'Dein bisheriger Eintrag war schon besser oder gleich gut \u2013 bleibt unver\u00e4ndert.';\n                        } else {\n                            eintragStatus.textContent = '\u2705 In der Rangliste eingetragen!';\n                        }\n                        ffmMiniStufe = aktuelleAltersstufe;\n                        ffmMiniRanglisteLaden();\n                    } else if (data.data && data.data.grund === 'name_vergeben') {\n                        eintragStatus.textContent = '\u26a0\ufe0f Dieser Name ist schon vergeben \u2013 bitte einen anderen w\u00e4hlen.';\n                        eintragBtn.disabled = false;\n                    } else {\n                        eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                        eintragBtn.disabled = false;\n                    }\n                })\n                .catch(function() {\n                    eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                    eintragBtn.disabled = false;\n                });\n        });\n\n        \/\/ Poolgr\u00f6\u00dfe direkt an den Buttons anzeigen, damit klar ist, wenn eine\n        \/\/ Altersstufe wegen zu weniger Fotos automatisch reduziert oder\n        \/\/ aufgef\u00fcllt wird.\n        wrap.querySelectorAll('.ffm-alter-btn').forEach(function(btn) {\n            var gewuenscht = parseInt(btn.dataset.paare);\n            var sub = btn.querySelector('.ffm-alter-sub');\n\n            if (btn.dataset.stufe === 'loeschzwerg') {\n                if (BILDPOOL_LZ.length >= gewuenscht) {\n                    sub.textContent = gewuenscht + ' Paare (eigene L\u00f6schzwerge-Fotos)';\n                } else if (BILDPOOL_LZ.length > 0) {\n                    sub.textContent = gewuenscht + ' Paare (' + BILDPOOL_LZ.length + ' eigene Fotos + Rest gemischt)';\n                } else {\n                    sub.textContent = gewuenscht + ' Paare (noch keine eigenen Fotos, gemischter Pool)';\n                }\n            } else if (BILDPOOL.length < gewuenscht) {\n                sub.textContent = Math.min(gewuenscht, BILDPOOL.length) + ' Paare (nur ' + BILDPOOL.length + ' Fotos verf\u00fcgbar)';\n            }\n        });\n\n        wrap.querySelectorAll('.ffm-alter-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() {\n                ffmSpielStart(parseInt(btn.dataset.paare), btn.dataset.stufe);\n            });\n        });\n        wrap.querySelector('.ffm-neustart-btn').addEventListener('click', function() {\n            endeOverlay.style.display = 'none';\n            startOverlay.style.display = 'flex';\n        });\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-quiz\">\n            <div class=\"ffq-wrap\" id=\"ffq-wrap-1\" data-fragen=\"[{&quot;frage&quot;:&quot;Welche Rufnummer w\\u00e4hlt man in Deutschland f\\u00fcr die Feuerwehr?&quot;,&quot;antworten&quot;:[&quot;110&quot;,&quot;112&quot;,&quot;19222&quot;,&quot;116117&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Wie viele \\&quot;W-Fragen\\&quot; sollte man beim Notruf beantworten?&quot;,&quot;antworten&quot;:[&quot;3&quot;,&quot;4&quot;,&quot;5&quot;,&quot;7&quot;],&quot;richtig&quot;:2},{&quot;frage&quot;:&quot;Ist der Notruf 112 auch im EU-Ausland kostenlos erreichbar?&quot;,&quot;antworten&quot;:[&quot;Ja, \\u00fcberall in der EU&quot;,&quot;Nein, nur in Deutschland&quot;,&quot;Nur mit Vertrag&quot;,&quot;Nur tags\\u00fcber&quot;],&quot;richtig&quot;:0},{&quot;frage&quot;:&quot;Was sollte man im Brandfall NICHT benutzen, um ein Geb\\u00e4ude zu verlassen?&quot;,&quot;antworten&quot;:[&quot;Treppe&quot;,&quot;Aufzug&quot;,&quot;Notausgang&quot;,&quot;Fenster im Erdgeschoss&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Wof\\u00fcr steht die Abk\\u00fcrzung \\&quot;AGT\\&quot;?&quot;,&quot;antworten&quot;:[&quot;Atemschutzger\\u00e4tetr\\u00e4ger&quot;,&quot;Allgemeine Grundtaktik&quot;,&quot;Aktiver Gefahrguttrupp&quot;,&quot;Automatisches Ger\\u00e4tetableau&quot;],&quot;richtig&quot;:0},{&quot;frage&quot;:&quot;Was bedeutet ein 1-min\\u00fctiger Dauerton der Sirene?&quot;,&quot;antworten&quot;:[&quot;Feuer&quot;,&quot;Entwarnung&quot;,&quot;Probealarm&quot;,&quot;Hochwasser&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Was ist die Aufgabe eines Rauchmelders?&quot;,&quot;antworten&quot;:[&quot;Feuer l\\u00f6schen&quot;,&quot;Bei Rauch akustisch warnen&quot;,&quot;Fenster automatisch \\u00f6ffnen&quot;,&quot;Notruf automatisch w\\u00e4hlen&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Welches L\\u00f6schmittel eignet sich NICHT f\\u00fcr einen Fettbrand?&quot;,&quot;antworten&quot;:[&quot;L\\u00f6schdecke&quot;,&quot;Spezial-Fettbrand-L\\u00f6scher&quot;,&quot;Wasser&quot;,&quot;Deckel drauf (ersticken)&quot;],&quot;richtig&quot;:2},{&quot;frage&quot;:&quot;Wie oft sollte man Rauchmelder-Batterien mindestens testen?&quot;,&quot;antworten&quot;:[&quot;Nie&quot;,&quot;Einmal im Jahr&quot;,&quot;Alle 10 Jahre&quot;,&quot;Nur beim Einbau&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Wer gilt als Schutzpatron der Feuerwehr (Namensgeber f\\u00fcr Funkrufnamen wie \\&quot;Florian\\&quot;)?&quot;,&quot;antworten&quot;:[&quot;Heiliger Florian&quot;,&quot;Heiliger Martin&quot;,&quot;Heiliger Georg&quot;,&quot;Heiliger Christophorus&quot;],&quot;richtig&quot;:0},{&quot;frage&quot;:&quot;Welche Farbe haben Feuerwehrfahrzeuge in Deutschland meist?&quot;,&quot;antworten&quot;:[&quot;Gelb&quot;,&quot;Rot&quot;,&quot;Gr\\u00fcn&quot;,&quot;Blau&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Wof\\u00fcr steht die Abk\\u00fcrzung \\&quot;THW\\&quot;?&quot;,&quot;antworten&quot;:[&quot;Technisches Hilfswerk&quot;,&quot;Technischer Hilfsdienst Wache&quot;,&quot;Team Hilfe Wasser&quot;,&quot;Technische Hauptwache&quot;],&quot;richtig&quot;:0},{&quot;frage&quot;:&quot;Welches Ger\\u00e4t wird benutzt, um T\\u00fcren im Notfall gewaltsam zu \\u00f6ffnen?&quot;,&quot;antworten&quot;:[&quot;Feuerl\\u00f6scher&quot;,&quot;Rettungsspreizer&quot;,&quot;Schlauchhaspel&quot;,&quot;Kettens\\u00e4ge&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Wie nennt man den Ort, an dem Feuerwehrfahrzeuge stationiert sind?&quot;,&quot;antworten&quot;:[&quot;Feuerwehrhaus \\\/ Ger\\u00e4tehaus&quot;,&quot;Depot&quot;,&quot;Kaserne&quot;,&quot;Lager&quot;],&quot;richtig&quot;:0},{&quot;frage&quot;:&quot;Was sollte man tun, wenn die eigene Kleidung brennt?&quot;,&quot;antworten&quot;:[&quot;Rennen&quot;,&quot;Hinlegen und w\\u00e4lzen&quot;,&quot;Wasser vermeiden&quot;,&quot;Sofort ausziehen und wegwerfen&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Was ist ein Hydrant?&quot;,&quot;antworten&quot;:[&quot;Ein Feuerl\\u00f6schger\\u00e4t&quot;,&quot;Ein Wasserentnahmepunkt aus dem Leitungsnetz&quot;,&quot;Eine Sirene&quot;,&quot;Ein Fahrzeugtyp&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Was bedeuten Blaulicht und Martinshorn zusammen?&quot;,&quot;antworten&quot;:[&quot;Vorfahrt f\\u00fcr alle&quot;,&quot;Sonderrechte f\\u00fcr Einsatzfahrzeuge&quot;,&quot;Stauwarnung&quot;,&quot;Nichts Besonderes&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Wie alt muss man laut eurer Vereinsseite mindestens sein, um bei den L\\u00f6schzwergen mitzumachen?&quot;,&quot;antworten&quot;:[&quot;4 Jahre&quot;,&quot;6 Jahre&quot;,&quot;8 Jahre&quot;,&quot;10 Jahre&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Was ist die Hauptaufgabe der L\\u00f6schzwerge\\\/Jugendfeuerwehr?&quot;,&quot;antworten&quot;:[&quot;Spielerisch Feuerwehrwissen lernen&quot;,&quot;Sofort echte Eins\\u00e4tze fahren&quot;,&quot;Nur zuschauen&quot;,&quot;Ausr\\u00fcstung reparieren&quot;],&quot;richtig&quot;:0},{&quot;frage&quot;:&quot;Welches Fahrzeug bringt meist Mannschaft UND L\\u00f6schwasser zum Einsatzort?&quot;,&quot;antworten&quot;:[&quot;Rettungswagen&quot;,&quot;L\\u00f6schfahrzeug&quot;,&quot;Streifenwagen&quot;,&quot;Kranwagen&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Was bedeutet es, wenn ein Rauchmelder regelm\\u00e4\\u00dfig kurz piept?&quot;,&quot;antworten&quot;:[&quot;Es brennt gerade&quot;,&quot;Die Batterie ist bald leer&quot;,&quot;Er ist kaputt und egal&quot;,&quot;Er testet sich selbst dauerhaft&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Was sollte man bei einem Wohnungsbrand als Erstes tun?&quot;,&quot;antworten&quot;:[&quot;Selbst l\\u00f6schen versuchen&quot;,&quot;Notruf 112 w\\u00e4hlen&quot;,&quot;Fenster \\u00f6ffnen&quot;,&quot;Fotos machen&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Wie nennt man den vereinbarten Treffpunkt au\\u00dferhalb eines brennenden Geb\\u00e4udes?&quot;,&quot;antworten&quot;:[&quot;L\\u00f6schplatz&quot;,&quot;Sammelplatz&quot;,&quot;Wartezone&quot;,&quot;Feuerplatz&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Was ist beim Verlassen eines verrauchten Raums wichtig?&quot;,&quot;antworten&quot;:[&quot;Aufrecht und schnell laufen&quot;,&quot;Niedrig bleiben \\\/ kriechen&quot;,&quot;Die Luft anhalten und rennen&quot;,&quot;R\\u00fcckw\\u00e4rts gehen&quot;],&quot;richtig&quot;:1},{&quot;frage&quot;:&quot;Wof\\u00fcr steht die Feuerwehr-Abk\\u00fcrzung \\&quot;ELW\\&quot;?&quot;,&quot;antworten&quot;:[&quot;Einsatzleitwagen&quot;,&quot;Erste-L\\u00f6schwagen&quot;,&quot;Elektro-L\\u00f6schwagen&quot;,&quot;Einsatz-L\\u00f6sch-Wache&quot;],&quot;richtig&quot;:0}]\">\n        <style>\n            .ffq-wrap { max-width: 440px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffq-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 22px; color: #fff !important; text-align: center; position: relative; overflow: hidden; }\n            .ffq-title { font-size: 22px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffq-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; }\n            .ffq-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; font-size: 14px; font-weight: 700; color: #fff !important; }\n            .ffq-spielfeld { position: relative; min-height: 320px !important; }\n            .ffq-fortschritt { width: 100%; height: 6px; background: rgba(255,255,255,0.12); border-radius: 3px; margin-bottom: 18px; overflow: hidden; }\n            .ffq-fortschritt-balken { height: 100%; background: var(--ff-red, #CC0000); border-radius: 3px; transition: width 0.3s; }\n\n            .ffq-frage { font-size: 17px; font-weight: 700; color: #fff !important; margin-bottom: 18px; line-height: 1.5; min-height: 50px; }\n            .ffq-antworten { display: flex; flex-direction: column; gap: 10px; }\n            .ffq-antwort-btn { background: rgba(255,255,255,0.06); border: 2px solid rgba(255,255,255,0.15); color: #fff !important; padding: 12px 16px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; font-family: inherit; text-align: left; transition: border-color 0.2s, background 0.2s; }\n            .ffq-antwort-btn:hover:not(:disabled) { border-color: var(--ff-red, #CC0000); }\n            .ffq-antwort-btn:disabled { cursor: default; }\n            .ffq-antwort-btn.richtig { border-color: #3fae4a; background: rgba(63,174,74,0.2); }\n            .ffq-antwort-btn.falsch { border-color: var(--ff-red, #CC0000); background: rgba(204,0,0,0.2); }\n\n            .ffq-weiter-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; margin-top: 18px; display: none; }\n            .ffq-weiter-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffq-weiter-btn.sichtbar { display: inline-block; }\n\n            .ffq-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px; border-radius: 12px; z-index: 3; color: #fff !important; }\n            .ffq-overlay h3 { font-size: 22px; margin-bottom: 8px; color: #fff !important; }\n            .ffq-overlay p { font-size: 14px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 18px; line-height: 1.6; }\n            .ffq-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .ffq-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffq-score-gross { font-size: 44px; font-weight: 900; margin: 6px 0; color: #fff !important; }\n        <\/style>\n\n        <div class=\"ffq-box\">\n            <div class=\"ffq-title\">\ud83e\uddef Feuerwehr-Quiz<\/div>\n            <div class=\"ffq-untertitel\">10 Fragen rund um Brandschutz &amp; Notruf<\/div>\n\n            <div class=\"ffq-spielfeld\">\n                <div class=\"ffq-hud\">\n                    <span>Frage <span class=\"ffq-nr\">1<\/span>\/10<\/span>\n                    <span>\u2705 Richtig: <span class=\"ffq-richtig-anzahl\">0<\/span><\/span>\n                <\/div>\n                <div class=\"ffq-fortschritt\"><div class=\"ffq-fortschritt-balken\" style=\"width:0%\"><\/div><\/div>\n\n                <div class=\"ffq-frage\"><\/div>\n                <div class=\"ffq-antworten\"><\/div>\n                <button class=\"ffq-weiter-btn\" type=\"button\">Weiter \u2192<\/button>\n\n                <div class=\"ffq-overlay ffq-start\">\n                    <h3>Bereit f\u00fcrs Quiz?<\/h3>\n                    <p>10 Fragen, direkt Feedback nach jeder Antwort. Kein Zeitdruck \u2013 einfach loslegen!<\/p>\n                    <button class=\"ffq-btn ffq-start-btn\" type=\"button\">\ud83e\uddef Los geht's<\/button>\n                <\/div>\n\n                <div class=\"ffq-overlay ffq-ende\" style=\"display:none;\">\n                    <h3>Quiz beendet! \ud83c\udf89<\/h3>\n                    <div class=\"ffq-score-gross\"><span class=\"ffq-endscore\">0<\/span>\/10<\/div>\n                    <p class=\"ffq-endtext\"><\/p>\n                    <button class=\"ffq-btn ffq-neustart-btn\" type=\"button\">Nochmal spielen<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var wrap = document.getElementById('ffq-wrap-1');\n        if (!wrap) return;\n\n        var FRAGEN_ORIGINAL = JSON.parse(wrap.dataset.fragen);\n        var fragenRunde = [];\n        var aktuelleFrage = 0;\n        var richtigAnzahl = 0;\n        var beantwortet = false;\n\n        var frageEl     = wrap.querySelector('.ffq-frage');\n        var antwortenEl = wrap.querySelector('.ffq-antworten');\n        var weiterBtn   = wrap.querySelector('.ffq-weiter-btn');\n        var nrAnzeige    = wrap.querySelector('.ffq-nr');\n        var richtigAnzeige = wrap.querySelector('.ffq-richtig-anzahl');\n        var balken       = wrap.querySelector('.ffq-fortschritt-balken');\n        var startOverlay = wrap.querySelector('.ffq-start');\n        var endeOverlay  = wrap.querySelector('.ffq-ende');\n        var endscoreEl   = wrap.querySelector('.ffq-endscore');\n        var endtextEl    = wrap.querySelector('.ffq-endtext');\n\n        function mischen(arr) {\n            var kopie = arr.slice();\n            for (var i = kopie.length - 1; i > 0; i--) {\n                var j = Math.floor(Math.random() * (i + 1));\n                var tmp = kopie[i]; kopie[i] = kopie[j]; kopie[j] = tmp;\n            }\n            return kopie;\n        }\n\n        var FRAGEN_PRO_RUNDE = 10;\n\n        function rundeVorbereiten() {\n            fragenRunde = mischen(FRAGEN_ORIGINAL).slice(0, FRAGEN_PRO_RUNDE).map(function(f) {\n                var indices = mischen([0, 1, 2, 3]);\n                var neueAntworten = indices.map(function(i) { return f.antworten[i]; });\n                var neuerRichtigIndex = indices.indexOf(f.richtig);\n                return { frage: f.frage, antworten: neueAntworten, richtig: neuerRichtigIndex };\n            });\n        }\n\n        function frageAnzeigen() {\n            beantwortet = false;\n            var f = fragenRunde[aktuelleFrage];\n            frageEl.textContent = f.frage;\n            nrAnzeige.textContent = (aktuelleFrage + 1);\n            balken.style.width = ((aktuelleFrage) \/ fragenRunde.length * 100) + '%';\n            weiterBtn.classList.remove('sichtbar');\n\n            antwortenEl.innerHTML = '';\n            f.antworten.forEach(function(text, i) {\n                var btn = document.createElement('button');\n                btn.type = 'button';\n                btn.className = 'ffq-antwort-btn';\n                btn.textContent = text;\n                btn.addEventListener('click', function() { antwortWaehlen(i, btn); });\n                antwortenEl.appendChild(btn);\n            });\n        }\n\n        function antwortWaehlen(index, btn) {\n            if (beantwortet) return;\n            beantwortet = true;\n            var f = fragenRunde[aktuelleFrage];\n\n            wrap.querySelectorAll('.ffq-antwort-btn').forEach(function(b, i) {\n                b.disabled = true;\n                if (i === f.richtig) b.classList.add('richtig');\n                else if (i === index) b.classList.add('falsch');\n            });\n\n            if (index === f.richtig) {\n                richtigAnzahl++;\n                richtigAnzeige.textContent = richtigAnzahl;\n            }\n\n            weiterBtn.classList.add('sichtbar');\n        }\n\n        weiterBtn.addEventListener('click', function() {\n            aktuelleFrage++;\n            if (aktuelleFrage >= fragenRunde.length) {\n                quizEnde();\n            } else {\n                frageAnzeigen();\n            }\n        });\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n\n        function quizEnde() {\n            balken.style.width = '100%';\n            endscoreEl.textContent = richtigAnzahl;\n            var text = '';\n            if (richtigAnzahl >= 9) text = 'Ausgezeichnet! Da k\u00f6nntest du glatt selbst Ausbilder werden. \ud83c\udfc5';\n            else if (richtigAnzahl >= 6) text = 'Gut gemacht! Ein paar Dinge k\u00f6nnt ihr noch auffrischen.';\n            else text = 'Nicht schlecht - schaut euch die Themen gerne nochmal an!';\n            endtextEl.textContent = text;\n            endeOverlay.style.display = 'flex';\n\n            var abzeichen = richtigAnzahl >= 9 ? 'gold' : (richtigAnzahl >= 6 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('quiz', abzeichen);\n        }\n\n        function quizStart() {\n            aktuelleFrage = 0;\n            richtigAnzahl = 0;\n            richtigAnzeige.textContent = '0';\n            startOverlay.style.display = 'none';\n            endeOverlay.style.display = 'none';\n            rundeVorbereiten();\n            frageAnzeigen();\n        }\n\n        wrap.querySelector('.ffq-start-btn').addEventListener('click', quizStart);\n        wrap.querySelector('.ffq-neustart-btn').addEventListener('click', quizStart);\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-schlauch\">\n            <div class=\"ffh-wrap\" id=\"ffh-wrap-1\">\n        <style>\n            .ffh-wrap { max-width: 420px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffh-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 20px; color: #fff !important; text-align: center; position: relative; overflow: hidden; }\n            .ffh-title { font-size: 22px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffh-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; }\n            .ffh-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; font-size: 14px; font-weight: 700; color: #fff !important; }\n\n            .ffh-spielfeld { position: relative; min-height: 420px !important; }\n\n            .ffh-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; max-width: 320px; margin: 0 auto; }\n            .ffh-zelle { position: relative; aspect-ratio: 1\/1; background: rgba(255,255,255,0.05); border-radius: 8px; overflow: hidden; }\n            .ffh-zelle.ffh-rohr { cursor: pointer; -webkit-tap-highlight-color: transparent; }\n            .ffh-rohr-inner { position: absolute; inset: 0; transition: transform 0.25s ease; }\n            .ffh-rohr-inner::before, .ffh-rohr-inner::after { content: ''; position: absolute; background: #4a90d9; }\n\n            \/* STRAIGHT: Basis West-Ost, ein durchgehender Balken *\/\n            .ffh-typ-gerade .ffh-rohr-inner::before { top: calc(50% - 6px); left: 0; width: 100%; height: 12px; }\n\n            \/* CORNER: Basis Nord-Ost (verbindet oben mit rechts) *\/\n            .ffh-typ-ecke .ffh-rohr-inner::before { top: 0; left: calc(50% - 6px); width: 12px; height: 50%; }\n            .ffh-typ-ecke .ffh-rohr-inner::after  { top: calc(50% - 6px); left: 50%; width: 50%; height: 12px; }\n\n            .ffh-zelle.geloest .ffh-rohr-inner::before,\n            .ffh-zelle.geloest .ffh-rohr-inner::after { background: #3fae4a; }\n\n            .ffh-icon { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 26px; }\n            .ffh-fest-stub { position: absolute; background: #4a90d9; }\n\n            .ffh-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px; border-radius: 12px; z-index: 3; color: #fff !important; overflow-y: auto; }\n            .ffh-overlay h3 { font-size: 22px; margin-bottom: 8px; color: #fff !important; }\n            .ffh-overlay p { font-size: 14px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 18px; line-height: 1.6; }\n            .ffh-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .ffh-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffh-ergebnis { font-size: 15px; margin-bottom: 18px; color: #fff !important; }\n            .ffh-ergebnis strong { color: gold !important; }\n        <\/style>\n\n        <div class=\"ffh-box\">\n            <div class=\"ffh-title\">\ud83d\udebf Schlauch-Verbindung<\/div>\n            <div class=\"ffh-untertitel\">Dreht die Leitungsteile, bis Wasser flie\u00dfen kann!<\/div>\n\n            <div class=\"ffh-hud\">\n                <span>\u23f1\ufe0f <span class=\"ffh-zeit\">0<\/span>s<\/span>\n                <span>\ud83d\udd04 Drehungen: <span class=\"ffh-drehungen\">0<\/span><\/span>\n            <\/div>\n\n            <div class=\"ffh-spielfeld\">\n                <div class=\"ffh-grid\"><\/div>\n\n                <div class=\"ffh-overlay ffh-start\">\n                    <h3>Bereit zum Verlegen?<\/h3>\n                    <p>Tippt auf ein Leitungsteil, um es um 90\u00b0 zu drehen. Verbindet den Hydrant\n                    mit der Feuerstelle zu einer durchgehenden Leitung!<\/p>\n                    <button class=\"ffh-btn ffh-start-btn\" type=\"button\">\ud83d\udebf Los geht's<\/button>\n                <\/div>\n\n                <div class=\"ffh-overlay ffh-ende\" style=\"display:none;\">\n                    <h3>Wasser marsch! \ud83d\udca6<\/h3>\n                    <div class=\"ffh-ergebnis\">\n                        Zeit: <strong><span class=\"ffh-endzeit\">0<\/span> Sekunden<\/strong><br>\n                        Drehungen: <strong><span class=\"ffh-enddrehungen\">0<\/span><\/strong>\n                    <\/div>\n                    <button class=\"ffh-btn ffh-neustart-btn\" type=\"button\">Nochmal legen<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var wrap = document.getElementById('ffh-wrap-1');\n        if (!wrap) return;\n\n        \/\/ Zuf\u00e4lliger, garantiert l\u00f6sbarer Pfad auf einem 4x4-Raster. Bei\n        \/\/ jedem Spielstart neu generiert - Hydrant und Feuer landen jedes\n        \/\/ Mal an anderer Stelle, der Verlauf dazwischen auch.\n        var RASTER_GROESSE = 4;\n\n        \/\/ Explizite Tabelle statt berechneter Rotation: f\u00fcr jeden Typ und\n        \/\/ jede der 4 Drehstellungen, welche zwei Seiten verbunden sind.\n        \/\/ (N=oben, O=rechts, S=unten, W=links)\n        var VERBINDUNGEN = {\n            gerade: { 0: ['W', 'O'], 90: ['N', 'S'], 180: ['W', 'O'], 270: ['N', 'S'] },\n            ecke:   { 0: ['N', 'O'], 90: ['O', 'S'], 180: ['S', 'W'], 270: ['W', 'N'] }\n        };\n\n        function ffhRichtungZuNachbar(von, zu) {\n            if (zu.r < von.r) return 'N';\n            if (zu.r > von.r) return 'S';\n            if (zu.c < von.c) return 'W';\n            return 'O';\n        }\n\n        \/\/ CSS-Position eines festen Anschluss-Stubs (Hydrant\/Feuer),\n        \/\/ abh\u00e4ngig davon in welche Richtung die Leitung tats\u00e4chlich weitergeht.\n        function ffhStubStyle(richtung) {\n            switch (richtung) {\n                case 'O': return 'top:calc(50% - 6px); right:0; width:50%; height:12px;';\n                case 'W': return 'top:calc(50% - 6px); left:0; width:50%; height:12px;';\n                case 'N': return 'left:calc(50% - 6px); top:0; width:12px; height:50%;';\n                case 'S': return 'left:calc(50% - 6px); bottom:0; width:12px; height:50%;';\n            }\n        }\n\n        function ffhZufallsPfad() {\n            var key = function(r, c) { return r + '-' + c; };\n            var start = { r: Math.floor(Math.random() * RASTER_GROESSE), c: Math.floor(Math.random() * RASTER_GROESSE) };\n            var pfad = [start];\n            var besucht = {}; besucht[key(start.r, start.c)] = true;\n            var zielLaenge = 6 + Math.floor(Math.random() * 4); \/\/ 6 bis 9 Felder\n\n            while (pfad.length < zielLaenge) {\n                var aktuelles = pfad[pfad.length - 1];\n                var kandidaten = [\n                    { r: aktuelles.r - 1, c: aktuelles.c },\n                    { r: aktuelles.r + 1, c: aktuelles.c },\n                    { r: aktuelles.r, c: aktuelles.c - 1 },\n                    { r: aktuelles.r, c: aktuelles.c + 1 }\n                ].filter(function(n) {\n                    return n.r >= 0 && n.r < RASTER_GROESSE && n.c >= 0 && n.c < RASTER_GROESSE && !besucht[key(n.r, n.c)];\n                });\n                if (!kandidaten.length) break; \/\/ Sackgasse - Pfad endet hier\n                var naechstes = kandidaten[Math.floor(Math.random() * kandidaten.length)];\n                pfad.push(naechstes);\n                besucht[key(naechstes.r, naechstes.c)] = true;\n            }\n\n            if (pfad.length < 4) return ffhZufallsPfad(); \/\/ zu kurz geraten, nochmal versuchen\n            return pfad;\n        }\n\n        \/\/ Nur noch den TYP bestimmen (gerade\/ecke) - keine Soll-Drehung mehr\n        \/\/ vorausberechnen. Die Pr\u00fcfung erfolgt sp\u00e4ter live.\n        function ffhPfadZuTeilen(zellenPfad) {\n            return zellenPfad.map(function(zelle, i) {\n                if (i === 0) return { r: zelle.r, c: zelle.c, typ: 'hydrant' };\n                if (i === zellenPfad.length - 1) return { r: zelle.r, c: zelle.c, typ: 'feuer' };\n\n                var richtungA = ffhRichtungZuNachbar(zelle, zellenPfad[i - 1]);\n                var richtungB = ffhRichtungZuNachbar(zelle, zellenPfad[i + 1]);\n                var gegensatz = { N: 'S', S: 'N', O: 'W', W: 'O' };\n                var typ = (gegensatz[richtungA] === richtungB) ? 'gerade' : 'ecke';\n\n                return { r: zelle.r, c: zelle.c, typ: typ };\n            });\n        }\n\n        var grid = wrap.querySelector('.ffh-grid');\n        var zeitAnzeige = wrap.querySelector('.ffh-zeit');\n        var drehAnzeige  = wrap.querySelector('.ffh-drehungen');\n        var startOverlay = wrap.querySelector('.ffh-start');\n        var endeOverlay  = wrap.querySelector('.ffh-ende');\n        var endzeitAnzeige = wrap.querySelector('.ffh-endzeit');\n        var enddrehAnzeige  = wrap.querySelector('.ffh-enddrehungen');\n\n        var zellenState = {};\n        var PFAD = [];\n        var drehungen = 0;\n        var laeuft = false;\n        var startZeit = null;\n        var zeitTimer = null;\n\n        function ffhAufbauen() {\n            PFAD = ffhPfadZuTeilen(ffhZufallsPfad());\n\n            grid.innerHTML = '';\n            zellenState = {};\n\n            for (var r = 0; r < RASTER_GROESSE; r++) {\n                for (var c = 0; c < RASTER_GROESSE; c++) {\n                    var zelle = document.createElement('div');\n                    zelle.className = 'ffh-zelle';\n                    grid.appendChild(zelle);\n                    zellenState['pos-' + r + '-' + c] = zelle;\n                }\n            }\n\n            PFAD.forEach(function(teil, i) {\n                var key = 'pos-' + teil.r + '-' + teil.c;\n                var zelle = zellenState[key];\n\n                if (teil.typ === 'hydrant') {\n                    var richtungHydrant = ffhRichtungZuNachbar(teil, PFAD[i + 1]);\n                    zelle.innerHTML = '<div class=\"ffh-icon\">\ud83d\udeb0<\/div><div class=\"ffh-fest-stub\" style=\"' + ffhStubStyle(richtungHydrant) + '\"><\/div>';\n                    return;\n                }\n                if (teil.typ === 'feuer') {\n                    var richtungFeuer = ffhRichtungZuNachbar(teil, PFAD[i - 1]);\n                    zelle.innerHTML = '<div class=\"ffh-icon\">\ud83d\udd25<\/div><div class=\"ffh-fest-stub\" style=\"' + ffhStubStyle(richtungFeuer) + '\"><\/div>';\n                    return;\n                }\n\n                var zufallsWinkel = [0, 90, 180, 270][Math.floor(Math.random() * 4)];\n                zelle.className = 'ffh-zelle ffh-rohr ffh-typ-' + teil.typ;\n                zelle.innerHTML = '<div class=\"ffh-rohr-inner\" style=\"transform:rotate(' + zufallsWinkel + 'deg)\"><\/div>';\n\n                var state = { aktuell: zufallsWinkel, typ: teil.typ, el: zelle };\n                zellenState[key] = state;\n\n                zelle.addEventListener('click', function() { ffhDrehen(state); });\n            });\n        }\n\n        function ffhDrehen(state) {\n            if (!laeuft) return;\n            state.aktuell = (state.aktuell + 90) % 360;\n            state.el.querySelector('.ffh-rohr-inner').style.transform = 'rotate(' + state.aktuell + 'deg)';\n            drehungen++;\n            drehAnzeige.textContent = drehungen;\n            ffhPruefen();\n        }\n\n        \/\/ Live-Pr\u00fcfung: l\u00e4uft den kompletten Pfad Schritt f\u00fcr Schritt ab und\n        \/\/ pr\u00fcft bei JEDEM \u00dcbergang, ob die aktuell (gerade jetzt) angezeigten\n        \/\/ Rohr-Drehungen tats\u00e4chlich zueinander passen. Kein Vergleich mit\n        \/\/ einer vorab berechneten \"Soll-Drehung\" mehr n\u00f6tig.\n        function ffhPruefen() {\n            for (var i = 0; i < PFAD.length - 1; i++) {\n                var a = PFAD[i];\n                var b = PFAD[i + 1];\n                var richtungAB = ffhRichtungZuNachbar(a, b);\n                var richtungBA = ffhRichtungZuNachbar(b, a);\n\n                if (a.typ !== 'hydrant') {\n                    var stateA = zellenState['pos-' + a.r + '-' + a.c];\n                    var verbindungenA = VERBINDUNGEN[stateA.typ][stateA.aktuell];\n                    if (verbindungenA.indexOf(richtungAB) === -1) return;\n                }\n                if (b.typ !== 'feuer') {\n                    var stateB = zellenState['pos-' + b.r + '-' + b.c];\n                    var verbindungenB = VERBINDUNGEN[stateB.typ][stateB.aktuell];\n                    if (verbindungenB.indexOf(richtungBA) === -1) return;\n                }\n            }\n            ffhSpielEnde();\n        }\n\n        function ffhSpielStart() {\n            laeuft = true;\n            drehungen = 0;\n            drehAnzeige.textContent = '0';\n            zeitAnzeige.textContent = '0';\n            startOverlay.style.display = 'none';\n            endeOverlay.style.display = 'none';\n            ffhAufbauen();\n\n            startZeit = Date.now();\n            clearInterval(zeitTimer);\n            zeitTimer = setInterval(function() {\n                zeitAnzeige.textContent = Math.floor((Date.now() - startZeit) \/ 1000);\n            }, 1000);\n        }\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n\n        function ffhSpielEnde() {\n            laeuft = false;\n            clearInterval(zeitTimer);\n            wrap.querySelectorAll('.ffh-rohr').forEach(function(z) { z.classList.add('geloest'); });\n            var sekunden = Math.floor((Date.now() - startZeit) \/ 1000);\n            endzeitAnzeige.textContent = sekunden;\n            enddrehAnzeige.textContent = drehungen;\n            setTimeout(function() { endeOverlay.style.display = 'flex'; }, 500);\n\n            var faktor = drehungen \/ PFAD.length;\n            var abzeichen = faktor <= 1.5 ? 'gold' : (faktor <= 3 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('schlauch', abzeichen);\n        }\n\n        wrap.querySelector('.ffh-start-btn').addEventListener('click', ffhSpielStart);\n        wrap.querySelector('.ffh-neustart-btn').addEventListener('click', ffhSpielStart);\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-fahrsimulator\">\n            <div class=\"fff-wrap\" id=\"fff-wrap-1\">\n        <style>\n            .fff-wrap { max-width: 380px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .fff-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 20px; color: #fff !important; text-align: center; position: relative; overflow: hidden; }\n            .fff-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .fff-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 10px; }\n\n            .fff-rang-btn { background: none; border: 1px solid gold; color: gold !important; padding: 6px 16px; border-radius: 20px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; margin-bottom: 4px; }\n            .fff-rang-btn:hover { background: gold; color: #1C2B4B !important; }\n            .fff-mini-rang { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,215,0,0.3); border-radius: 8px; padding: 10px 14px; margin-bottom: 14px; text-align: left; }\n            .fff-mini-rang-titel { font-size: 12px; font-weight: 700; color: gold !important; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 6px; text-align: center; }\n            .fff-mini-rang-zeile { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; color: #fff !important; }\n            .fff-mini-rang-platz { width: 18px; font-weight: 700; color: gold !important; text-align: right; }\n            .fff-mini-rang-name { flex: 1; }\n            .fff-mini-rang-score { font-weight: 700; }\n            .fff-mini-rang-leer { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; text-align: center; }\n\n            .fff-tab-reihe { display: flex; gap: 6px; margin-bottom: 10px; justify-content: center; flex-wrap: wrap; }\n            .fff-tab-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: var(--ff-text-muted, #a0b0c8) !important; padding: 5px 10px; border-radius: 20px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit; }\n            .fff-tab-btn.aktiv { background: gold; border-color: gold; color: #1C2B4B !important; }\n\n            .fff-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; font-size: 13px; font-weight: 700; color: #fff !important; }\n\n            .fff-spielfeld { position: relative; min-height: 480px !important; touch-action: manipulation; }\n            .fff-strasse { position: relative; height: 380px; background: repeating-linear-gradient(0deg, #3a4a68, #3a4a68 20px, #33415c 20px, #33415c 40px); border-radius: 10px; overflow: hidden; display: flex; }\n            .fff-spur { flex: 1; position: relative; border-left: 2px dashed rgba(255,255,255,0.15); }\n            .fff-spur:first-child { border-left: none; }\n\n            .fff-hindernis { position: absolute; left: 50%; transform: translateX(-50%); font-size: 30px; top: -40px; }\n            .fff-fahrzeug { position: absolute; left: 50%; transform: translateX(-50%); bottom: 10px; font-size: 34px; transition: left 0.15s; z-index: 2; }\n\n            .fff-steuerung { display: flex; justify-content: center; gap: 20px; margin-top: 14px; position: relative; z-index: 20; }\n            .fff-steuer-btn { background: rgba(255,255,255,0.08); border: 2px solid rgba(255,255,255,0.2); color: #fff !important; width: 60px; height: 50px; border-radius: 8px; font-size: 22px; cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }\n            .fff-steuer-btn:active { background: var(--ff-red, #CC0000); }\n\n            .fff-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px; border-radius: 12px; z-index: 3; color: #fff !important; overflow-y: auto; }\n            .fff-overlay h3 { font-size: 20px; margin-bottom: 8px; color: #fff !important; }\n            .fff-overlay p { font-size: 14px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; line-height: 1.6; }\n            .fff-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .fff-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .fff-btn:disabled { opacity: 0.5; cursor: default; }\n            .fff-ergebnis { font-size: 15px; margin-bottom: 14px; color: #fff !important; }\n            .fff-ergebnis strong { color: gold !important; }\n\n            .fff-alter-buttons { display: flex; flex-direction: column; gap: 8px; width: 100%; margin-bottom: 4px; }\n            .fff-alter-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: #fff !important; padding: 10px 16px; border-radius: 8px; font-size: 14px; font-weight: 700; cursor: pointer; font-family: inherit; text-align: left; display: flex; align-items: center; justify-content: space-between; }\n            .fff-alter-btn:hover { border-color: var(--ff-red, #CC0000); background: rgba(204,0,0,0.15); }\n            .fff-alter-btn span.fff-alter-sub { font-size: 12px; font-weight: 400; color: var(--ff-text-muted, #a0b0c8) !important; }\n\n            .fff-eintrag-wrap { width: 100%; margin-bottom: 14px; }\n            .fff-name-input { width: 100%; box-sizing: border-box; padding: 10px 14px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.25) !important; background: rgba(255,255,255,0.08) !important; color: #fff !important; font-size: 14px; font-family: inherit; margin-bottom: 10px; text-align: center; }\n            .fff-name-input::placeholder { color: var(--ff-text-muted, #a0b0c8) !important; }\n            .fff-btn-klein { padding: 8px 22px; font-size: 13px; }\n            .fff-eintrag-status { font-size: 12px; color: gold !important; margin-top: 8px; min-height: 16px; }\n\n            .fff-rang-liste { width: 100%; max-height: 300px; overflow-y: auto; margin-bottom: 16px; }\n            .fff-rang-zeile { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 6px; font-size: 14px; color: #fff !important; }\n            .fff-rang-zeile:nth-child(odd) { background: rgba(255,255,255,0.05); }\n            .fff-rang-platz { width: 24px; font-weight: 700; color: gold !important; text-align: right; }\n            .fff-rang-name { flex: 1; text-align: left; color: #fff !important; }\n            .fff-rang-score { font-weight: 700; color: #fff !important; }\n            .fff-rang-leer { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; }\n        <\/style>\n\n        <div class=\"fff-box\">\n            <div class=\"fff-title\">\ud83d\ude92 Einsatzfahrt-Simulator<\/div>\n            <div class=\"fff-untertitel\">Weicht so lange wie m\u00f6glich den Hindernissen aus!<\/div>\n\n            <div class=\"fff-mini-rang\">\n                <div class=\"fff-mini-rang-titel\">\ud83c\udfc6 Bestenliste (ausgewichen)<\/div>\n                <div class=\"fff-tab-reihe fff-mini-tabs\">\n                    <button class=\"fff-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76<\/button>\n                    <button class=\"fff-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2<\/button>\n                    <button class=\"fff-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92<\/button>\n                <\/div>\n                <div class=\"fff-mini-rang-inhalt\">L\u00e4dt \u2026<\/div>\n            <\/div>\n            <button class=\"fff-rang-btn fff-rang-oeffnen-btn\" type=\"button\">Komplette Rangliste<\/button>\n\n            <div class=\"fff-hud\">\n                <span>\u26a0\ufe0f Ausgewichen: <span class=\"fff-ausgewichen\">0<\/span><\/span>\n                <span>\ud83d\udca7 Bonus: <span class=\"fff-bonus\">0<\/span><\/span>\n            <\/div>\n\n            <div class=\"fff-spielfeld\">\n                <div class=\"fff-strasse\">\n                    <div class=\"fff-spur\" data-spur=\"0\"><\/div>\n                    <div class=\"fff-spur\" data-spur=\"1\"><\/div>\n                    <div class=\"fff-spur\" data-spur=\"2\"><\/div>\n                    <div class=\"fff-fahrzeug\">\ud83d\ude92<\/div>\n                <\/div>\n\n                <div class=\"fff-steuerung\">\n                    <button class=\"fff-steuer-btn fff-links-btn\" type=\"button\">\u2b05\ufe0f<\/button>\n                    <button class=\"fff-steuer-btn fff-rechts-btn\" type=\"button\">\u27a1\ufe0f<\/button>\n                <\/div>\n\n                <div class=\"fff-overlay fff-start\">\n                    <h3>Bereit zur Ausfahrt?<\/h3>\n                    <p>Mit den Pfeilen die Spur wechseln, Hindernissen ausweichen, Wassertropfen\n                    \ud83d\udca7 einsammeln. Die Fahrt wird stetig schneller - wie weit kommt ihr?<\/p>\n                    <div class=\"fff-alter-buttons\">\n                        <button class=\"fff-alter-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerg <span class=\"fff-alter-sub\">gem\u00fctliches Tempo<\/span><\/button>\n                        <button class=\"fff-alter-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend <span class=\"fff-alter-sub\">mittleres Tempo<\/span><\/button>\n                        <button class=\"fff-alter-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene <span class=\"fff-alter-sub\">volles Tempo<\/span><\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"fff-overlay fff-ende\" style=\"display:none;\">\n                    <h3 class=\"fff-endtitel\">\ud83d\udca5 Zusammensto\u00df!<\/h3>\n                    <div class=\"fff-ergebnis\">\n                        Ausgewichen: <strong><span class=\"fff-endausgewichen\">0<\/span><\/strong><br>\n                        Bonus gesammelt: <strong><span class=\"fff-endbonus\">0<\/span><\/strong>\n                    <\/div>\n                    <div class=\"fff-eintrag-wrap\">\n                        <input type=\"text\" class=\"fff-name-input\" maxlength=\"20\" placeholder=\"Dein Name f\u00fcr die Rangliste\">\n                        <button class=\"fff-btn fff-btn-klein fff-eintrag-btn\" type=\"button\">In Rangliste eintragen<\/button>\n                        <div class=\"fff-eintrag-status\"><\/div>\n                    <\/div>\n                    <button class=\"fff-btn fff-neustart-btn\" type=\"button\">Nochmal w\u00e4hlen<\/button>\n                <\/div>\n\n                <div class=\"fff-overlay fff-rangliste-overlay\" style=\"display:none;\">\n                    <h3>\ud83c\udfc6 Rangliste<\/h3>\n                    <div class=\"fff-tab-reihe fff-voll-tabs\">\n                        <button class=\"fff-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerge<\/button>\n                        <button class=\"fff-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend<\/button>\n                        <button class=\"fff-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene<\/button>\n                    <\/div>\n                    <div class=\"fff-rang-liste fff-rang-liste-inhalt\">L\u00e4dt \u2026<\/div>\n                    <button class=\"fff-btn fff-rang-schliessen-btn\" type=\"button\">Schlie\u00dfen<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var wrap = document.getElementById('fff-wrap-1');\n        if (!wrap) return;\n\n        var NONCE   = 'f9a741e5a2';\n        var AJAXURL = 'https:\/\/ff-willmatshofen.de\/wp-admin\/admin-ajax.php';\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n\n        function ffsSpielerId() {\n            var id = null;\n            try { id = localStorage.getItem('ffs_player_id'); } catch (e) {}\n            if (!id) {\n                id = (window.crypto && crypto.randomUUID) ? crypto.randomUUID() : ('id-' + Date.now() + '-' + Math.random().toString(16).slice(2));\n                try { localStorage.setItem('ffs_player_id', id); } catch (e) {}\n            }\n            return id;\n        }\n\n        \/\/ Schwierigkeit je Altersstufe: Start-Spawnabstand (ms), wie schnell\n        \/\/ er sich verk\u00fcrzt, Mindestabstand, sowie Start-\/Maxgeschwindigkeit.\n        var SCHWIERIGKEIT = {\n            loeschzwerg: { spawnStart: 1700, spawnStep: 6,  spawnMin: 950, tempoStart: 1.5, tempoMax: 2.8, tempoStep: 0.02 },\n            jugend:      { spawnStart: 1300, spawnStep: 10, spawnMin: 700, tempoStart: 1.9, tempoMax: 3.8, tempoStep: 0.035 },\n            erwachsene:  { spawnStart: 1000, spawnStep: 15, spawnMin: 500, tempoStart: 2.2, tempoMax: 5.0, tempoStep: 0.05 }\n        };\n\n        var strasse   = wrap.querySelector('.fff-strasse');\n        var fahrzeug  = wrap.querySelector('.fff-fahrzeug');\n        var ausgewichenAnzeige = wrap.querySelector('.fff-ausgewichen');\n        var bonusAnzeige = wrap.querySelector('.fff-bonus');\n        var startOverlay = wrap.querySelector('.fff-start');\n        var endeOverlay  = wrap.querySelector('.fff-ende');\n        var ranglisteOverlay = wrap.querySelector('.fff-rangliste-overlay');\n        var miniRangInhalt = wrap.querySelector('.fff-mini-rang-inhalt');\n        var vollRangInhalt = wrap.querySelector('.fff-rang-liste-inhalt');\n        var nameInput = wrap.querySelector('.fff-name-input');\n        var eintragBtn = wrap.querySelector('.fff-eintrag-btn');\n        var eintragStatus = wrap.querySelector('.fff-eintrag-status');\n\n        var HINDERNIS_ICONS = ['\ud83d\ude97', '\ud83d\udea7', '\ud83d\uded1', '\ud83d\ude8c'];\n        var BONUS_CHANCE = 0.15;\n\n        var aktuelleAltersstufe = 'erwachsene';\n        var spur = 1;\n        var laeuft = false;\n        var ausgewichen = 0;\n        var bonusPunkte = 0;\n        var hindernisse = [];\n        var spawnTimer = null;\n        var loopTimer = null;\n        var geschwindigkeit = 2.2;\n        var spawnAbstand = 1000;\n\n        function fffFahrzeugPositionieren() {\n            fahrzeug.style.left = (spur * 33.333 + 16.666) + '%';\n        }\n        function fffSpurWechseln(richtung) {\n            if (!laeuft) return;\n            spur = Math.max(0, Math.min(2, spur + richtung));\n            fffFahrzeugPositionieren();\n        }\n\n        function fffHindernisErzeugen() {\n            if (!laeuft) return;\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n            var zielSpur = Math.floor(Math.random() * 3);\n            var istBonus = Math.random() < BONUS_CHANCE;\n\n            var el = document.createElement('div');\n            el.className = 'fff-hindernis';\n            el.textContent = istBonus ? '\ud83d\udca7' : HINDERNIS_ICONS[Math.floor(Math.random() * HINDERNIS_ICONS.length)];\n            el.style.left = (zielSpur * 33.333 + 16.666) + '%';\n            el.dataset.spur = zielSpur;\n            el.dataset.top = '-40';\n            if (istBonus) el.dataset.bonus = '1';\n            strasse.appendChild(el);\n            hindernisse.push(el);\n\n            spawnAbstand = Math.max(c.spawnMin, spawnAbstand - c.spawnStep);\n            spawnTimer = setTimeout(fffHindernisErzeugen, spawnAbstand);\n        }\n\n        function fffLoop() {\n            if (!laeuft) return;\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n\n            hindernisse.forEach(function(el) {\n                var top = parseFloat(el.dataset.top) + geschwindigkeit * 4;\n                el.dataset.top = top;\n                el.style.top = top + 'px';\n\n                if (top > 300 && top < 350 && parseInt(el.dataset.spur) === spur && !el.dataset.ausgewertet) {\n                    el.dataset.ausgewertet = '1';\n                    if (el.dataset.bonus === '1') {\n                        bonusPunkte++;\n                        bonusAnzeige.textContent = bonusPunkte;\n                        el.remove();\n                    } else {\n                        fffCrash();\n                    }\n                    return;\n                }\n\n                if (top > 380 && !el.dataset.ausgewertet) {\n                    el.dataset.ausgewertet = '1';\n                    if (el.dataset.bonus !== '1') {\n                        ausgewichen++;\n                        ausgewichenAnzeige.textContent = ausgewichen;\n                    }\n                }\n            });\n\n            hindernisse = hindernisse.filter(function(el) {\n                if (parseFloat(el.dataset.top) > 400) { el.remove(); return false; }\n                return true;\n            });\n\n            geschwindigkeit = Math.min(c.tempoMax, geschwindigkeit + c.tempoStep * 0.1);\n        }\n\n        function fffCrash() {\n            laeuft = false;\n            clearTimeout(spawnTimer);\n            clearInterval(loopTimer);\n            wrap.querySelector('.fff-endtitel').textContent = '\ud83d\udca5 Zusammensto\u00df!';\n            wrap.querySelector('.fff-endausgewichen').textContent = ausgewichen;\n            wrap.querySelector('.fff-endbonus').textContent = bonusPunkte;\n\n            nameInput.value = '';\n            eintragBtn.disabled = false;\n            eintragStatus.textContent = '';\n            endeOverlay.style.display = 'flex';\n\n            var score = ausgewichen + bonusPunkte * 3;\n            var abzeichen = score >= 40 ? 'gold' : (score >= 15 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('fahrsimulator', abzeichen);\n        }\n\n        function fffSpielStart(altersstufe) {\n            aktuelleAltersstufe = altersstufe;\n            try { localStorage.setItem('fff_last_bracket', altersstufe); } catch (e) {}\n\n            var c = SCHWIERIGKEIT[altersstufe];\n            laeuft = true;\n            spur = 1;\n            ausgewichen = 0;\n            bonusPunkte = 0;\n            geschwindigkeit = c.tempoStart;\n            spawnAbstand = c.spawnStart;\n\n            ausgewichenAnzeige.textContent = '0';\n            bonusAnzeige.textContent = '0';\n            hindernisse.forEach(function(el) { el.remove(); });\n            hindernisse = [];\n            fffFahrzeugPositionieren();\n\n            startOverlay.style.display = 'none';\n            endeOverlay.style.display = 'none';\n            ranglisteOverlay.style.display = 'none';\n\n            clearTimeout(spawnTimer);\n            clearInterval(loopTimer);\n            spawnTimer = setTimeout(fffHindernisErzeugen, 800);\n            loopTimer = setInterval(fffLoop, 40);\n        }\n\n        wrap.querySelector('.fff-links-btn').addEventListener('click', function() { fffSpurWechseln(-1); });\n        wrap.querySelector('.fff-rechts-btn').addEventListener('click', function() { fffSpurWechseln(1); });\n        wrap.querySelectorAll('.fff-alter-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { fffSpielStart(btn.dataset.stufe); });\n        });\n        wrap.querySelector('.fff-neustart-btn').addEventListener('click', function() {\n            endeOverlay.style.display = 'none';\n            startOverlay.style.display = 'flex';\n        });\n\n        document.addEventListener('keydown', function(e) {\n            if (!laeuft) return;\n            if (e.key === 'ArrowLeft') fffSpurWechseln(-1);\n            if (e.key === 'ArrowRight') fffSpurWechseln(1);\n        });\n\n        fffFahrzeugPositionieren();\n\n        \/\/ ---------- Rangliste ----------\n        function fffRangZeilenHtml(liste, prefix) {\n            var html = '';\n            liste.forEach(function(eintrag, i) {\n                html += '<div class=\"' + prefix + '-zeile\">' +\n                    '<span class=\"' + prefix + '-platz\">' + (i + 1) + '.<\/span>' +\n                    '<span class=\"' + prefix + '-name\">' + fffEscapeHtml(eintrag.name) + '<\/span>' +\n                    '<span class=\"' + prefix + '-score\">' + eintrag.score + '<\/span>' +\n                '<\/div>';\n            });\n            return html;\n        }\n        function fffEscapeHtml(str) {\n            var div = document.createElement('div');\n            div.textContent = str;\n            return div.innerHTML;\n        }\n        function fffRanglisteHolen(altersstufe, callback) {\n            var formData = new FormData();\n            formData.append('action', 'ff_fahrsim_rangliste_holen');\n            formData.append('nonce', NONCE);\n            formData.append('altersstufe', altersstufe);\n            fetch(AJAXURL, { method: 'POST', body: formData })\n                .then(function(r) { return r.json(); })\n                .then(function(data) { callback((data.success && data.data) ? data.data : []); })\n                .catch(function() { callback(null); });\n        }\n        function fffLetzteAltersstufe() {\n            var stufe = null;\n            try { stufe = localStorage.getItem('fff_last_bracket'); } catch (e) {}\n            return (stufe === 'loeschzwerg' || stufe === 'jugend' || stufe === 'erwachsene') ? stufe : 'erwachsene';\n        }\n        function fffTabsAktualisieren(selector, aktiveStufe) {\n            wrap.querySelectorAll(selector + ' .fff-tab-btn').forEach(function(btn) {\n                btn.classList.toggle('aktiv', btn.dataset.stufe === aktiveStufe);\n            });\n        }\n\n        var fffMiniStufe = fffLetzteAltersstufe();\n        function fffMiniRanglisteLaden() {\n            fffTabsAktualisieren('.fff-mini-tabs', fffMiniStufe);\n            miniRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            fffRanglisteHolen(fffMiniStufe, function(liste) {\n                if (liste === null) { miniRangInhalt.innerHTML = '<div class=\"fff-mini-rang-leer\">Rangliste konnte nicht geladen werden.<\/div>'; return; }\n                if (!liste.length) { miniRangInhalt.innerHTML = '<div class=\"fff-mini-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/div>'; return; }\n                miniRangInhalt.innerHTML = fffRangZeilenHtml(liste.slice(0, 5), 'fff-mini-rang');\n            });\n        }\n        wrap.querySelectorAll('.fff-mini-tabs .fff-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { fffMiniStufe = btn.dataset.stufe; fffMiniRanglisteLaden(); });\n        });\n        fffMiniRanglisteLaden();\n\n        var fffVollStufe = fffLetzteAltersstufe();\n        function fffVollRanglisteLaden() {\n            fffTabsAktualisieren('.fff-voll-tabs', fffVollStufe);\n            vollRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            fffRanglisteHolen(fffVollStufe, function(liste) {\n                if (liste === null) { vollRangInhalt.innerHTML = '<p class=\"fff-rang-leer\">Rangliste konnte nicht geladen werden.<\/p>'; return; }\n                if (!liste.length) { vollRangInhalt.innerHTML = '<p class=\"fff-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/p>'; return; }\n                vollRangInhalt.innerHTML = fffRangZeilenHtml(liste, 'fff-rang');\n            });\n        }\n        wrap.querySelectorAll('.fff-voll-tabs .fff-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { fffVollStufe = btn.dataset.stufe; fffVollRanglisteLaden(); });\n        });\n        wrap.querySelector('.fff-rang-oeffnen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'flex';\n            fffVollRanglisteLaden();\n        });\n        wrap.querySelector('.fff-rang-schliessen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'none';\n        });\n\n        eintragBtn.addEventListener('click', function() {\n            var name = nameInput.value.trim();\n            if (!name) { eintragStatus.textContent = 'Bitte einen Namen eingeben.'; return; }\n\n            eintragBtn.disabled = true;\n            eintragStatus.textContent = 'Wird gespeichert \u2026';\n\n            var score = ausgewichen + bonusPunkte * 3;\n            var formData = new FormData();\n            formData.append('action', 'ff_fahrsim_score_speichern');\n            formData.append('nonce', NONCE);\n            formData.append('name', name);\n            formData.append('score', score);\n            formData.append('spieler_id', ffsSpielerId());\n            formData.append('altersstufe', aktuelleAltersstufe);\n\n            fetch(AJAXURL, { method: 'POST', body: formData })\n                .then(function(r) { return r.json(); })\n                .then(function(data) {\n                    if (data.success) {\n                        if (data.data && data.data.verbessert === false) {\n                            eintragStatus.textContent = 'Dein bisheriger Eintrag war schon besser oder gleich gut \u2013 bleibt unver\u00e4ndert.';\n                        } else {\n                            eintragStatus.textContent = '\u2705 In der Rangliste eingetragen!';\n                        }\n                        fffMiniStufe = aktuelleAltersstufe;\n                        fffMiniRanglisteLaden();\n                    } else if (data.data && data.data.grund === 'name_vergeben') {\n                        eintragStatus.textContent = '\u26a0\ufe0f Dieser Name ist schon vergeben \u2013 bitte einen anderen w\u00e4hlen.';\n                        eintragBtn.disabled = false;\n                    } else {\n                        eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                        eintragBtn.disabled = false;\n                    }\n                })\n                .catch(function() {\n                    eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                    eintragBtn.disabled = false;\n                });\n        });\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-strahlrohr\">\n            <div class=\"ffr-wrap\" id=\"ffr-wrap-1\">\n        <style>\n            .ffr-wrap { max-width: 400px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffr-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 20px; color: #fff !important; text-align: center; position: relative; overflow: hidden; }\n            .ffr-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffr-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 10px; }\n\n            .ffr-rang-btn { background: none; border: 1px solid gold; color: gold !important; padding: 6px 16px; border-radius: 20px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; margin-bottom: 4px; }\n            .ffr-rang-btn:hover { background: gold; color: #1C2B4B !important; }\n            .ffr-mini-rang { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,215,0,0.3); border-radius: 8px; padding: 10px 14px; margin-bottom: 14px; text-align: left; }\n            .ffr-mini-rang-titel { font-size: 12px; font-weight: 700; color: gold !important; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 6px; text-align: center; }\n            .ffr-mini-rang-zeile { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; color: #fff !important; }\n            .ffr-mini-rang-platz { width: 18px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffr-mini-rang-name { flex: 1; }\n            .ffr-mini-rang-score { font-weight: 700; }\n            .ffr-mini-rang-leer { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; text-align: center; }\n\n            .ffr-tab-reihe { display: flex; gap: 6px; margin-bottom: 10px; justify-content: center; flex-wrap: wrap; }\n            .ffr-tab-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: var(--ff-text-muted, #a0b0c8) !important; padding: 5px 10px; border-radius: 20px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit; }\n            .ffr-tab-btn.aktiv { background: gold; border-color: gold; color: #1C2B4B !important; }\n\n            .ffr-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-size: 13px; font-weight: 700; color: #fff !important; }\n\n            .ffr-tank-wrap { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }\n            .ffr-tank-label { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; white-space: nowrap; }\n            .ffr-tank-balken-wrap { flex: 1; height: 8px; background: rgba(255,255,255,0.12); border-radius: 4px; overflow: hidden; }\n            .ffr-tank-balken { height: 100%; background: #4a90d9; border-radius: 4px; transition: width 0.15s linear, background 0.3s; }\n            .ffr-tank-balken.leer { background: var(--ff-red, #CC0000); }\n\n            .ffr-spielfeld { position: relative; min-height: 460px !important; touch-action: manipulation; }\n            .ffr-feld { position: relative; height: 220px; background: linear-gradient(180deg, #0f1e38, #1a2c4a); border-radius: 10px; overflow: hidden; margin-bottom: 10px; touch-action: none; cursor: grab; }\n            .ffr-feld:active { cursor: grabbing; }\n            .ffr-ziel { position: absolute; top: 20px; font-size: 34px; transform: translateX(-50%); transition: filter 0.15s, font-size 0.1s linear; }\n            .ffr-ziel.getroffen { filter: brightness(2) drop-shadow(0 0 10px gold); }\n            .ffr-ziel.geloescht { animation: ffr-verpuffen 0.45s ease forwards; }\n            @keyframes ffr-verpuffen { 0% { opacity: 1; transform: translateX(-50%) scale(1); } 100% { opacity: 0; transform: translateX(-50%) scale(1.8) translateY(-20px); } }\n\n            .ffr-strahl {\n                position: absolute; bottom: 0; width: 8px;\n                background: repeating-linear-gradient(180deg, rgba(120,190,255,0.95) 0px, rgba(180,220,255,0.7) 8px, rgba(80,160,240,0.9) 16px);\n                background-size: 100% 32px;\n                border-radius: 4px 4px 0 0; transform-origin: bottom center; display: none;\n                animation: ffr-fliessen 0.35s linear infinite, ffr-pulsieren 0.6s ease-in-out infinite;\n            }\n            .ffr-strahl.aktiv { display: block; }\n            @keyframes ffr-fliessen { from { background-position-y: 0; } to { background-position-y: 32px; } }\n            @keyframes ffr-pulsieren { 0%, 100% { transform: translateX(-50%) scaleX(1); } 50% { transform: translateX(-50%) scaleX(1.15); } }\n            .ffr-duese { position: absolute; bottom: 0; font-size: 30px; transform: translateX(-50%); }\n\n            .ffr-hydrant { position: absolute; bottom: 0; left: 3%; font-size: 26px; transform: translateX(-50%); opacity: 0.8; }\n            .ffr-wind-hinweis { position: absolute; top: 4px; left: 50%; transform: translateX(-50%); font-size: 12px; font-weight: 700; color: #fff !important; background: rgba(204,0,0,0.85); padding: 3px 10px; border-radius: 12px; opacity: 0; transition: opacity 0.3s; white-space: nowrap; }\n            .ffr-wind-hinweis.aktiv { opacity: 1; animation: ffr-wind-schweben 0.8s ease-in-out infinite alternate; }\n            @keyframes ffr-wind-schweben { from { margin-top: 0; } to { margin-top: 4px; } }\n\n            .ffr-kombo-anzeige { text-align: center; font-size: 13px; font-weight: 700; color: gold !important; min-height: 18px; margin-bottom: 6px; opacity: 0; transition: opacity 0.2s; }\n            .ffr-kombo-anzeige.sichtbar { opacity: 1; }\n\n            .ffr-zieh-hinweis { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 8px; }\n\n            .ffr-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px; border-radius: 12px; z-index: 30; color: #fff !important; overflow-y: auto; }\n            .ffr-overlay h3 { font-size: 20px; margin-bottom: 8px; color: #fff !important; }\n            .ffr-overlay p { font-size: 14px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; line-height: 1.6; }\n            .ffr-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .ffr-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffr-btn:disabled { opacity: 0.5; cursor: default; }\n            .ffr-ergebnis { font-size: 15px; margin-bottom: 14px; color: #fff !important; }\n            .ffr-ergebnis strong { color: gold !important; }\n\n            .ffr-alter-buttons { display: flex; flex-direction: column; gap: 8px; width: 100%; margin-bottom: 4px; }\n            .ffr-alter-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: #fff !important; padding: 10px 16px; border-radius: 8px; font-size: 14px; font-weight: 700; cursor: pointer; font-family: inherit; text-align: left; display: flex; align-items: center; justify-content: space-between; }\n            .ffr-alter-btn:hover { border-color: var(--ff-red, #CC0000); background: rgba(204,0,0,0.15); }\n            .ffr-alter-btn span.ffr-alter-sub { font-size: 12px; font-weight: 400; color: var(--ff-text-muted, #a0b0c8) !important; }\n\n            .ffr-eintrag-wrap { width: 100%; margin-bottom: 14px; }\n            .ffr-name-input { width: 100%; box-sizing: border-box; padding: 10px 14px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.25) !important; background: rgba(255,255,255,0.08) !important; color: #fff !important; font-size: 14px; font-family: inherit; margin-bottom: 10px; text-align: center; }\n            .ffr-name-input::placeholder { color: var(--ff-text-muted, #a0b0c8) !important; }\n            .ffr-btn-klein { padding: 8px 22px; font-size: 13px; }\n            .ffr-eintrag-status { font-size: 12px; color: gold !important; margin-top: 8px; min-height: 16px; }\n\n            .ffr-rang-liste { width: 100%; max-height: 300px; overflow-y: auto; margin-bottom: 16px; }\n            .ffr-rang-zeile { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 6px; font-size: 14px; color: #fff !important; }\n            .ffr-rang-zeile:nth-child(odd) { background: rgba(255,255,255,0.05); }\n            .ffr-rang-platz { width: 24px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffr-rang-name { flex: 1; text-align: left; color: #fff !important; }\n            .ffr-rang-score { font-weight: 700; color: #fff !important; }\n            .ffr-rang-leer { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; }\n        <\/style>\n\n        <div class=\"ffr-box\">\n            <div class=\"ffr-title\">\ud83c\udfaf Strahlrohr-Ziel<\/div>\n            <div class=\"ffr-untertitel\">Zielt mit dem Wasserstrahl auf das wandernde Feuer!<\/div>\n\n            <div class=\"ffr-mini-rang\">\n                <div class=\"ffr-mini-rang-titel\">\ud83c\udfc6 Bestenliste<\/div>\n                <div class=\"ffr-tab-reihe ffr-mini-tabs\">\n                    <button class=\"ffr-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76<\/button>\n                    <button class=\"ffr-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2<\/button>\n                    <button class=\"ffr-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92<\/button>\n                <\/div>\n                <div class=\"ffr-mini-rang-inhalt\">L\u00e4dt \u2026<\/div>\n            <\/div>\n            <button class=\"ffr-rang-btn ffr-rang-oeffnen-btn\" type=\"button\">Komplette Rangliste<\/button>\n\n            <div class=\"ffr-hud\">\n                <span>\u23f1\ufe0f <span class=\"ffr-zeit\">45<\/span>s<\/span>\n                <span>\ud83d\udd25 Gel\u00f6scht: <span class=\"ffr-punkte\">0<\/span><\/span>\n            <\/div>\n            <div class=\"ffr-tank-wrap\">\n                <span class=\"ffr-tank-label\">\ud83d\udca7 Tank<\/span>\n                <div class=\"ffr-tank-balken-wrap\"><div class=\"ffr-tank-balken\" style=\"width:100%\"><\/div><\/div>\n            <\/div>\n\n            <div class=\"ffr-spielfeld\">\n                <div class=\"ffr-feld\">\n                    <div class=\"ffr-hydrant\">\ud83d\udeb0<\/div>\n                    <div class=\"ffr-ziel\">\ud83d\udd25<\/div>\n                    <div class=\"ffr-wind-hinweis\">\ud83d\udca8 Windb\u00f6e \u2013 Strahl wird abgedr\u00fcckt!<\/div>\n                    <div class=\"ffr-strahl\"><\/div>\n                    <div class=\"ffr-duese\">\ud83d\udebf<\/div>\n                <\/div>\n                <div class=\"ffr-kombo-anzeige\"><\/div>\n\n                <div class=\"ffr-zieh-hinweis\">\ud83d\udc46 Finger aufs Spielfeld legen und hin- und herziehen zum Spr\u00fchen<\/div>\n\n                <div class=\"ffr-overlay ffr-start\">\n                    <h3>Bereit zum Zielen?<\/h3>\n                    <p>Mit dem Finger auf dem Spielfeld ziehen, um die D\u00fcse auszurichten - solange\n                    ihr zieht, wird gespr\u00fcht. Bleibt am Feuer dran: Je l\u00e4nger ihr trefft, desto\n                    kleiner wird die Flamme, bis sie ganz erlischt. Euer Wassertank leert sich dabei -\n                    zum Hydranten \ud83d\udeb0 links fahren, um nachzuf\u00fcllen. Mehrere Flammen ohne Pause l\u00f6schen\n                    gibt Kombo-Bonus! Bei Jugend\/Erwachsenen dr\u00fcckt ab und zu eine Windb\u00f6e den Strahl\n                    seitlich weg - dann kurz gegensteuern. 45 Sekunden Zeit.<\/p>\n                    <div class=\"ffr-alter-buttons\">\n                        <button class=\"ffr-alter-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerg <span class=\"ffr-alter-sub\">langsames Ziel, kein Wind<\/span><\/button>\n                        <button class=\"ffr-alter-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend <span class=\"ffr-alter-sub\">mittleres Tempo, gelegentlich Wind<\/span><\/button>\n                        <button class=\"ffr-alter-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene <span class=\"ffr-alter-sub\">schnelles Ziel, Wind, enge Toleranz<\/span><\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"ffr-overlay ffr-ende\" style=\"display:none;\">\n                    <h3>Zeit abgelaufen! \ud83c\udf89<\/h3>\n                    <div class=\"ffr-ergebnis\">Flammen gel\u00f6scht: <strong><span class=\"ffr-endpunkte\">0<\/span><\/strong><\/div>\n                    <div class=\"ffr-eintrag-wrap\">\n                        <input type=\"text\" class=\"ffr-name-input\" maxlength=\"20\" placeholder=\"Dein Name f\u00fcr die Rangliste\">\n                        <button class=\"ffr-btn ffr-btn-klein ffr-eintrag-btn\" type=\"button\">In Rangliste eintragen<\/button>\n                        <div class=\"ffr-eintrag-status\"><\/div>\n                    <\/div>\n                    <button class=\"ffr-btn ffr-neustart-btn\" type=\"button\">Nochmal w\u00e4hlen<\/button>\n                <\/div>\n\n                <div class=\"ffr-overlay ffr-rangliste-overlay\" style=\"display:none;\">\n                    <h3>\ud83c\udfc6 Rangliste<\/h3>\n                    <div class=\"ffr-tab-reihe ffr-voll-tabs\">\n                        <button class=\"ffr-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerge<\/button>\n                        <button class=\"ffr-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend<\/button>\n                        <button class=\"ffr-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene<\/button>\n                    <\/div>\n                    <div class=\"ffr-rang-liste ffr-rang-liste-inhalt\">L\u00e4dt \u2026<\/div>\n                    <button class=\"ffr-btn ffr-rang-schliessen-btn\" type=\"button\">Schlie\u00dfen<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var wrap = document.getElementById('ffr-wrap-1');\n        if (!wrap) return;\n\n        var NONCE   = '23a7ac955e';\n        var AJAXURL = 'https:\/\/ff-willmatshofen.de\/wp-admin\/admin-ajax.php';\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n        function ffsSpielerId() {\n            var id = null;\n            try { id = localStorage.getItem('ffs_player_id'); } catch (e) {}\n            if (!id) {\n                id = (window.crypto && crypto.randomUUID) ? crypto.randomUUID() : ('id-' + Date.now() + '-' + Math.random().toString(16).slice(2));\n                try { localStorage.setItem('ffs_player_id', id); } catch (e) {}\n            }\n            return id;\n        }\n\n        var SCHWIERIGKEIT = {\n            loeschzwerg: { tempo: 0.5, toleranz: 15, startGroesse: 52, loeschDauerMs: 1600, tankLeerMs: 9000, tankFuellMs: 1500, wind: false },\n            jugend:      { tempo: 0.9, toleranz: 10, startGroesse: 42, loeschDauerMs: 2300, tankLeerMs: 7000, tankFuellMs: 2000, wind: true },\n            erwachsene:  { tempo: 1.4, toleranz: 6,  startGroesse: 32, loeschDauerMs: 3200, tankLeerMs: 5500, tankFuellMs: 2500, wind: true }\n        };\n        var RUNDENDAUER = 45;\n        var KOMBO_FENSTER_MS = 4000;\n        var HYDRANT_POS = 3;\n        var HYDRANT_REICHWEITE = 9;\n\n        var feld = wrap.querySelector('.ffr-feld');\n        var zielEl = wrap.querySelector('.ffr-ziel');\n        var strahlEl = wrap.querySelector('.ffr-strahl');\n        var dueseEl = wrap.querySelector('.ffr-duese');\n        var tankBalken = wrap.querySelector('.ffr-tank-balken');\n        var komboAnzeige = wrap.querySelector('.ffr-kombo-anzeige');\n        var windHinweis = wrap.querySelector('.ffr-wind-hinweis');\n        var zeitAnzeige = wrap.querySelector('.ffr-zeit');\n        var punkteAnzeige = wrap.querySelector('.ffr-punkte');\n        var startOverlay = wrap.querySelector('.ffr-start');\n        var endeOverlay = wrap.querySelector('.ffr-ende');\n        var ranglisteOverlay = wrap.querySelector('.ffr-rangliste-overlay');\n        var miniRangInhalt = wrap.querySelector('.ffr-mini-rang-inhalt');\n        var vollRangInhalt = wrap.querySelector('.ffr-rang-liste-inhalt');\n        var nameInput = wrap.querySelector('.ffr-name-input');\n        var eintragBtn = wrap.querySelector('.ffr-eintrag-btn');\n        var eintragStatus = wrap.querySelector('.ffr-eintrag-status');\n\n        var aktuelleAltersstufe = 'erwachsene';\n        var laeuft = false;\n        var punkte = 0;\n        var duesePos = 50;\n        var zielPos = 50;\n        var zielRichtung = 1;\n        var zielGesundheit = 100; \/\/ 100 = frisch entfacht, 0 = gel\u00f6scht\n        var sprueht = false;\n        var spielTimer = null;\n        var loopTimer = null;\n        var restZeit = RUNDENDAUER;\n\n        var tankProzent = 100;\n        var kombo = 0;\n        var letzterLoeschZeitpunkt = 0;\n        var windOffset = 0;\n        var windTimer = null;\n\n        function ffrPositionieren() {\n            dueseEl.style.left = duesePos + '%';\n            zielEl.style.left = zielPos + '%';\n            var strahlPos = Math.max(2, Math.min(98, duesePos + windOffset));\n            strahlEl.style.left = strahlPos + '%';\n            strahlEl.style.height = '200px';\n        }\n\n        function ffrZielGroesseAnwenden() {\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n            var groesse = Math.max(10, c.startGroesse * (zielGesundheit \/ 100));\n            zielEl.style.fontSize = groesse + 'px';\n        }\n\n        function ffrNeueFlamme() {\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n            zielGesundheit = 100;\n            zielPos = 10 + Math.random() * 80;\n            zielEl.style.display = '';\n            zielEl.textContent = '\ud83d\udd25';\n            ffrZielGroesseAnwenden();\n            ffrPositionieren();\n        }\n\n        function ffrDueseAufX(clientX) {\n            var rect = feld.getBoundingClientRect();\n            var prozent = ((clientX - rect.left) \/ rect.width) * 100;\n            duesePos = Math.max(5, Math.min(95, prozent));\n            ffrPositionieren();\n        }\n\n        function ffrTankAnzeigen() {\n            tankBalken.style.width = tankProzent + '%';\n            tankBalken.classList.toggle('leer', tankProzent <= 0);\n        }\n\n        function ffrLoop() {\n            if (!laeuft) return;\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n\n            zielPos += zielRichtung * c.tempo;\n            if (zielPos >= 93 || zielPos <= 7) zielRichtung *= -1;\n\n            \/\/ Am Hydranten (fester Punkt links) f\u00fcllt sich der Tank, solange\n            \/\/ die D\u00fcse dort in Reichweite ist - Spr\u00fchen ist dabei nicht m\u00f6glich.\n            var amHydranten = duesePos <= HYDRANT_REICHWEITE;\n            if (amHydranten && tankProzent < 100) {\n                tankProzent = Math.min(100, tankProzent + (100 \/ c.tankFuellMs) * 40);\n                ffrTankAnzeigen();\n            }\n\n            var kannSpruehen = sprueht && !amHydranten && tankProzent > 0;\n            strahlEl.classList.toggle('aktiv', kannSpruehen);\n\n            if (kannSpruehen) {\n                tankProzent = Math.max(0, tankProzent - (100 \/ c.tankLeerMs) * 40);\n                ffrTankAnzeigen();\n                if (tankProzent <= 0) ffrSprayEnde();\n            }\n\n            ffrPositionieren();\n\n            var effektivePos = Math.max(2, Math.min(98, duesePos + windOffset));\n            var getroffen = kannSpruehen && Math.abs(effektivePos - zielPos) <= c.toleranz;\n            zielEl.classList.toggle('getroffen', getroffen);\n\n            if (getroffen) {\n                \/\/ Pro Tick (40ms) so viel Gesundheit abziehen, dass die Flamme\n                \/\/ nach loeschDauerMs durchgehendem Treffer komplett erlischt.\n                var abzug = (100 \/ c.loeschDauerMs) * 40;\n                zielGesundheit = Math.max(0, zielGesundheit - abzug);\n                ffrZielGroesseAnwenden();\n\n                if (zielGesundheit <= 0) {\n                    ffrFlammeGeloescht();\n                }\n            }\n        }\n\n        function ffrKomboAnzeigen(text) {\n            komboAnzeige.textContent = text;\n            komboAnzeige.classList.add('sichtbar');\n            clearTimeout(komboAnzeige._timeout);\n            komboAnzeige._timeout = setTimeout(function() {\n                komboAnzeige.classList.remove('sichtbar');\n            }, 1200);\n        }\n\n        function ffrFlammeGeloescht() {\n            var jetzt = Date.now();\n            if (jetzt - letzterLoeschZeitpunkt <= KOMBO_FENSTER_MS) {\n                kombo++;\n            } else {\n                kombo = 1;\n            }\n            letzterLoeschZeitpunkt = jetzt;\n\n            var bonus = Math.min(kombo - 1, 5);\n            punkte += 1 + bonus;\n            punkteAnzeige.textContent = punkte;\n\n            if (kombo >= 2) {\n                ffrKomboAnzeigen('\ud83d\udd25 Kombo x' + kombo + '! +' + (1 + bonus));\n            }\n\n            zielEl.classList.remove('getroffen');\n            zielEl.classList.add('geloescht');\n            zielEl.textContent = '\ud83d\udca8';\n\n            setTimeout(function() {\n                zielEl.classList.remove('geloescht');\n                if (laeuft) ffrNeueFlamme();\n            }, 450);\n\n            \/\/ Kurz pausieren, damit nicht sofort die n\u00e4chste Flamme \"getroffen\"\n            \/\/ registriert wird, w\u00e4hrend die alte noch als Rauch angezeigt wird.\n            zielGesundheit = 999;\n        }\n\n        function ffrSprayStart() {\n            if (!laeuft) return;\n            sprueht = true;\n        }\n        function ffrSprayEnde() {\n            sprueht = false;\n            strahlEl.classList.remove('aktiv');\n            zielEl.classList.remove('getroffen');\n        }\n\n        function ffrSpielEnde() {\n            laeuft = false;\n            clearInterval(spielTimer);\n            clearInterval(loopTimer);\n            clearTimeout(windTimer);\n            ffrSprayEnde();\n\n            wrap.querySelector('.ffr-endpunkte').textContent = punkte;\n            nameInput.value = '';\n            eintragBtn.disabled = false;\n            eintragStatus.textContent = '';\n            endeOverlay.style.display = 'flex';\n\n            var abzeichen = punkte >= 16 ? 'gold' : (punkte >= 8 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('strahlrohr', abzeichen);\n        }\n\n        function ffrSpielStart(altersstufe) {\n            aktuelleAltersstufe = altersstufe;\n            try { localStorage.setItem('ffr_last_bracket', altersstufe); } catch (e) {}\n\n            laeuft = true;\n            punkte = 0;\n            duesePos = 50;\n            zielRichtung = 1;\n            restZeit = RUNDENDAUER;\n            tankProzent = 100;\n            kombo = 0;\n            letzterLoeschZeitpunkt = 0;\n            windOffset = 0;\n            windHinweis.classList.remove('aktiv');\n            komboAnzeige.classList.remove('sichtbar');\n            punkteAnzeige.textContent = '0';\n            zeitAnzeige.textContent = restZeit;\n            ffrTankAnzeigen();\n            ffrNeueFlamme();\n            ffrPositionieren();\n\n            startOverlay.style.display = 'none';\n            endeOverlay.style.display = 'none';\n            ranglisteOverlay.style.display = 'none';\n\n            clearInterval(spielTimer);\n            clearInterval(loopTimer);\n            clearTimeout(windTimer);\n            spielTimer = setInterval(function() {\n                restZeit--;\n                zeitAnzeige.textContent = restZeit;\n                if (restZeit <= 0) ffrSpielEnde();\n            }, 1000);\n            loopTimer = setInterval(ffrLoop, 40);\n\n            if (SCHWIERIGKEIT[altersstufe].wind) {\n                ffrWindZyklusPlanen();\n            }\n        }\n\n        function ffrWindZyklusPlanen() {\n            clearTimeout(windTimer);\n            windTimer = setTimeout(function() {\n                if (!laeuft) return;\n                windOffset = (Math.random() < 0.5 ? -1 : 1) * (6 + Math.random() * 6);\n                windHinweis.classList.add('aktiv');\n                setTimeout(function() {\n                    windOffset = 0;\n                    windHinweis.classList.remove('aktiv');\n                    if (laeuft) ffrWindZyklusPlanen();\n                }, 1500);\n            }, 5000 + Math.random() * 3000);\n        }\n\n        feld.addEventListener('pointerdown', function(e) {\n            if (!laeuft) return;\n            feld.setPointerCapture(e.pointerId);\n            ffrSprayStart();\n            ffrDueseAufX(e.clientX);\n        });\n        feld.addEventListener('pointermove', function(e) {\n            if (!laeuft || !sprueht) return;\n            ffrDueseAufX(e.clientX);\n        });\n        feld.addEventListener('pointerup', ffrSprayEnde);\n        feld.addEventListener('pointercancel', ffrSprayEnde);\n        feld.addEventListener('pointerleave', function(e) {\n            \/\/ Nur beenden, wenn die Maus wirklich losgelassen wurde (kein\n            \/\/ Touch-Pointer, der ohnehin \u00fcber setPointerCapture gebunden ist)\n            if (e.pointerType === 'mouse') ffrSprayEnde();\n        });\n\n        wrap.querySelectorAll('.ffr-alter-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { ffrSpielStart(btn.dataset.stufe); });\n        });\n        wrap.querySelector('.ffr-neustart-btn').addEventListener('click', function() {\n            endeOverlay.style.display = 'none';\n            startOverlay.style.display = 'flex';\n        });\n\n        ffrPositionieren();\n\n        \/\/ ---------- Rangliste (gleiches Muster wie bei den anderen Spielen) ----------\n        function ffrRangZeilenHtml(liste, prefix) {\n            var html = '';\n            liste.forEach(function(e, i) {\n                html += '<div class=\"' + prefix + '-zeile\"><span class=\"' + prefix + '-platz\">' + (i + 1) + '.<\/span>' +\n                    '<span class=\"' + prefix + '-name\">' + ffrEscapeHtml(e.name) + '<\/span>' +\n                    '<span class=\"' + prefix + '-score\">' + e.score + '<\/span><\/div>';\n            });\n            return html;\n        }\n        function ffrEscapeHtml(str) { var d = document.createElement('div'); d.textContent = str; return d.innerHTML; }\n        function ffrRanglisteHolen(stufe, callback) {\n            var fd = new FormData();\n            fd.append('action', 'ff_strahl_rangliste_holen');\n            fd.append('nonce', NONCE);\n            fd.append('altersstufe', stufe);\n            fetch(AJAXURL, { method: 'POST', body: fd })\n                .then(function(r) { return r.json(); })\n                .then(function(data) { callback((data.success && data.data) ? data.data : []); })\n                .catch(function() { callback(null); });\n        }\n        function ffrLetzteAltersstufe() {\n            var stufe = null;\n            try { stufe = localStorage.getItem('ffr_last_bracket'); } catch (e) {}\n            return (stufe === 'loeschzwerg' || stufe === 'jugend' || stufe === 'erwachsene') ? stufe : 'erwachsene';\n        }\n        function ffrTabsAktualisieren(sel, aktiv) {\n            wrap.querySelectorAll(sel + ' .ffr-tab-btn').forEach(function(b) { b.classList.toggle('aktiv', b.dataset.stufe === aktiv); });\n        }\n\n        var ffrMiniStufe = ffrLetzteAltersstufe();\n        function ffrMiniRanglisteLaden() {\n            ffrTabsAktualisieren('.ffr-mini-tabs', ffrMiniStufe);\n            miniRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            ffrRanglisteHolen(ffrMiniStufe, function(liste) {\n                if (liste === null) { miniRangInhalt.innerHTML = '<div class=\"ffr-mini-rang-leer\">Rangliste konnte nicht geladen werden.<\/div>'; return; }\n                if (!liste.length) { miniRangInhalt.innerHTML = '<div class=\"ffr-mini-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/div>'; return; }\n                miniRangInhalt.innerHTML = ffrRangZeilenHtml(liste.slice(0, 5), 'ffr-mini-rang');\n            });\n        }\n        wrap.querySelectorAll('.ffr-mini-tabs .ffr-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { ffrMiniStufe = btn.dataset.stufe; ffrMiniRanglisteLaden(); });\n        });\n        ffrMiniRanglisteLaden();\n\n        var ffrVollStufe = ffrLetzteAltersstufe();\n        function ffrVollRanglisteLaden() {\n            ffrTabsAktualisieren('.ffr-voll-tabs', ffrVollStufe);\n            vollRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            ffrRanglisteHolen(ffrVollStufe, function(liste) {\n                if (liste === null) { vollRangInhalt.innerHTML = '<p class=\"ffr-rang-leer\">Rangliste konnte nicht geladen werden.<\/p>'; return; }\n                if (!liste.length) { vollRangInhalt.innerHTML = '<p class=\"ffr-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/p>'; return; }\n                vollRangInhalt.innerHTML = ffrRangZeilenHtml(liste, 'ffr-rang');\n            });\n        }\n        wrap.querySelectorAll('.ffr-voll-tabs .ffr-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { ffrVollStufe = btn.dataset.stufe; ffrVollRanglisteLaden(); });\n        });\n        wrap.querySelector('.ffr-rang-oeffnen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'flex';\n            ffrVollRanglisteLaden();\n        });\n        wrap.querySelector('.ffr-rang-schliessen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'none';\n        });\n\n        eintragBtn.addEventListener('click', function() {\n            var name = nameInput.value.trim();\n            if (!name) { eintragStatus.textContent = 'Bitte einen Namen eingeben.'; return; }\n            eintragBtn.disabled = true;\n            eintragStatus.textContent = 'Wird gespeichert \u2026';\n\n            var fd = new FormData();\n            fd.append('action', 'ff_strahl_score_speichern');\n            fd.append('nonce', NONCE);\n            fd.append('name', name);\n            fd.append('score', punkte);\n            fd.append('spieler_id', ffsSpielerId());\n            fd.append('altersstufe', aktuelleAltersstufe);\n\n            fetch(AJAXURL, { method: 'POST', body: fd })\n                .then(function(r) { return r.json(); })\n                .then(function(data) {\n                    if (data.success) {\n                        eintragStatus.textContent = (data.data && data.data.verbessert === false)\n                            ? 'Dein bisheriger Eintrag war schon besser oder gleich gut \u2013 bleibt unver\u00e4ndert.'\n                            : '\u2705 In der Rangliste eingetragen!';\n                        ffrMiniStufe = aktuelleAltersstufe;\n                        ffrMiniRanglisteLaden();\n                    } else if (data.data && data.data.grund === 'name_vergeben') {\n                        eintragStatus.textContent = '\u26a0\ufe0f Dieser Name ist schon vergeben \u2013 bitte einen anderen w\u00e4hlen.';\n                        eintragBtn.disabled = false;\n                    } else {\n                        eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                        eintragBtn.disabled = false;\n                    }\n                })\n                .catch(function() {\n                    eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                    eintragBtn.disabled = false;\n                });\n        });\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-deich\">\n            <div class=\"ffd-wrap\" id=\"ffd-wrap-1\">\n        <style>\n            .ffd-wrap { max-width: 420px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffd-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 20px; color: #fff !important; text-align: center; position: relative; overflow: hidden; }\n            .ffd-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffd-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 10px; }\n\n            .ffd-rang-btn { background: none; border: 1px solid gold; color: gold !important; padding: 6px 16px; border-radius: 20px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; margin-bottom: 4px; }\n            .ffd-rang-btn:hover { background: gold; color: #1C2B4B !important; }\n            .ffd-mini-rang { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,215,0,0.3); border-radius: 8px; padding: 10px 14px; margin-bottom: 14px; text-align: left; }\n            .ffd-mini-rang-titel { font-size: 12px; font-weight: 700; color: gold !important; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 6px; text-align: center; }\n            .ffd-mini-rang-zeile { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; color: #fff !important; }\n            .ffd-mini-rang-platz { width: 18px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffd-mini-rang-name { flex: 1; }\n            .ffd-mini-rang-score { font-weight: 700; }\n            .ffd-mini-rang-leer { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; text-align: center; }\n\n            .ffd-tab-reihe { display: flex; gap: 6px; margin-bottom: 10px; justify-content: center; flex-wrap: wrap; }\n            .ffd-tab-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: var(--ff-text-muted, #a0b0c8) !important; padding: 5px 10px; border-radius: 20px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit; }\n            .ffd-tab-btn.aktiv { background: gold; border-color: gold; color: #1C2B4B !important; }\n\n            .ffd-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-size: 13px; font-weight: 700; color: #fff !important; }\n            .ffd-pegel-wrap { width: 100%; height: 10px; background: rgba(255,255,255,0.12); border-radius: 5px; margin-bottom: 14px; overflow: hidden; }\n            .ffd-pegel-balken { height: 100%; background: linear-gradient(90deg, #4a90d9, #3fae4a, gold, var(--ff-red, #CC0000)); border-radius: 5px; transition: width 0.5s linear; }\n\n            .ffd-spielfeld { position: relative; min-height: 440px !important; }\n            .ffd-reihe { display: flex; gap: 6px; margin-bottom: 8px; }\n            .ffd-abschnitt { flex: 1; aspect-ratio: 1\/1.3; background: rgba(255,255,255,0.06); border: 2px solid rgba(255,255,255,0.15); border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 26px; cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation; transition: transform 0.1s; }\n            .ffd-abschnitt:active { transform: scale(0.92); }\n            .ffd-abschnitt.gefahr { border-color: var(--ff-red, #CC0000); animation: ffd-puls 0.4s infinite alternate; }\n            .ffd-abschnitt.gesichert { border-color: #3fae4a; animation: ffd-pop 0.3s ease; }\n            .ffd-abschnitt.gebrochen { border-color: #555; }\n            @keyframes ffd-puls { from { box-shadow: 0 0 0 var(--ff-red,#CC0000); } to { box-shadow: 0 0 12px var(--ff-red,#CC0000); } }\n            @keyframes ffd-pop { 0% { transform: scale(1); } 40% { transform: scale(1.2); } 100% { transform: scale(1); } }\n\n            .ffd-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px; border-radius: 12px; z-index: 3; color: #fff !important; overflow-y: auto; }\n            .ffd-overlay h3 { font-size: 20px; margin-bottom: 8px; color: #fff !important; }\n            .ffd-overlay p { font-size: 14px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; line-height: 1.6; }\n            .ffd-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .ffd-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffd-btn:disabled { opacity: 0.5; cursor: default; }\n            .ffd-ergebnis { font-size: 15px; margin-bottom: 14px; color: #fff !important; }\n            .ffd-ergebnis strong { color: gold !important; }\n\n            .ffd-alter-buttons { display: flex; flex-direction: column; gap: 8px; width: 100%; margin-bottom: 4px; }\n            .ffd-alter-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: #fff !important; padding: 10px 16px; border-radius: 8px; font-size: 14px; font-weight: 700; cursor: pointer; font-family: inherit; text-align: left; display: flex; align-items: center; justify-content: space-between; }\n            .ffd-alter-btn:hover { border-color: var(--ff-red, #CC0000); background: rgba(204,0,0,0.15); }\n            .ffd-alter-btn span.ffd-alter-sub { font-size: 12px; font-weight: 400; color: var(--ff-text-muted, #a0b0c8) !important; }\n\n            .ffd-eintrag-wrap { width: 100%; margin-bottom: 14px; }\n            .ffd-name-input { width: 100%; box-sizing: border-box; padding: 10px 14px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.25) !important; background: rgba(255,255,255,0.08) !important; color: #fff !important; font-size: 14px; font-family: inherit; margin-bottom: 10px; text-align: center; }\n            .ffd-name-input::placeholder { color: var(--ff-text-muted, #a0b0c8) !important; }\n            .ffd-btn-klein { padding: 8px 22px; font-size: 13px; }\n            .ffd-eintrag-status { font-size: 12px; color: gold !important; margin-top: 8px; min-height: 16px; }\n\n            .ffd-rang-liste { width: 100%; max-height: 300px; overflow-y: auto; margin-bottom: 16px; }\n            .ffd-rang-zeile { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 6px; font-size: 14px; color: #fff !important; }\n            .ffd-rang-zeile:nth-child(odd) { background: rgba(255,255,255,0.05); }\n            .ffd-rang-platz { width: 24px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffd-rang-name { flex: 1; text-align: left; color: #fff !important; }\n            .ffd-rang-score { font-weight: 700; color: #fff !important; }\n            .ffd-rang-leer { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; }\n        <\/style>\n\n        <div class=\"ffd-box\">\n            <div class=\"ffd-title\">\ud83c\udf0a Deich-Verteidigung<\/div>\n            <div class=\"ffd-untertitel\">Stapelt rechtzeitig Sands\u00e4cke, bevor der Deich bricht!<\/div>\n\n            <div class=\"ffd-mini-rang\">\n                <div class=\"ffd-mini-rang-titel\">\ud83c\udfc6 Bestenliste<\/div>\n                <div class=\"ffd-tab-reihe ffd-mini-tabs\">\n                    <button class=\"ffd-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76<\/button>\n                    <button class=\"ffd-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2<\/button>\n                    <button class=\"ffd-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92<\/button>\n                <\/div>\n                <div class=\"ffd-mini-rang-inhalt\">L\u00e4dt \u2026<\/div>\n            <\/div>\n            <button class=\"ffd-rang-btn ffd-rang-oeffnen-btn\" type=\"button\">Komplette Rangliste<\/button>\n\n            <div class=\"ffd-hud\">\n                <span>\ud83c\udf92 Gesichert: <span class=\"ffd-punkte\">0<\/span><\/span>\n                <span class=\"ffd-leben\">\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f<\/span>\n            <\/div>\n            <div class=\"ffd-pegel-wrap\"><div class=\"ffd-pegel-balken\" style=\"width:0%\"><\/div><\/div>\n\n            <div class=\"ffd-spielfeld\">\n                <div class=\"ffd-reihe\"><\/div>\n\n                <div class=\"ffd-overlay ffd-start\">\n                    <h3>Bereit zur Deichverteidigung?<\/h3>\n                    <p>Sobald an einem Abschnitt \"Gefahr\" aufblinkt, schnell antippen, um Sands\u00e4cke\n                    zu stapeln. 3 Leben, wird mit der Zeit schneller!<\/p>\n                    <div class=\"ffd-alter-buttons\">\n                        <button class=\"ffd-alter-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerg <span class=\"ffd-alter-sub\">viel Reaktionszeit<\/span><\/button>\n                        <button class=\"ffd-alter-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend <span class=\"ffd-alter-sub\">mittlere Reaktionszeit<\/span><\/button>\n                        <button class=\"ffd-alter-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene <span class=\"ffd-alter-sub\">wenig Reaktionszeit<\/span><\/button>\n                    <\/div>\n                <\/div>\n\n                <div class=\"ffd-overlay ffd-ende\" style=\"display:none;\">\n                    <h3>Einsatz beendet!<\/h3>\n                    <div class=\"ffd-ergebnis\">Sands\u00e4cke gestapelt: <strong><span class=\"ffd-endpunkte\">0<\/span><\/strong><\/div>\n                    <div class=\"ffd-eintrag-wrap\">\n                        <input type=\"text\" class=\"ffd-name-input\" maxlength=\"20\" placeholder=\"Dein Name f\u00fcr die Rangliste\">\n                        <button class=\"ffd-btn ffd-btn-klein ffd-eintrag-btn\" type=\"button\">In Rangliste eintragen<\/button>\n                        <div class=\"ffd-eintrag-status\"><\/div>\n                    <\/div>\n                    <button class=\"ffd-btn ffd-neustart-btn\" type=\"button\">Nochmal w\u00e4hlen<\/button>\n                <\/div>\n\n                <div class=\"ffd-overlay ffd-rangliste-overlay\" style=\"display:none;\">\n                    <h3>\ud83c\udfc6 Rangliste<\/h3>\n                    <div class=\"ffd-tab-reihe ffd-voll-tabs\">\n                        <button class=\"ffd-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerge<\/button>\n                        <button class=\"ffd-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend<\/button>\n                        <button class=\"ffd-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene<\/button>\n                    <\/div>\n                    <div class=\"ffd-rang-liste ffd-rang-liste-inhalt\">L\u00e4dt \u2026<\/div>\n                    <button class=\"ffd-btn ffd-rang-schliessen-btn\" type=\"button\">Schlie\u00dfen<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var wrap = document.getElementById('ffd-wrap-1');\n        if (!wrap) return;\n\n        var NONCE   = 'd99c3ade34';\n        var AJAXURL = 'https:\/\/ff-willmatshofen.de\/wp-admin\/admin-ajax.php';\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n        function ffsSpielerId() {\n            var id = null;\n            try { id = localStorage.getItem('ffs_player_id'); } catch (e) {}\n            if (!id) {\n                id = (window.crypto && crypto.randomUUID) ? crypto.randomUUID() : ('id-' + Date.now() + '-' + Math.random().toString(16).slice(2));\n                try { localStorage.setItem('ffs_player_id', id); } catch (e) {}\n            }\n            return id;\n        }\n\n        var ABSCHNITTE = 6;\n        var SCHWIERIGKEIT = {\n            loeschzwerg: { rampStart: 4, spawnStart: 2600, spawnStep: 20, spawnMin: 1600, fensterStart: 3200, fensterStep: 20, fensterMin: 2000 },\n            jugend:      { rampStart: 2, spawnStart: 1900, spawnStep: 28, spawnMin: 1100, fensterStart: 2300, fensterStep: 28, fensterMin: 1300 },\n            erwachsene:  { rampStart: 0, spawnStart: 1400, spawnStep: 35, spawnMin: 700,  fensterStart: 1700, fensterStep: 35, fensterMin: 800 }\n        };\n\n        var reihe = wrap.querySelector('.ffd-reihe');\n        var punkteAnzeige = wrap.querySelector('.ffd-punkte');\n        var lebenAnzeige = wrap.querySelector('.ffd-leben');\n        var pegelBalken = wrap.querySelector('.ffd-pegel-balken');\n        var startOverlay = wrap.querySelector('.ffd-start');\n        var endeOverlay = wrap.querySelector('.ffd-ende');\n        var ranglisteOverlay = wrap.querySelector('.ffd-rangliste-overlay');\n        var miniRangInhalt = wrap.querySelector('.ffd-mini-rang-inhalt');\n        var vollRangInhalt = wrap.querySelector('.ffd-rang-liste-inhalt');\n        var nameInput = wrap.querySelector('.ffd-name-input');\n        var eintragBtn = wrap.querySelector('.ffd-eintrag-btn');\n        var eintragStatus = wrap.querySelector('.ffd-eintrag-status');\n\n        var aktuelleAltersstufe = 'erwachsene';\n        var abschnitte = [];\n        var punkte = 0;\n        var leben = 3;\n        var laeuft = false;\n        var spawnTimer = null;\n        var pegelTimer = null;\n        var pegelProzent = 0;\n\n        function ffdAufbauen() {\n            reihe.innerHTML = '';\n            abschnitte = [];\n            for (var i = 0; i < ABSCHNITTE; i++) {\n                var el = document.createElement('div');\n                el.className = 'ffd-abschnitt';\n                el.textContent = '\ud83e\uddf1';\n                el.dataset.index = i;\n                el.addEventListener('click', function() { ffdTippen(abschnitte[parseInt(this.dataset.index)]); });\n                reihe.appendChild(el);\n                abschnitte.push({ el: el, status: 'ok', timeout: null });\n            }\n        }\n\n        function ffdSpawnIntervall() {\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n            var eff = Math.max(0, punkte - c.rampStart);\n            return Math.max(c.spawnMin, c.spawnStart - eff * c.spawnStep);\n        }\n        function ffdFenster() {\n            var c = SCHWIERIGKEIT[aktuelleAltersstufe];\n            var eff = Math.max(0, punkte - c.rampStart);\n            return Math.max(c.fensterMin, c.fensterStart - eff * c.fensterStep);\n        }\n\n        function ffdNaechsteGefahr() {\n            if (!laeuft) return;\n            var freie = abschnitte.filter(function(a) { return a.status === 'ok'; });\n            if (freie.length) {\n                var a = freie[Math.floor(Math.random() * freie.length)];\n                ffdGefahrAn(a);\n            }\n            spawnTimer = setTimeout(ffdNaechsteGefahr, ffdSpawnIntervall());\n        }\n\n        function ffdGefahrAn(a) {\n            a.status = 'gefahr';\n            a.el.className = 'ffd-abschnitt gefahr';\n            a.el.textContent = '\u26a0\ufe0f';\n            var fenster = ffdFenster();\n            a.timeout = setTimeout(function() { ffdGebrochen(a); }, fenster);\n        }\n\n        function ffdTippen(a) {\n            if (!laeuft || a.status !== 'gefahr') return;\n            clearTimeout(a.timeout);\n            a.status = 'ok';\n            a.el.className = 'ffd-abschnitt gesichert';\n            a.el.textContent = '\ud83c\udf92';\n            punkte++;\n            punkteAnzeige.textContent = punkte;\n            setTimeout(function() {\n                if (a.status === 'ok') { a.el.className = 'ffd-abschnitt'; a.el.textContent = '\ud83e\uddf1'; }\n            }, 350);\n        }\n\n        function ffdGebrochen(a) {\n            a.status = 'gebrochen';\n            a.el.className = 'ffd-abschnitt gebrochen';\n            a.el.textContent = '\ud83d\udca5';\n            leben--;\n            lebenAnzeige.textContent = '\u2764\ufe0f'.repeat(Math.max(0, leben)) + '\ud83d\udda4'.repeat(3 - Math.max(0, leben));\n            setTimeout(function() {\n                if (a.status === 'gebrochen') { a.status = 'ok'; a.el.className = 'ffd-abschnitt'; a.el.textContent = '\ud83e\uddf1'; }\n            }, 500);\n            if (leben <= 0) ffdSpielEnde();\n        }\n\n        function ffdPegelSteigen() {\n            pegelProzent = Math.min(100, pegelProzent + 0.6);\n            pegelBalken.style.width = pegelProzent + '%';\n        }\n\n        function ffdSpielEnde() {\n            laeuft = false;\n            clearTimeout(spawnTimer);\n            clearInterval(pegelTimer);\n            abschnitte.forEach(function(a) { clearTimeout(a.timeout); });\n\n            wrap.querySelector('.ffd-endpunkte').textContent = punkte;\n            nameInput.value = '';\n            eintragBtn.disabled = false;\n            eintragStatus.textContent = '';\n            endeOverlay.style.display = 'flex';\n\n            var abzeichen = punkte >= 30 ? 'gold' : (punkte >= 15 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('deich', abzeichen);\n        }\n\n        function ffdSpielStart(altersstufe) {\n            aktuelleAltersstufe = altersstufe;\n            try { localStorage.setItem('ffd_last_bracket', altersstufe); } catch (e) {}\n\n            laeuft = true;\n            punkte = 0;\n            leben = 3;\n            pegelProzent = 0;\n            punkteAnzeige.textContent = '0';\n            lebenAnzeige.textContent = '\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f';\n            pegelBalken.style.width = '0%';\n\n            startOverlay.style.display = 'none';\n            endeOverlay.style.display = 'none';\n            ranglisteOverlay.style.display = 'none';\n\n            ffdAufbauen();\n\n            clearTimeout(spawnTimer);\n            clearInterval(pegelTimer);\n            spawnTimer = setTimeout(ffdNaechsteGefahr, 1200);\n            pegelTimer = setInterval(ffdPegelSteigen, 800);\n        }\n\n        wrap.querySelectorAll('.ffd-alter-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { ffdSpielStart(btn.dataset.stufe); });\n        });\n        wrap.querySelector('.ffd-neustart-btn').addEventListener('click', function() {\n            endeOverlay.style.display = 'none';\n            startOverlay.style.display = 'flex';\n        });\n\n        \/\/ ---------- Rangliste ----------\n        function ffdRangZeilenHtml(liste, prefix) {\n            var html = '';\n            liste.forEach(function(e, i) {\n                html += '<div class=\"' + prefix + '-zeile\"><span class=\"' + prefix + '-platz\">' + (i + 1) + '.<\/span>' +\n                    '<span class=\"' + prefix + '-name\">' + ffdEscapeHtml(e.name) + '<\/span>' +\n                    '<span class=\"' + prefix + '-score\">' + e.score + '<\/span><\/div>';\n            });\n            return html;\n        }\n        function ffdEscapeHtml(str) { var d = document.createElement('div'); d.textContent = str; return d.innerHTML; }\n        function ffdRanglisteHolen(stufe, callback) {\n            var fd = new FormData();\n            fd.append('action', 'ff_deich_rangliste_holen');\n            fd.append('nonce', NONCE);\n            fd.append('altersstufe', stufe);\n            fetch(AJAXURL, { method: 'POST', body: fd })\n                .then(function(r) { return r.json(); })\n                .then(function(data) { callback((data.success && data.data) ? data.data : []); })\n                .catch(function() { callback(null); });\n        }\n        function ffdLetzteAltersstufe() {\n            var stufe = null;\n            try { stufe = localStorage.getItem('ffd_last_bracket'); } catch (e) {}\n            return (stufe === 'loeschzwerg' || stufe === 'jugend' || stufe === 'erwachsene') ? stufe : 'erwachsene';\n        }\n        function ffdTabsAktualisieren(sel, aktiv) {\n            wrap.querySelectorAll(sel + ' .ffd-tab-btn').forEach(function(b) { b.classList.toggle('aktiv', b.dataset.stufe === aktiv); });\n        }\n\n        var ffdMiniStufe = ffdLetzteAltersstufe();\n        function ffdMiniRanglisteLaden() {\n            ffdTabsAktualisieren('.ffd-mini-tabs', ffdMiniStufe);\n            miniRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            ffdRanglisteHolen(ffdMiniStufe, function(liste) {\n                if (liste === null) { miniRangInhalt.innerHTML = '<div class=\"ffd-mini-rang-leer\">Rangliste konnte nicht geladen werden.<\/div>'; return; }\n                if (!liste.length) { miniRangInhalt.innerHTML = '<div class=\"ffd-mini-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/div>'; return; }\n                miniRangInhalt.innerHTML = ffdRangZeilenHtml(liste.slice(0, 5), 'ffd-mini-rang');\n            });\n        }\n        wrap.querySelectorAll('.ffd-mini-tabs .ffd-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { ffdMiniStufe = btn.dataset.stufe; ffdMiniRanglisteLaden(); });\n        });\n        ffdMiniRanglisteLaden();\n\n        var ffdVollStufe = ffdLetzteAltersstufe();\n        function ffdVollRanglisteLaden() {\n            ffdTabsAktualisieren('.ffd-voll-tabs', ffdVollStufe);\n            vollRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            ffdRanglisteHolen(ffdVollStufe, function(liste) {\n                if (liste === null) { vollRangInhalt.innerHTML = '<p class=\"ffd-rang-leer\">Rangliste konnte nicht geladen werden.<\/p>'; return; }\n                if (!liste.length) { vollRangInhalt.innerHTML = '<p class=\"ffd-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/p>'; return; }\n                vollRangInhalt.innerHTML = ffdRangZeilenHtml(liste, 'ffd-rang');\n            });\n        }\n        wrap.querySelectorAll('.ffd-voll-tabs .ffd-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { ffdVollStufe = btn.dataset.stufe; ffdVollRanglisteLaden(); });\n        });\n        wrap.querySelector('.ffd-rang-oeffnen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'flex';\n            ffdVollRanglisteLaden();\n        });\n        wrap.querySelector('.ffd-rang-schliessen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'none';\n        });\n\n        eintragBtn.addEventListener('click', function() {\n            var name = nameInput.value.trim();\n            if (!name) { eintragStatus.textContent = 'Bitte einen Namen eingeben.'; return; }\n            eintragBtn.disabled = true;\n            eintragStatus.textContent = 'Wird gespeichert \u2026';\n\n            var fd = new FormData();\n            fd.append('action', 'ff_deich_score_speichern');\n            fd.append('nonce', NONCE);\n            fd.append('name', name);\n            fd.append('score', punkte);\n            fd.append('spieler_id', ffsSpielerId());\n            fd.append('altersstufe', aktuelleAltersstufe);\n\n            fetch(AJAXURL, { method: 'POST', body: fd })\n                .then(function(r) { return r.json(); })\n                .then(function(data) {\n                    if (data.success) {\n                        eintragStatus.textContent = (data.data && data.data.verbessert === false)\n                            ? 'Dein bisheriger Eintrag war schon besser oder gleich gut \u2013 bleibt unver\u00e4ndert.'\n                            : '\u2705 In der Rangliste eingetragen!';\n                        ffdMiniStufe = aktuelleAltersstufe;\n                        ffdMiniRanglisteLaden();\n                    } else if (data.data && data.data.grund === 'name_vergeben') {\n                        eintragStatus.textContent = '\u26a0\ufe0f Dieser Name ist schon vergeben \u2013 bitte einen anderen w\u00e4hlen.';\n                        eintragBtn.disabled = false;\n                    } else {\n                        eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                        eintragBtn.disabled = false;\n                    }\n                })\n                .catch(function() {\n                    eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                    eintragBtn.disabled = false;\n                });\n        });\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-einsatzfahrt\">\n            <div class=\"ffc-wrap\" id=\"ffc-wrap-1\">\n        <style>\n            .ffc-wrap { max-width: 420px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffc-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 16px; color: #fff !important; text-align: center; position: relative; overflow: hidden; }\n            .ffc-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffc-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 10px; }\n\n            .ffc-rang-btn { background: none; border: 1px solid gold; color: gold !important; padding: 6px 16px; border-radius: 20px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; margin-bottom: 10px; }\n            .ffc-rang-btn:hover { background: gold; color: #1C2B4B !important; }\n\n            .ffc-spielfeld { position: relative; touch-action: manipulation; overflow: hidden; }\n            .ffc-canvas-wrap { position: relative; width: 100%; }\n            .ffc-canvas { width: 100%; display: block; border-radius: 10px; background: #6ec6ff; }\n\n            .ffc-canvas-leiste { position: absolute; top: 8px; right: 8px; z-index: 15; display: flex; align-items: center; gap: 8px; }\n            .ffc-blaulicht-indikator { width: 44px; height: 44px; border-radius: 50%; background: rgba(0,0,0,0.4); display: flex; align-items: center; justify-content: center; font-size: 22px; animation: ffc-blaulicht-blink 0.45s steps(1) infinite; }\n            @keyframes ffc-blaulicht-blink { 0% { box-shadow: 0 0 12px 3px rgba(42,123,255,0.9); } 50% { box-shadow: 0 0 12px 3px rgba(255,60,60,0.9); } 100% { box-shadow: 0 0 12px 3px rgba(42,123,255,0.9); } }\n            .ffc-sound-btn { background: rgba(0,0,0,0.55); border: 2px solid rgba(255,255,255,0.5); color: #fff !important; font-size: 26px; width: 64px; height: 64px; border-radius: 18px; cursor: pointer; -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; flex-shrink: 0; }\n            .ffc-horn-label { font-size: 11px; font-weight: 700; color: #fff !important; }\n            .ffc-sound-btn.an { border-color: gold; box-shadow: 0 0 10px rgba(255,215,0,0.6); background: rgba(90,70,0,0.75); }\n\n            .ffc-steuerung { display: flex; align-items: center; justify-content: flex-start; gap: 14px; margin-top: 12px; position: relative; z-index: 20; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }\n            .ffc-joystick { position: relative; width: 130px; height: 130px; border-radius: 50%; background: rgba(255,255,255,0.07); border: 2px solid rgba(255,255,255,0.25); touch-action: none; -webkit-touch-callout: none; }\n            .ffc-joystick::before { content: ''; position: absolute; inset: 12px; border-radius: 50%; border: 1px dashed rgba(255,255,255,0.15); }\n            .ffc-stick { position: absolute; left: 50%; top: 50%; width: 54px; height: 54px; margin: -27px 0 0 -27px; border-radius: 50%; background: var(--ff-red, #CC0000); border: 3px solid rgba(255,255,255,0.7); box-shadow: 0 3px 8px rgba(0,0,0,0.4); display: flex; align-items: center; justify-content: center; font-size: 20px; pointer-events: none; }\n            .ffc-joystick-hinweis { font-size: 11px; color: var(--ff-text-muted, #a0b0c8) !important; align-self: center; margin-left: 14px; text-align: left; line-height: 1.5; }\n\n            .ffc-overlay { position: absolute; inset: 0; background: rgba(15,30,56,0.97); display: flex; flex-direction: column; align-items: center; justify-content: flex-start; padding: 18px; border-radius: 12px; z-index: 30; color: #fff !important; overflow-y: auto; }\n            .ffc-overlay h3 { font-size: 19px; margin-bottom: 6px; color: #fff !important; }\n            .ffc-overlay p { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 12px; line-height: 1.5; }\n            .ffc-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 11px 26px; border-radius: 6px; font-weight: 700; font-size: 14px; cursor: pointer; font-family: inherit; }\n            .ffc-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffc-btn:disabled { opacity: 0.5; cursor: default; }\n            .ffc-ergebnis { font-size: 15px; margin-bottom: 12px; color: #fff !important; }\n            .ffc-ergebnis strong { color: gold !important; }\n\n            .ffc-tier-chips { display: flex; gap: 6px; justify-content: center; margin-bottom: 12px; flex-wrap: wrap; }\n            .ffc-tier-chip { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: #fff !important; padding: 7px 13px; border-radius: 20px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; }\n            .ffc-tier-chip.aktiv { background: gold; border-color: gold; color: #1C2B4B !important; }\n\n            .ffc-modus-titel { font-size: 13px; font-weight: 700; color: gold !important; text-transform: uppercase; letter-spacing: 0.05em; margin: 8px 0 6px; }\n            .ffc-modus-btn { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: #fff !important; padding: 10px 14px; border-radius: 8px; font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; text-align: left; margin-bottom: 7px; }\n            .ffc-modus-btn:hover { border-color: var(--ff-red, #CC0000); background: rgba(204,0,0,0.15); }\n            .ffc-modus-btn .sub { font-size: 11px; font-weight: 400; color: var(--ff-text-muted, #a0b0c8) !important; }\n            .ffc-modus-btn .haken { flex-shrink: 0; }\n\n            .ffc-eintrag-wrap { width: 100%; margin-bottom: 12px; }\n            .ffc-name-input { width: 100%; box-sizing: border-box; padding: 10px 14px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.25) !important; background: rgba(255,255,255,0.08) !important; color: #fff !important; font-size: 14px; font-family: inherit; margin-bottom: 8px; text-align: center; }\n            .ffc-name-input::placeholder { color: var(--ff-text-muted, #a0b0c8) !important; }\n            .ffc-btn-klein { padding: 8px 20px; font-size: 13px; }\n            .ffc-eintrag-status { font-size: 12px; color: gold !important; margin-top: 6px; min-height: 16px; }\n\n            .ffc-tab-reihe { display: flex; gap: 6px; margin-bottom: 8px; justify-content: center; flex-wrap: wrap; }\n            .ffc-tab-btn { background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.2); color: var(--ff-text-muted, #a0b0c8) !important; padding: 4px 10px; border-radius: 20px; font-size: 12px; font-weight: 700; cursor: pointer; font-family: inherit; }\n            .ffc-tab-btn.aktiv { background: gold; border-color: gold; color: #1C2B4B !important; }\n            .ffc-rang-zeile { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 13px; color: #fff !important; }\n            .ffc-rang-platz { width: 20px; font-weight: 700; color: gold !important; text-align: right; }\n            .ffc-rang-name { flex: 1; }\n            .ffc-rang-score { font-weight: 700; }\n            .ffc-rang-leer { font-size: 12px; color: var(--ff-text-muted, #a0b0c8) !important; text-align: center; }\n            .ffc-rang-liste { width: 100%; max-height: 260px; overflow-y: auto; margin-bottom: 12px; }\n        <\/style>\n\n        <div class=\"ffc-box\">\n            <div class=\"ffc-title\">\ud83d\udea8 Einsatzfahrt 3D<\/div>\n            <div class=\"ffc-untertitel\">Mit Blaulicht durchs Dorf \u2013 lenken, Gas geben, ausweichen!<\/div>\n            <button class=\"ffc-rang-btn ffc-rang-oeffnen-btn\" type=\"button\">\ud83c\udfc6 Rangliste (Endlos-Fahrt)<\/button>\n\n            <div class=\"ffc-spielfeld\">\n                <div class=\"ffc-canvas-wrap\">\n                    <canvas class=\"ffc-canvas\" width=\"360\" height=\"480\"><\/canvas>\n                    <div class=\"ffc-canvas-leiste\">\n                        <div class=\"ffc-blaulicht-indikator\" title=\"Blaulicht aktiv\">\ud83d\udea8<\/div>\n                    <\/div>\n                <\/div>\n\n                <div class=\"ffc-steuerung\">\n                    <div class=\"ffc-joystick\">\n                        <div class=\"ffc-stick\">\ud83d\ude92<\/div>\n                    <\/div>\n                    <button class=\"ffc-sound-btn\" type=\"button\" title=\"Martinshorn an\/aus\">\n                        \ud83d\udd07<span class=\"ffc-horn-label\">Horn<\/span>\n                    <\/button>\n                    <div class=\"ffc-joystick-hinweis\">\n                        \u2b05\ufe0f\u27a1\ufe0f lenken<br>\n                        \u2b06\ufe0f Gas geben<br>\n                        \u2b07\ufe0f bremsen\n                    <\/div>\n                <\/div>\n\n                <!-- START \/ MODUSWAHL -->\n                <div class=\"ffc-overlay ffc-start\">\n                    <h3>Bereit zur Einsatzfahrt?<\/h3>\n                    <p>Steuert alles \u00fcber den Joystick: nach links\/rechts lenken, nach oben Gas\n                    geben, nach unten bremsen (am PC gehen auch die Pfeiltasten). Weicht Autos,\n                    Fu\u00dfg\u00e4ngern und Radfahrern aus - ein Crash kostet Tempo und Punkte!<\/p>\n\n                    <div class=\"ffc-modus-titel\">Altersstufe<\/div>\n                    <div class=\"ffc-tier-chips\">\n                        <button class=\"ffc-tier-chip\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerg<\/button>\n                        <button class=\"ffc-tier-chip\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend<\/button>\n                        <button class=\"ffc-tier-chip aktiv\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene<\/button>\n                    <\/div>\n\n                    <div class=\"ffc-modus-titel\">Endlos-Fahrt<\/div>\n                    <button class=\"ffc-modus-btn ffc-endlos-btn\" type=\"button\">\n                        <span>\ud83c\udfc1 Endlos-Fahrt (90s) <span class=\"sub\">Strecke + \u00dcberholbonus \u2192 Rangliste<\/span><\/span>\n                    <\/button>\n\n                    <div class=\"ffc-modus-titel\">Missionen<\/div>\n                    <div class=\"ffc-missionen-liste\"><\/div>\n                <\/div>\n\n                <!-- ENDE -->\n                <div class=\"ffc-overlay ffc-ende\" style=\"display:none;\">\n                    <h3 class=\"ffc-endtitel\"><\/h3>\n                    <div class=\"ffc-ergebnis ffc-endtext\"><\/div>\n                    <div class=\"ffc-eintrag-wrap ffc-eintrag-bereich\" style=\"display:none;\">\n                        <input type=\"text\" class=\"ffc-name-input\" maxlength=\"20\" placeholder=\"Dein Name f\u00fcr die Rangliste\">\n                        <button class=\"ffc-btn ffc-btn-klein ffc-eintrag-btn\" type=\"button\">In Rangliste eintragen<\/button>\n                        <div class=\"ffc-eintrag-status\"><\/div>\n                    <\/div>\n                    <button class=\"ffc-btn ffc-neustart-btn\" type=\"button\">Zur\u00fcck zur Auswahl<\/button>\n                <\/div>\n\n                <!-- RANGLISTE -->\n                <div class=\"ffc-overlay ffc-rangliste-overlay\" style=\"display:none;\">\n                    <h3>\ud83c\udfc6 Rangliste \u2013 Endlos-Fahrt<\/h3>\n                    <div class=\"ffc-tab-reihe ffc-voll-tabs\">\n                        <button class=\"ffc-tab-btn\" data-stufe=\"loeschzwerg\" type=\"button\">\ud83d\udc76 L\u00f6schzwerge<\/button>\n                        <button class=\"ffc-tab-btn\" data-stufe=\"jugend\" type=\"button\">\ud83e\uddd2 Jugend<\/button>\n                        <button class=\"ffc-tab-btn\" data-stufe=\"erwachsene\" type=\"button\">\ud83d\ude92 Erwachsene<\/button>\n                    <\/div>\n                    <div class=\"ffc-rang-liste ffc-rang-liste-inhalt\">L\u00e4dt \u2026<\/div>\n                    <button class=\"ffc-btn ffc-rang-schliessen-btn\" type=\"button\">Schlie\u00dfen<\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var wrap = document.getElementById('ffc-wrap-1');\n        if (!wrap) return;\n\n        var NONCE   = '7d28bacb72';\n        var AJAXURL = 'https:\/\/ff-willmatshofen.de\/wp-admin\/admin-ajax.php';\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n        function ffsSpielerId() {\n            var id = null;\n            try { id = localStorage.getItem('ffs_player_id'); } catch (e) {}\n            if (!id) {\n                id = (window.crypto && crypto.randomUUID) ? crypto.randomUUID() : ('id-' + Date.now() + '-' + Math.random().toString(16).slice(2));\n                try { localStorage.setItem('ffs_player_id', id); } catch (e) {}\n            }\n            return id;\n        }\n\n        \/\/ ============ Konfiguration ============\n        var TIERS = {\n            loeschzwerg: { maxTempo: 16,   verkehr: 0.55, fussgaenger: 0.4 },  \/\/ ~58 km\/h\n            jugend:      { maxTempo: 20.5, verkehr: 0.8,  fussgaenger: 0.7 },  \/\/ ~74 km\/h\n            erwachsene:  { maxTempo: 25,   verkehr: 1.0,  fussgaenger: 1.0 }   \/\/ 90 km\/h max\n        };\n        var MISSIONEN = [\n            { id: 'm1', titel: '\ud83c\udfc1 Zum Einsatzort!', sub: '1100 m in 60 Sekunden', ziel: 'strecke', streckeZiel: 1100, zeitLimit: 60, nacht: false },\n            { id: 'm2', titel: '\ud83d\udee1\ufe0f Ohne Kratzer', sub: '45 Sekunden ohne Crash', ziel: 'ohnecrash', zeitLimit: 45, nacht: false },\n            { id: 'm3', titel: '\ud83d\ude97 \u00dcberholman\u00f6ver', sub: '8 Fahrzeuge \u00fcberholen (max. 90s)', ziel: 'ueberholen', anzahl: 8, zeitLimit: 90, nacht: false },\n            { id: 'm4', titel: '\ud83d\udeb8 Achtung, Fu\u00dfg\u00e4nger!', sub: '1200 m ohne Personen-Crash', ziel: 'ped', streckeZiel: 1200, zeitLimit: 90, nacht: false },\n            { id: 'm5', titel: '\ud83c\udf19 Nachteinsatz', sub: '1300 m in 75 Sekunden bei Nacht', ziel: 'strecke', streckeZiel: 1300, zeitLimit: 75, nacht: true },\n            { id: 'm6', titel: '\ud83d\udca7 Hydrantenmeister', sub: '5 Hydranten einsammeln in 80s', ziel: 'hydrant', anzahl: 5, zeitLimit: 80, nacht: false, kinder: true },\n            { id: 'm7', titel: '\ud83d\udc08 Katze retten', sub: 'Katze am Baum finden in 70s', ziel: 'katze', anzahl: 1, zeitLimit: 70, nacht: false, kinder: true },\n            { id: 'm8', titel: '\ud83d\udea8 Blaulicht-Start', sub: 'Horn nutzen und 400 m fahren', ziel: 'blaulicht', streckeZiel: 400, zeitLimit: 60, nacht: false, kinder: true }\n        ];\n\n        function missionSkalieren(m) {\n            var c = JSON.parse(JSON.stringify(m));\n            if (tier === 'loeschzwerg') {\n                if (c.streckeZiel) c.streckeZiel = Math.round(c.streckeZiel * 0.60);\n                if (c.anzahl) c.anzahl = Math.max(1, Math.ceil(c.anzahl * 0.45));\n                c.zeitLimit = Math.round(c.zeitLimit * 1.25);\n            } else if (tier === 'jugend') {\n                if (c.streckeZiel) c.streckeZiel = Math.round(c.streckeZiel * 0.80);\n                if (c.anzahl) c.anzahl = Math.max(1, Math.ceil(c.anzahl * 0.70));\n                c.zeitLimit = Math.round(c.zeitLimit * 1.10);\n            }\n            return c;\n        }\n        var BANNER_TEXTE = ['FF Willmatshofen', 'Werde L\u00f6schzwerg!', 'Notruf 112', 'Freiwillige Feuerwehr', 'Jugendfeuerwehr'];\n\n        \/\/ ============ Elemente ============\n        var canvas = wrap.querySelector('.ffc-canvas');\n        var ctx = canvas.getContext('2d');\n        var W = canvas.width, H = canvas.height;\n        var HORIZON = 175;\n\n        var startOverlay = wrap.querySelector('.ffc-start');\n        var endeOverlay = wrap.querySelector('.ffc-ende');\n        var ranglisteOverlay = wrap.querySelector('.ffc-rangliste-overlay');\n        var endtitelEl = wrap.querySelector('.ffc-endtitel');\n        var endtextEl = wrap.querySelector('.ffc-endtext');\n        var eintragBereich = wrap.querySelector('.ffc-eintrag-bereich');\n        var nameInput = wrap.querySelector('.ffc-name-input');\n        var eintragBtn = wrap.querySelector('.ffc-eintrag-btn');\n        var eintragStatus = wrap.querySelector('.ffc-eintrag-status');\n        var soundBtn = wrap.querySelector('.ffc-sound-btn');\n        var missionenListe = wrap.querySelector('.ffc-missionen-liste');\n        var vollRangInhalt = wrap.querySelector('.ffc-rang-liste-inhalt');\n\n        \/\/ ============ Zustand ============\n        var laeuft = false;\n        var modus = null;         \/\/ 'endlos' oder Missions-Objekt\n        var tier = 'erwachsene';\n        var playerX = 0;          \/\/ -1.35 .. 1.35 (Stra\u00dfenbreite = \u00b11)\n        var tempo = 0;            \/\/ m\/s\n        var position = 0;         \/\/ gefahrene Meter\n        var restZeit = 0;\n        var ueberholt = 0;\n        var crashes = 0;\n        var personenCrash = false;\n        var unverwundbarBis = 0;\n        var blitzBis = 0;\n        var entities = [];        \/\/ {typ:'auto'|'ped'|'rad'|'banner'|'bruecke', z, x, ...}\n        var naechsterSpawnZ = 120;\n        var naechsterBannerZ = 200;\n        var naechsteBrueckeZ = 600;\n        var naechstesHausZ = 35;\n        var naechsteLaterneZ = 35;\n        var naechsterBaumZ = 38;\n        var naechsteKircheZ = 700;\n        var naechsterHydrantZ = 180;\n        var naechsteKatzeZ = 650;\n        var ortsschildGesetzt = false;\n        var feuerwehrhausGesetzt = false;\n        var hyd = 0;\n        var katze = 0;\n        var blaulichtSek = 0;\n        var rotlicht = 0;\n        var letzterFrame = 0;\n        var animId = null;\n        var input = { steer: 0, accel: 0 }; \/\/ steer: -1..1 (links\/rechts), accel: -1..1 (Bremse\/Gas)\n        var nachtModus = false;\n\n        \/\/ ============ Sound (Martinshorn) ============\n        var audioCtx = null, oszillator = null, gainNode = null, hornTimer = null, hornAn = false, tonHoch = false;\n        function hornStart() {\n            try {\n                if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();\n                if (audioCtx.state === 'suspended') audioCtx.resume();\n                if (oszillator) return;\n                oszillator = audioCtx.createOscillator();\n                gainNode = audioCtx.createGain();\n                gainNode.gain.value = 0.04;\n                oszillator.type = 'sawtooth';\n                oszillator.frequency.value = 420;\n                oszillator.connect(gainNode);\n                gainNode.connect(audioCtx.destination);\n                oszillator.start();\n                hornTimer = setInterval(function() {\n                    tonHoch = !tonHoch;\n                    if (oszillator) oszillator.frequency.setValueAtTime(tonHoch ? 560 : 420, audioCtx.currentTime);\n                }, 600);\n            } catch (e) {}\n        }\n        function hornStop() {\n            clearInterval(hornTimer);\n            try { if (oszillator) { oszillator.stop(); oszillator.disconnect(); } } catch (e) {}\n            oszillator = null;\n        }\n        soundBtn.addEventListener('click', function() {\n            hornAn = !hornAn;\n            soundBtn.textContent = hornAn ? '\ud83d\udcef' : '\ud83d\udd07';\n            soundBtn.classList.toggle('an', hornAn);\n            if (!hornAn) { hornStop(); return; }\n\n            \/\/ Sofort starten - im Spiel dauerhaft, im Men\u00fc als kurze H\u00f6rprobe,\n            \/\/ damit direkt klar ist, dass der Ton funktioniert.\n            hornStart();\n            if (!laeuft) {\n                setTimeout(function() { if (!laeuft) hornStop(); }, 1500);\n            }\n        });\n        document.addEventListener('visibilitychange', function() { if (document.hidden) hornStop(); });\n\n        \/\/ ============ Missionen: Fortschritt ============\n        function missionenGeschafft() {\n            try { return JSON.parse(localStorage.getItem('ff_einsatzfahrt_missionen') || '{}'); } catch (e) { return {}; }\n        }\n        function missionSpeichern(id) {\n            try {\n                var m = missionenGeschafft();\n                m[id] = true;\n                localStorage.setItem('ff_einsatzfahrt_missionen', JSON.stringify(m));\n            } catch (e) {}\n            var anzahl = Object.keys(missionenGeschafft()).length;\n            var abzeichen = anzahl >= 5 ? 'gold' : (anzahl >= 3 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('einsatzfahrt', abzeichen);\n        }\n        function missionenAnzeigen() {\n            var geschafft = missionenGeschafft();\n            missionenListe.innerHTML = '';\n            MISSIONEN.forEach(function(m) {\n                if (m.kinder && tier === 'erwachsene') return; \/\/ Kinder-Missionen nur f\u00fcr j\u00fcngere\n                var skaliert = missionSkalieren(m);\n                var sub = m.sub;\n                if (tier !== 'erwachsene') {\n                    \/\/ Zeige skalierte Werte\n                    if (skaliert.streckeZiel) sub = skaliert.streckeZiel + ' m in ' + skaliert.zeitLimit + 's';\n                    else if (skaliert.anzahl) sub = skaliert.anzahl + ' \u00d7 in ' + skaliert.zeitLimit + 's';\n                    else sub = skaliert.zeitLimit + 's';\n                }\n                var btn = document.createElement('button');\n                btn.type = 'button';\n                btn.className = 'ffc-modus-btn';\n                btn.innerHTML = '<span>' + m.titel + ' <span class=\"sub\">' + sub + '<\/span><\/span>' +\n                    '<span class=\"haken\">' + (geschafft[m.id] ? '\u2705' : '') + '<\/span>';\n                btn.addEventListener('click', function() { spielStart(skaliert); });\n                missionenListe.appendChild(btn);\n            });\n        }\n\n        \/\/ ============ Spiel-Logik ============\n        function kurveBei(z) {\n            \/\/ Sanfte, deterministische Kurvenfolge aus Sinus-\u00dcberlagerung\n            return Math.sin(z * 0.004) * 1.6 + Math.sin(z * 0.0013 + 2) * 1.1;\n        }\n\n        function spawneVerkehr(dt) {\n            var c = TIERS[tier];\n            if (position + 300 > naechsterSpawnZ) {\n                var abstand = (140 - tempo) \/ c.verkehr;\n                naechsterSpawnZ = position + 300 + Math.max(60, abstand + Math.random() * 80);\n                \/\/ Gegenverkehr: 18% (L\u00f6schzwerg), 30% (Jugend), 45% (Erwachsene)\n                var gegChance = tier === 'loeschzwerg' ? 0.18 : (tier === 'jugend' ? 0.30 : 0.45);\n                var gegenverkehr = Math.random() < gegChance;\n                entities.push({\n                    typ: 'auto', gegenverkehr: gegenverkehr,\n                    z: position + (gegenverkehr ? 530 : 320),\n                    basisX: gegenverkehr ? -0.55 : 0.55,\n                    x: gegenverkehr ? -0.55 : 0.55,\n                    tempo: gegenverkehr ? (13 + Math.random() * 6) : (6 + Math.random() * 7),\n                    farbe: ['#d94a4a','#4a7bd9','#4ad96b','#d9c94a','#9a4ad9','#eeeeee'][Math.floor(Math.random()*6)],\n                    ueberholtZaehlt: false, getroffen: false\n                });\n            }\n            if (Math.random() < 0.006 * c.fussgaenger * dt * 60) {\n                var vonLinks = Math.random() < 0.5;\n                entities.push({ typ: Math.random() < 0.5 ? 'ped' : 'rad', z: position + 180 + Math.random() * 140, x: vonLinks ? -1.5 : 1.5, richtung: vonLinks ? 1 : -1, getroffen: false });\n            }\n            if (position + 350 > naechsterBannerZ) {\n                naechsterBannerZ = position + 350 + 160 + Math.random() * 120;\n                entities.push({ typ: 'banner', z: naechsterBannerZ, x: (Math.random() < 0.5 ? -1.6 : 1.6), text: BANNER_TEXTE[Math.floor(Math.random() * BANNER_TEXTE.length)] });\n            }\n            if (position + 400 > naechsteBrueckeZ) {\n                naechsteBrueckeZ = position + 400 + 550 + Math.random() * 300;\n                entities.push({ typ: 'bruecke', z: naechsteBrueckeZ, text: 'FF WILLMATSHOFEN' });\n            }\n\n            \/\/ ---- Dorf-Kulisse ----\n            if (!feuerwehrhausGesetzt) {\n                feuerwehrhausGesetzt = true;\n                entities.push({ typ: 'feuerwehrhaus', z: 55, x: -1.95 });\n                entities.push({ typ: 'ortsschild', z: position + 120, x: 1.7 });\n            }\n            \/\/ Einsatzstelle am Streckenende anzeigen (nur bei Strecken-Missionen)\n            if (modus && modus !== 'endlos' && modus.streckeZiel && !modus._einsatzstelleGesetzt) {\n                modus._einsatzstelleGesetzt = true;\n                entities.push({ typ: 'einsatzstelle', z: modus.streckeZiel, x: 0 });\n            }\n            \/\/ H\u00e4user auf BEIDEN Seiten dichter\n            if (position + 320 > naechstesHausZ) {\n                naechstesHausZ = position + 320 + 38 + Math.random() * 48;\n                for (var h = 0; h < 2; h++) {\n                    var seite = h === 0 ? -1 : 1;\n                    entities.push({\n                        typ: 'haus', z: naechstesHausZ + h * 18 + Math.random() * 18,\n                        x: seite * (1.85 + Math.random() * 0.55),\n                        farbe: ['#e8d8b0','#d8c8a8','#e0e0e0','#d4b896','#c8d8e0'][Math.floor(Math.random() * 5)],\n                        dach: ['#a0522d','#8b4040','#705048'][Math.floor(Math.random() * 3)],\n                        breite: 0.85 + Math.random() * 0.65,\n                        stockwerke: 1 + Math.floor(Math.random() * 3)\n                    });\n                }\n            }\n            if (position + 320 > naechsteLaterneZ) {\n                naechsteLaterneZ = position + 320 + 42;\n                entities.push({ typ: 'laterne', z: naechsteLaterneZ, x: -1.45 });\n                entities.push({ typ: 'laterne', z: naechsteLaterneZ + 12, x: 1.45 });\n            }\n            if (position + 320 > naechsterBaumZ) {\n                naechsterBaumZ = position + 320 + 30 + Math.random() * 60;\n                for (var b = 0; b < 4; b++) entities.push({ typ: 'baum', z: naechsterBaumZ + b * 15 + Math.random() * 14, x: (Math.random() < 0.5 ? -1 : 1) * (1.65 + Math.random()), groesse: 0.8 + Math.random() * 0.7 });\n            }\n            if (position + 400 > naechsteKircheZ) {\n                naechsteKircheZ = position + 400 + 1000 + Math.random() * 420;\n                entities.push({ typ: 'kirche', z: naechsteKircheZ, x: (Math.random() < 0.5 ? -2.6 : 2.6) });\n            }\n            \/\/ Hydranten und Katze nur bei entsprechenden Missionen\n            if (modus && modus.ziel === 'hydrant' && position + 260 > naechsterHydrantZ) {\n                naechsterHydrantZ = position + 260 + 120 + Math.random() * 110;\n                entities.push({ typ: 'hydrant_sammel', z: naechsterHydrantZ, x: Math.random() < 0.5 ? -0.85 : 0.85, getroffen: false });\n            }\n            if (modus && modus.ziel === 'katze' && position + 320 > naechsteKatzeZ) {\n                naechsteKatzeZ = position + 99999; \/\/ nur einmal\n                entities.push({ typ: 'katze', z: position + 520, x: Math.random() < 0.5 ? -1.7 : 1.7, getroffen: false });\n            }\n        }\n\n        function update(dt) {\n            var c = TIERS[tier];\n\n            \/\/ Fahrphysik (analog \u00fcber Joystick: accel > 0 = Gas, < 0 = Bremse)\n            if (input.accel > 0.1) tempo += 14 * input.accel * dt;\n            else if (input.accel < -0.1) tempo += 34 * input.accel * dt;\n            else tempo -= 5 * dt;\n            tempo = Math.max(0, Math.min(c.maxTempo, tempo));\n\n            var kurve = kurveBei(position);\n            var tempoFaktor = tempo \/ c.maxTempo;\n            playerX += input.steer * 2.2 * dt;\n            playerX -= kurve * 0.35 * tempoFaktor * dt; \/\/ Kurve dr\u00fcckt nach au\u00dfen\n            playerX = Math.max(-1.35, Math.min(1.35, playerX));\n\n            \/\/ Abseits der Stra\u00dfe: stark bremsen\n            if (Math.abs(playerX) > 1.05) tempo = Math.max(0, tempo - 25 * dt);\n\n            position += tempo * dt;\n\n            spawneVerkehr(dt);\n\n            var jetzt = performance.now();\n            if (hornAn) blaulichtSek += dt;\n\n            entities.forEach(function(e) {\n                var d = e.z - position;\n                if (e.typ === 'auto') {\n                    \/\/ Gegenverkehr bewegt sich entgegen, Gleichverkehr vor uns her\n                    var near = hornAn && d > 0 && d < 150;\n                    var target = typeof e.basisX === 'number' ? e.basisX : (e.gegenverkehr ? -0.55 : 0.55);\n                    if (near) target = e.gegenverkehr ? -0.98 : 0.98; \/\/ ausweichen\n                    e.x += (target - e.x) * Math.min(1, dt * 2.2);\n                    e.z += (e.gegenverkehr ? -e.tempo : e.tempo) * dt;\n                }\n                if (e.typ === 'ped') e.x += e.richtung * 0.22 * dt;\n                if (e.typ === 'rad') e.x += e.richtung * 0.45 * dt;\n\n                \/\/ \u00dcberholt (nur Gleichverkehr)?\n                if (e.typ === 'auto' && !e.gegenverkehr && !e.ueberholtZaehlt && d < -2) {\n                    e.ueberholtZaehlt = true;\n                    if (!e.getroffen) ueberholt++;\n                }\n\n                \/\/ Hydrant oder Katze einsammeln\n                if ((e.typ === 'hydrant_sammel' || e.typ === 'katze') && !e.getroffen && d > 0 && d < 8 && Math.abs(e.x - playerX) < 0.55) {\n                    e.getroffen = true;\n                    if (e.typ === 'hydrant_sammel') hyd++;\n                    if (e.typ === 'katze') katze++;\n                    tempo = Math.min(c.maxTempo, tempo + 3);\n                }\n\n                \/\/ Kollision\n                if (!e.getroffen && d > 0 && d < 7 && jetzt > unverwundbarBis) {\n                    var breite = (e.typ === 'auto') ? 0.5 : 0.3;\n                    if ((e.typ === 'auto' || e.typ === 'ped' || e.typ === 'rad') && Math.abs(e.x - playerX) < breite) {\n                        e.getroffen = true;\n                        crashes++;\n                        if (e.typ === 'ped' || e.typ === 'rad') personenCrash = true;\n                        tempo *= 0.25;\n                        position = Math.max(0, position - 15);\n                        unverwundbarBis = jetzt + 1200;\n                        blitzBis = jetzt + 350;\n                    }\n                }\n            });\n            entities = entities.filter(function(e) {\n                if ((e.typ === 'hydrant_sammel' || e.typ === 'katze') && e.getroffen) return false;\n                return e.z - position > -45;\n            });\n\n            \/\/ Zeit + Missionsziele\n            restZeit -= dt;\n            if (restZeit <= 0) {\n                if (modus === 'endlos') { spielEnde(); }\n                else if (modus.ziel === 'ohnecrash') { spielEnde(crashes === 0); }\n                else { spielEnde(false); }\n                return;\n            }\n\n            if (modus !== 'endlos') {\n                var m = modus;\n                if (m.ziel === 'strecke' && position >= m.streckeZiel) { spielEnde(true); return; }\n                if (m.ziel === 'ohnecrash' && crashes > 0) { spielEnde(false); return; }\n                if (m.ziel === 'ueberholen' && ueberholt >= m.anzahl) { spielEnde(true); return; }\n                if (m.ziel === 'ped') {\n                    if (personenCrash) { spielEnde(false); return; }\n                    if (position >= m.streckeZiel) { spielEnde(true); return; }\n                }\n                if (m.ziel === 'hydrant' && hyd >= m.anzahl) { spielEnde(true); return; }\n                if (m.ziel === 'katze' && katze >= 1) { spielEnde(true); return; }\n                if (m.ziel === 'blaulicht' && position >= m.streckeZiel && blaulichtSek >= 5) { spielEnde(true); return; }\n            }\n        }\n\n        \/\/ ============ Rendering ============\n        function projektion(d) {\n            \/\/ d = Distanz vor dem Fahrzeug (m). Liefert {s: Skala 0..1, y: Bildschirm-Y}\n            var s = 1 \/ (1 + d * 0.02);\n            return { s: s, y: HORIZON + (H - HORIZON) * s };\n        }\n        function strassenHalbBreite(s) { return 150 * s; }\n        function kurvenVersatz(s) {\n            return kurveBei(position) * Math.pow(1 - s, 2) * 260;\n        }\n\n        function zeichnen() {\n            var jetzt = performance.now();\n\n            \/\/ Himmel mit Verlauf\n            var himmel = ctx.createLinearGradient(0, 0, 0, HORIZON);\n            if (nachtModus) {\n                himmel.addColorStop(0, '#060a20');\n                himmel.addColorStop(1, '#1a2448');\n            } else {\n                himmel.addColorStop(0, '#4aa8f0');\n                himmel.addColorStop(1, '#b8e0ff');\n            }\n            ctx.fillStyle = himmel;\n            ctx.fillRect(0, 0, W, HORIZON);\n\n            \/\/ Sonne\/Mond\n            ctx.fillStyle = nachtModus ? '#e8e8d0' : '#ffe07a';\n            ctx.beginPath();\n            ctx.arc(W - 60, 46, 22, 0, Math.PI * 2);\n            ctx.fill();\n\n            \/\/ Sterne bei Nacht\n            if (nachtModus) {\n                ctx.fillStyle = 'rgba(255,255,255,0.7)';\n                for (var st = 0; st < 18; st++) {\n                    ctx.fillRect((st * 73 + 31) % W, (st * 41 + 13) % (HORIZON - 40), 2, 2);\n                }\n            }\n\n            \/\/ H\u00fcgelkette am Horizont (bewegt sich langsam mit)\n            ctx.fillStyle = nachtModus ? '#131c36' : '#5aa860';\n            ctx.beginPath();\n            ctx.moveTo(0, HORIZON);\n            for (var hx = 0; hx <= W; hx += 8) {\n                var hoehe = Math.sin((hx + position * 0.15) * 0.018) * 14 + Math.sin((hx + position * 0.15) * 0.007 + 3) * 10;\n                ctx.lineTo(hx, HORIZON - 16 - hoehe);\n            }\n            ctx.lineTo(W, HORIZON);\n            ctx.closePath();\n            ctx.fill();\n\n            \/\/ Wolken (ziehen langsam)\n            if (!nachtModus) {\n                ctx.fillStyle = 'rgba(255,255,255,0.85)';\n                for (var wo = 0; wo < 3; wo++) {\n                    var wx = ((wo * 150 + 40 - position * 0.08) % (W + 120) + W + 120) % (W + 120) - 60;\n                    var wy = 34 + wo * 26;\n                    ctx.beginPath();\n                    ctx.arc(wx, wy, 15, 0, Math.PI * 2);\n                    ctx.arc(wx + 18, wy - 5, 12, 0, Math.PI * 2);\n                    ctx.arc(wx + 34, wy, 13, 0, Math.PI * 2);\n                    ctx.fill();\n                }\n            }\n\n            \/\/ Boden (Gras, zweifarbig gestreift f\u00fcr Bewegungsgef\u00fchl)\n            ctx.fillStyle = nachtModus ? '#0f2416' : '#3f9e4d';\n            ctx.fillRect(0, HORIZON, W, H - HORIZON);\n\n            \/\/ Stra\u00dfe in Streifen von hinten (klein) nach vorn (gro\u00df)\n            var streifen = 70;\n            for (var i = 0; i < streifen; i++) {\n                var t1 = i \/ streifen, t2 = (i + 1) \/ streifen;\n                var s1 = 0.06 + t1 * 0.94, s2 = 0.06 + t2 * 0.94;\n                var y1 = HORIZON + (H - HORIZON) * s1;\n                var y2 = HORIZON + (H - HORIZON) * s2;\n                var hb1 = strassenHalbBreite(s1), hb2 = strassenHalbBreite(s2);\n                var kv1 = kurvenVersatz(s1), kv2 = kurvenVersatz(s2);\n                var cx1 = W \/ 2 + kv1 - playerX * hb1;\n                var cx2 = W \/ 2 + kv2 - playerX * hb2;\n\n                var d1 = (1 \/ s1 - 1) \/ 0.02;\n                var welt = Math.floor((position + d1) \/ 6);\n                var hell = welt % 2 === 0;\n\n                \/\/ Gras-Streifen (volle Breite, unter der Stra\u00dfe)\n                ctx.fillStyle = nachtModus ? (hell ? '#10281a' : '#0d2015') : (hell ? '#46aa55' : '#3c9448');\n                ctx.fillRect(0, y1, W, y2 - y1 + 1);\n\n                ctx.fillStyle = nachtModus ? (hell ? '#2a2a34' : '#24242e') : (hell ? '#8a8a94' : '#80808a');\n                ctx.beginPath();\n                ctx.moveTo(cx1 - hb1, y1);\n                ctx.lineTo(cx1 + hb1, y1);\n                ctx.lineTo(cx2 + hb2, y2);\n                ctx.lineTo(cx2 - hb2, y2);\n                ctx.closePath();\n                ctx.fill();\n\n                \/\/ Randstreifen\n                ctx.fillStyle = hell ? '#e5e5e5' : (nachtModus ? '#888' : '#cc4444');\n                ctx.fillRect(cx1 - hb1 - 4 * s1, y1, 4 * s1, y2 - y1 + 1);\n                ctx.fillRect(cx1 + hb1, y1, 4 * s1, y2 - y1 + 1);\n\n                \/\/ Mittellinie\n                if (hell) {\n                    ctx.fillStyle = '#fff';\n                    ctx.fillRect(cx1 - 2 * s1, y1, 4 * s1, y2 - y1 + 1);\n                }\n            }\n\n            \/\/ Entities von hinten nach vorn\n            var sichtbar = entities.filter(function(e) { var d = e.z - position; return d > 0 && d < 320; });\n            sichtbar.sort(function(a, b) { return (b.z - position) - (a.z - position); });\n            sichtbar.forEach(function(e) {\n                var d = e.z - position;\n                var p = projektion(d);\n                var hb = strassenHalbBreite(p.s);\n                var kv = kurvenVersatz(p.s);\n                var cx = W \/ 2 + kv - playerX * hb;\n\n                if (e.typ === 'bruecke') {\n                    var pfeilerH = 90 * p.s * 2.4;\n                    var bh = 26 * p.s * 3;\n                    ctx.fillStyle = '#8a5a2a';\n                    ctx.fillRect(cx - hb - 12 * p.s, p.y - pfeilerH, 10 * p.s * 2, pfeilerH);\n                    ctx.fillRect(cx + hb + 2 * p.s, p.y - pfeilerH, 10 * p.s * 2, pfeilerH);\n                    ctx.fillStyle = '#CC0000';\n                    ctx.fillRect(cx - hb - 12 * p.s, p.y - pfeilerH, hb * 2 + 24 * p.s, bh);\n                    if (p.s > 0.22) {\n                        ctx.fillStyle = '#fff';\n                        ctx.font = '700 ' + Math.max(8, 18 * p.s * 2.2) + 'px Oswald, sans-serif';\n                        ctx.textAlign = 'center';\n                        ctx.fillText(e.text, cx, p.y - pfeilerH + bh * 0.72);\n                    }\n                    return;\n                }\n\n                if (e.typ === 'banner') {\n                    var bx = cx + e.x * hb;\n                    var stangeH = 70 * p.s * 1.6;\n                    var bw = 120 * p.s * 1.6, bhh = 44 * p.s * 1.6;\n                    ctx.fillStyle = '#6a6a6a';\n                    ctx.fillRect(bx - 3 * p.s, p.y - stangeH, 6 * p.s, stangeH);\n                    ctx.fillStyle = '#1C2B4B';\n                    ctx.fillRect(bx - bw \/ 2, p.y - stangeH - bhh, bw, bhh);\n                    ctx.strokeStyle = '#CC0000';\n                    ctx.lineWidth = Math.max(1, 3 * p.s);\n                    ctx.strokeRect(bx - bw \/ 2, p.y - stangeH - bhh, bw, bhh);\n                    if (p.s > 0.25) {\n                        ctx.fillStyle = '#fff';\n                        ctx.font = '700 ' + Math.max(7, 13 * p.s * 1.7) + 'px Oswald, sans-serif';\n                        ctx.textAlign = 'center';\n                        ctx.fillText(e.text, bx, p.y - stangeH - bhh * 0.35);\n                    }\n                    return;\n                }\n\n                if (e.typ === 'feuerwehrhaus') {\n                    var fx = cx + e.x * hb;\n                    ctx.fillStyle = '#b00000';\n                    ctx.fillRect(fx - 74 * p.s, p.y - 90 * p.s, 148 * p.s, 90 * p.s);\n                    ctx.fillStyle = '#fff';\n                    ctx.fillRect(fx - 32 * p.s, p.y - 42 * p.s, 64 * p.s, 42 * p.s);\n                    ctx.fillStyle = '#1C2B4B';\n                    ctx.fillRect(fx - 25 * p.s, p.y - 35 * p.s, 50 * p.s, 35 * p.s);\n                    if (p.s > 0.18) {\n                        ctx.fillStyle = '#fff';\n                        ctx.font = '700 ' + Math.max(8, 22 * p.s) + 'px Oswald, sans-serif';\n                        ctx.textAlign = 'center';\n                        ctx.fillText('FEUERWEHR', fx, p.y - 62 * p.s);\n                    }\n                    return;\n                }\n\n                if (e.typ === 'einsatzstelle') {\n                    ctx.fillStyle = 'rgba(255,230,0,0.85)';\n                    ctx.beginPath();\n                    ctx.ellipse(cx, p.y, hb * 0.7, 18 * p.s, 0, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.fillStyle = '#cc0000';\n                    ctx.fillRect(cx - 76 * p.s, p.y - 62 * p.s, 152 * p.s, 44 * p.s);\n                    if (p.s > 0.18) {\n                        ctx.fillStyle = '#fff';\n                        ctx.font = '700 ' + Math.max(8, 30 * p.s) + 'px Oswald, sans-serif';\n                        ctx.textAlign = 'center';\n                        ctx.fillText('EINSATZSTELLE', cx, p.y - 30 * p.s);\n                    }\n                    return;\n                }\n\n                if (e.typ === 'hydrant_sammel') {\n                    var hyx = cx + e.x * hb;\n                    ctx.fillStyle = '#cc0000';\n                    ctx.fillRect(hyx - 7 * p.s, p.y - 28 * p.s, 14 * p.s, 28 * p.s);\n                    ctx.fillRect(hyx - 15 * p.s, p.y - 22 * p.s, 30 * p.s, 8 * p.s);\n                    ctx.beginPath();\n                    ctx.arc(hyx, p.y - 30 * p.s, 9 * p.s, 0, Math.PI * 2);\n                    ctx.fill();\n                    \/\/ Glitzer-Effekt zum Einsammeln\n                    ctx.fillStyle = 'rgba(255,255,100,0.7)';\n                    ctx.beginPath();\n                    ctx.arc(hyx, p.y - 36 * p.s, 5 * p.s, 0, Math.PI * 2);\n                    ctx.fill();\n                    return;\n                }\n\n                if (e.typ === 'katze') {\n                    var kax = cx + e.x * hb;\n                    \/\/ Baum\n                    ctx.fillStyle = '#6a4a2a';\n                    ctx.fillRect(kax - 3 * p.s, p.y - 70 * p.s, 6 * p.s, 70 * p.s);\n                    ctx.fillStyle = nachtModus ? '#173d24' : '#2e7d3a';\n                    ctx.beginPath();\n                    ctx.arc(kax, p.y - 86 * p.s, 35 * p.s, 0, Math.PI * 2);\n                    ctx.fill();\n                    \/\/ Katze-Emoji\n                    ctx.globalAlpha = 1;\n                    ctx.font = Math.max(11, 30 * p.s) + 'px sans-serif';\n                    ctx.textAlign = 'center';\n                    ctx.fillStyle = '#000';\n                    ctx.fillText('\ud83d\udc08', kax, p.y - 88 * p.s);\n                    ctx.globalAlpha = 1;\n                    return;\n                }\n\n                if (e.typ === 'haus') {\n                    var hx2 = cx + e.x * hb;\n                    var stockwerke = e.stockwerke || 1;\n                    var hw = 70 * p.s * 2 * e.breite, hh = (45 + stockwerke * 18) * p.s * 2;\n                    var seite = 14 * p.s * 2;\n                    var innen = e.x < 0 ? 1 : -1;\n\n                    \/\/ Seitenwand (dunkler, leicht schr\u00e4g) f\u00fcr 3D-Wirkung\n                    ctx.fillStyle = 'rgba(0,0,0,0.28)';\n                    ctx.beginPath();\n                    ctx.moveTo(hx2 + innen * hw \/ 2, p.y - hh);\n                    ctx.lineTo(hx2 + innen * (hw \/ 2 + seite), p.y - hh + 6 * p.s);\n                    ctx.lineTo(hx2 + innen * (hw \/ 2 + seite), p.y + 6 * p.s);\n                    ctx.lineTo(hx2 + innen * hw \/ 2, p.y);\n                    ctx.closePath();\n                    ctx.fillStyle = e.farbe;\n                    ctx.fill();\n                    ctx.fillStyle = 'rgba(0,0,0,0.28)';\n                    ctx.fill();\n\n                    \/\/ Frontwand\n                    ctx.fillStyle = e.farbe;\n                    ctx.fillRect(hx2 - hw \/ 2, p.y - hh, hw, hh);\n                    \/\/ Dach\n                    ctx.fillStyle = e.dach;\n                    ctx.beginPath();\n                    ctx.moveTo(hx2 - hw \/ 2 - 5 * p.s, p.y - hh);\n                    ctx.lineTo(hx2, p.y - hh - 28 * p.s * 2);\n                    ctx.lineTo(hx2 + hw \/ 2 + 5 * p.s, p.y - hh);\n                    ctx.closePath();\n                    ctx.fill();\n                    \/\/ Dach-Schattierung (eine Seite dunkler)\n                    ctx.fillStyle = 'rgba(0,0,0,0.18)';\n                    ctx.beginPath();\n                    ctx.moveTo(hx2, p.y - hh - 28 * p.s * 2);\n                    ctx.lineTo(hx2 + hw \/ 2 + 5 * p.s, p.y - hh);\n                    ctx.lineTo(hx2, p.y - hh);\n                    ctx.closePath();\n                    ctx.fill();\n                    \/\/ Fenster + T\u00fcr\n                    if (p.s > 0.15) {\n                        ctx.fillStyle = nachtModus ? '#ffd76a' : '#5a7a9a';\n                        var fg = 12 * p.s * 2;\n                        ctx.fillRect(hx2 - hw * 0.32, p.y - hh * 0.75, fg, fg);\n                        ctx.fillRect(hx2 + hw * 0.32 - fg, p.y - hh * 0.75, fg, fg);\n                        \/\/ Fensterkreuze\n                        ctx.strokeStyle = 'rgba(255,255,255,0.5)';\n                        ctx.lineWidth = 1;\n                        ctx.beginPath();\n                        ctx.moveTo(hx2 - hw * 0.32 + fg \/ 2, p.y - hh * 0.75);\n                        ctx.lineTo(hx2 - hw * 0.32 + fg \/ 2, p.y - hh * 0.75 + fg);\n                        ctx.moveTo(hx2 + hw * 0.32 - fg \/ 2, p.y - hh * 0.75);\n                        ctx.lineTo(hx2 + hw * 0.32 - fg \/ 2, p.y - hh * 0.75 + fg);\n                        ctx.stroke();\n                        ctx.fillStyle = '#6a4a2a';\n                        ctx.fillRect(hx2 - fg \/ 2, p.y - fg * 1.6, fg, fg * 1.6);\n                    }\n                    return;\n                }\n\n                if (e.typ === 'laterne') {\n                    var lx = cx + e.x * hb;\n                    var mastH = 60 * p.s * 2;\n                    ctx.fillStyle = '#555';\n                    ctx.fillRect(lx - 2 * p.s, p.y - mastH, 4 * p.s, mastH);\n                    ctx.fillStyle = nachtModus ? '#ffe07a' : '#dddddd';\n                    ctx.beginPath();\n                    ctx.arc(lx, p.y - mastH, 6 * p.s * 1.6, 0, Math.PI * 2);\n                    ctx.fill();\n                    if (nachtModus && p.s > 0.15) {\n                        var lgrad = ctx.createRadialGradient(lx, p.y - mastH, 2, lx, p.y - mastH, 30 * p.s * 2.5);\n                        lgrad.addColorStop(0, 'rgba(255,224,122,0.35)');\n                        lgrad.addColorStop(1, 'rgba(255,224,122,0)');\n                        ctx.fillStyle = lgrad;\n                        ctx.beginPath();\n                        ctx.arc(lx, p.y - mastH * 0.6, 30 * p.s * 2.5, 0, Math.PI * 2);\n                        ctx.fill();\n                    }\n                    return;\n                }\n\n                if (e.typ === 'baum') {\n                    var bx2 = cx + e.x * hb;\n                    var stammH = 26 * p.s * 2 * e.groesse;\n                    ctx.fillStyle = '#6a4a2a';\n                    ctx.fillRect(bx2 - 3 * p.s * e.groesse, p.y - stammH, 6 * p.s * e.groesse, stammH);\n                    ctx.fillStyle = nachtModus ? '#12331e' : '#2e7d3a';\n                    ctx.beginPath();\n                    ctx.arc(bx2, p.y - stammH - 16 * p.s * 2 * e.groesse, 20 * p.s * 2 * e.groesse, 0, Math.PI * 2);\n                    ctx.fill();\n                    ctx.fillStyle = nachtModus ? '#173d24' : '#3a9448';\n                    ctx.beginPath();\n                    ctx.arc(bx2 - 8 * p.s * e.groesse, p.y - stammH - 10 * p.s * 2 * e.groesse, 13 * p.s * 2 * e.groesse, 0, Math.PI * 2);\n                    ctx.fill();\n                    return;\n                }\n\n                if (e.typ === 'ortsschild') {\n                    var ox = cx + e.x * hb;\n                    var mast2H = 50 * p.s * 2;\n                    var sw = 95 * p.s * 2, sh = 34 * p.s * 2;\n                    ctx.fillStyle = '#777';\n                    ctx.fillRect(ox - 2.5 * p.s, p.y - mast2H, 5 * p.s, mast2H);\n                    ctx.fillStyle = '#f7d94c';\n                    ctx.fillRect(ox - sw \/ 2, p.y - mast2H - sh, sw, sh);\n                    ctx.strokeStyle = '#222';\n                    ctx.lineWidth = Math.max(1, 2.5 * p.s);\n                    ctx.strokeRect(ox - sw \/ 2, p.y - mast2H - sh, sw, sh);\n                    if (p.s > 0.2) {\n                        ctx.fillStyle = '#222';\n                        ctx.font = '700 ' + Math.max(7, 12 * p.s * 2) + 'px Oswald, sans-serif';\n                        ctx.textAlign = 'center';\n                        ctx.fillText('Willmatshofen', ox, p.y - mast2H - sh * 0.35);\n                    }\n                    return;\n                }\n\n                if (e.typ === 'kirche') {\n                    var kx = cx + e.x * hb;\n                    var kw = 80 * p.s * 2.4, kh = 60 * p.s * 2.4;\n                    var turmW = 26 * p.s * 2.4, turmH = 110 * p.s * 2.4;\n                    \/\/ Kirchenschiff\n                    ctx.fillStyle = '#e8e0d0';\n                    ctx.fillRect(kx - kw \/ 2, p.y - kh, kw, kh);\n                    ctx.fillStyle = '#8b4040';\n                    ctx.beginPath();\n                    ctx.moveTo(kx - kw \/ 2 - 4 * p.s, p.y - kh);\n                    ctx.lineTo(kx, p.y - kh - 24 * p.s * 2.4);\n                    ctx.lineTo(kx + kw \/ 2 + 4 * p.s, p.y - kh);\n                    ctx.closePath();\n                    ctx.fill();\n                    \/\/ Turm (Zwiebelturm-Andeutung)\n                    var turmX = kx + kw \/ 2 - turmW \/ 2;\n                    ctx.fillStyle = '#e8e0d0';\n                    ctx.fillRect(turmX, p.y - turmH, turmW, turmH);\n                    ctx.fillStyle = '#556b2f';\n                    ctx.beginPath();\n                    ctx.arc(turmX + turmW \/ 2, p.y - turmH, turmW * 0.62, Math.PI, 0);\n                    ctx.fill();\n                    ctx.beginPath();\n                    ctx.moveTo(turmX + turmW \/ 2 - turmW * 0.25, p.y - turmH);\n                    ctx.lineTo(turmX + turmW \/ 2, p.y - turmH - 22 * p.s * 2.4);\n                    ctx.lineTo(turmX + turmW \/ 2 + turmW * 0.25, p.y - turmH);\n                    ctx.closePath();\n                    ctx.fill();\n                    \/\/ Kreuz\n                    ctx.strokeStyle = '#d4af37';\n                    ctx.lineWidth = Math.max(1, 2 * p.s);\n                    ctx.beginPath();\n                    ctx.moveTo(turmX + turmW \/ 2, p.y - turmH - 22 * p.s * 2.4 - 10 * p.s * 2);\n                    ctx.lineTo(turmX + turmW \/ 2, p.y - turmH - 22 * p.s * 2.4);\n                    ctx.moveTo(turmX + turmW \/ 2 - 4 * p.s * 2, p.y - turmH - 22 * p.s * 2.4 - 6 * p.s * 2);\n                    ctx.lineTo(turmX + turmW \/ 2 + 4 * p.s * 2, p.y - turmH - 22 * p.s * 2.4 - 6 * p.s * 2);\n                    ctx.stroke();\n                    \/\/ Kirchenfenster\n                    if (p.s > 0.15) {\n                        ctx.fillStyle = nachtModus ? '#ffd76a' : '#7a6a9a';\n                        ctx.fillRect(kx - 6 * p.s * 2, p.y - kh * 0.7, 12 * p.s * 2, 20 * p.s * 2);\n                    }\n                    return;\n                }\n\n                if (e.typ === 'auto') {\n                    var ax = cx + e.x * hb;\n                    var aw = 46 * p.s * 1.9, ah = 34 * p.s * 1.9;\n                    \/\/ Schatten\n                    ctx.fillStyle = 'rgba(0,0,0,0.3)';\n                    ctx.beginPath();\n                    ctx.ellipse(ax, p.y, aw * 0.55, 4 * p.s * 1.9, 0, 0, Math.PI * 2);\n                    ctx.fill();\n                    \/\/ Karosserie mit Seiten-Schattierung\n                    ctx.fillStyle = e.farbe;\n                    ctx.fillRect(ax - aw \/ 2, p.y - ah, aw, ah * 0.75);\n                    ctx.fillStyle = 'rgba(0,0,0,0.2)';\n                    ctx.fillRect(ax - aw \/ 2, p.y - ah, aw * 0.12, ah * 0.75);\n                    ctx.fillStyle = 'rgba(255,255,255,0.15)';\n                    ctx.fillRect(ax + aw \/ 2 - aw * 0.12, p.y - ah, aw * 0.12, ah * 0.75);\n                    \/\/ Dach (dunklerer Farbton) + Heckscheibe\n                    ctx.fillStyle = 'rgba(0,0,0,0.22)';\n                    ctx.fillRect(ax - aw * 0.36, p.y - ah * 1.05, aw * 0.72, ah * 0.14);\n                    ctx.fillStyle = 'rgba(220,240,255,0.85)';\n                    ctx.fillRect(ax - aw * 0.32, p.y - ah * 0.95, aw * 0.64, ah * 0.3);\n                    \/\/ R\u00fccklichter + R\u00e4der\n                    ctx.fillStyle = '#ff5a3a';\n                    ctx.fillRect(ax - aw \/ 2 + 1.5 * p.s, p.y - ah * 0.42, aw * 0.12, ah * 0.1);\n                    ctx.fillRect(ax + aw \/ 2 - 1.5 * p.s - aw * 0.12, p.y - ah * 0.42, aw * 0.12, ah * 0.1);\n                    ctx.fillStyle = '#1a1a1a';\n                    ctx.fillRect(ax - aw \/ 2 + 2, p.y - ah * 0.2, aw * 0.24, ah * 0.2);\n                    ctx.fillRect(ax + aw \/ 2 - 2 - aw * 0.24, p.y - ah * 0.2, aw * 0.24, ah * 0.2);\n                    return;\n                }\n\n                \/\/ Fu\u00dfg\u00e4nger \/ Radfahrer als Emoji (skaliert) mit Schatten\n                var px = cx + e.x * hb;\n                ctx.fillStyle = 'rgba(0,0,0,0.25)';\n                ctx.beginPath();\n                ctx.ellipse(px, p.y, 11 * p.s * 1.9, 3 * p.s * 1.9, 0, 0, Math.PI * 2);\n                ctx.fill();\n                ctx.fillStyle = '#000'; \/\/ WICHTIG: volle Deckkraft, sonst wird das Emoji halbtransparent\n                ctx.font = Math.max(12, 34 * p.s * 1.9) + 'px sans-serif';\n                ctx.textAlign = 'center';\n                ctx.fillText(e.typ === 'ped' ? '\ud83d\udeb6' : '\ud83d\udeb4', px, p.y - 2);\n            });\n\n            \/\/ Nacht: Scheinwerferkegel\n            if (nachtModus) {\n                var grad = ctx.createRadialGradient(W \/ 2, H - 30, 20, W \/ 2, H - 150, 240);\n                grad.addColorStop(0, 'rgba(255,255,210,0.28)');\n                grad.addColorStop(1, 'rgba(255,255,210,0)');\n                ctx.fillStyle = grad;\n                ctx.fillRect(0, HORIZON, W, H - HORIZON);\n            }\n\n            \/\/ Feuerwehrauto (fest unten in der Mitte, neigt sich beim Lenken)\n            var tx = W \/ 2, ty = H - 24;\n            var tw = 92, th = 58;\n            var neigung = input.steer * 0.06; \/\/ leichtes Wanken in Lenkrichtung\n\n            \/\/ Schatten auf der Fahrbahn\n            ctx.fillStyle = 'rgba(0,0,0,0.35)';\n            ctx.beginPath();\n            ctx.ellipse(tx, ty + 2, tw * 0.55, 9, 0, 0, Math.PI * 2);\n            ctx.fill();\n\n            ctx.save();\n            ctx.translate(tx, ty - th \/ 2);\n            ctx.rotate(neigung);\n            ctx.translate(-tx, -(ty - th \/ 2));\n\n            \/\/ Aufbau (hinterer Kasten) mit Schattierung links\/rechts\n            ctx.fillStyle = '#CC0000';\n            ctx.fillRect(tx - tw \/ 2, ty - th, tw, th * 0.8);\n            ctx.fillStyle = 'rgba(0,0,0,0.18)';\n            ctx.fillRect(tx - tw \/ 2, ty - th, 10, th * 0.8);\n            ctx.fillStyle = 'rgba(255,255,255,0.12)';\n            ctx.fillRect(tx + tw \/ 2 - 10, ty - th, 10, th * 0.8);\n\n            \/\/ Ger\u00e4tefach-Rolll\u00e4den (silberne Streifen)\n            ctx.fillStyle = '#c8ccd4';\n            ctx.fillRect(tx - tw * 0.36, ty - th * 0.62, tw * 0.30, th * 0.34);\n            ctx.fillRect(tx + tw * 0.06, ty - th * 0.62, tw * 0.30, th * 0.34);\n            ctx.strokeStyle = '#9aa0aa';\n            ctx.lineWidth = 1;\n            for (var rl = 1; rl < 4; rl++) {\n                var rly = ty - th * 0.62 + (th * 0.34 \/ 4) * rl;\n                ctx.beginPath();\n                ctx.moveTo(tx - tw * 0.36, rly); ctx.lineTo(tx - tw * 0.06, rly);\n                ctx.moveTo(tx + tw * 0.06, rly); ctx.lineTo(tx + tw * 0.36, rly);\n                ctx.stroke();\n            }\n\n            \/\/ Wei\u00dfer Zierstreifen + Sto\u00dfstange\n            ctx.fillStyle = '#f0f0f0';\n            ctx.fillRect(tx - tw \/ 2, ty - th * 0.30, tw, th * 0.09);\n            ctx.fillStyle = '#a80000';\n            ctx.fillRect(tx - tw \/ 2, ty - th * 0.21, tw, th * 0.13);\n\n            \/\/ Kabinendach + Heckscheibe (wir sehen das Auto von hinten)\n            ctx.fillStyle = '#b80000';\n            ctx.fillRect(tx - tw * 0.40, ty - th * 1.02, tw * 0.80, th * 0.24);\n            var scheibe = ctx.createLinearGradient(tx, ty - th * 1.0, tx, ty - th * 0.72);\n            scheibe.addColorStop(0, '#dceeff');\n            scheibe.addColorStop(1, '#8fb8d8');\n            ctx.fillStyle = scheibe;\n            ctx.fillRect(tx - tw * 0.34, ty - th * 0.98, tw * 0.68, th * 0.26);\n\n            \/\/ Leiter auf dem Dach\n            ctx.strokeStyle = '#d8d8d8';\n            ctx.lineWidth = 2.5;\n            ctx.beginPath();\n            ctx.moveTo(tx - tw * 0.30, ty - th * 1.06);\n            ctx.lineTo(tx + tw * 0.30, ty - th * 1.06);\n            ctx.moveTo(tx - tw * 0.30, ty - th * 1.12);\n            ctx.lineTo(tx + tw * 0.30, ty - th * 1.12);\n            ctx.stroke();\n            ctx.lineWidth = 1.5;\n            for (var sp = -2; sp <= 2; sp++) {\n                ctx.beginPath();\n                ctx.moveTo(tx + sp * tw * 0.13, ty - th * 1.06);\n                ctx.lineTo(tx + sp * tw * 0.13, ty - th * 1.12);\n                ctx.stroke();\n            }\n\n            \/\/ R\u00e4der mit Felgen\n            ctx.fillStyle = '#1a1a1a';\n            ctx.fillRect(tx - tw \/ 2 + 3, ty - 12, 24, 14);\n            ctx.fillRect(tx + tw \/ 2 - 27, ty - 12, 24, 14);\n            ctx.fillStyle = '#666';\n            ctx.fillRect(tx - tw \/ 2 + 11, ty - 8, 8, 6);\n            ctx.fillRect(tx + tw \/ 2 - 19, ty - 8, 8, 6);\n\n            \/\/ R\u00fccklichter\n            ctx.fillStyle = '#ff6a3a';\n            ctx.fillRect(tx - tw \/ 2 + 2, ty - th * 0.30, 6, th * 0.09);\n            ctx.fillRect(tx + tw \/ 2 - 8, ty - th * 0.30, 6, th * 0.09);\n\n            \/\/ 112-Schriftzug\n            ctx.fillStyle = '#fff';\n            ctx.font = '700 13px Oswald, sans-serif';\n            ctx.textAlign = 'center';\n            ctx.fillText('112', tx, ty - th * 0.42);\n\n            \/\/ Blaulicht (blinkt abwechselnd) auf dem Kabinendach\n            var phase = Math.floor(jetzt \/ 220) % 2;\n            ctx.fillStyle = phase === 0 ? '#2a7bff' : '#7db4ff';\n            ctx.beginPath(); ctx.arc(tx - 16, ty - th * 1.12 - 4, 5.5, 0, Math.PI * 2); ctx.fill();\n            ctx.fillStyle = phase === 1 ? '#2a7bff' : '#7db4ff';\n            ctx.beginPath(); ctx.arc(tx + 16, ty - th * 1.12 - 4, 5.5, 0, Math.PI * 2); ctx.fill();\n\n            ctx.restore();\n\n            ctx.fillStyle = phase === 0 ? 'rgba(42,123,255,0.10)' : 'rgba(255,60,60,0.07)';\n            ctx.fillRect(0, 0, W, H);\n\n            \/\/ Crash-Blitz\n            if (jetzt < blitzBis) {\n                ctx.fillStyle = 'rgba(255,80,80,0.35)';\n                ctx.fillRect(0, 0, W, H);\n            }\n\n            \/\/ HUD\n            ctx.fillStyle = 'rgba(0,0,0,0.45)';\n            ctx.fillRect(0, 0, W, 30);\n            ctx.fillStyle = '#fff';\n            ctx.font = '700 13px Oswald, sans-serif';\n            ctx.textAlign = 'left';\n            ctx.fillText('\u23f1 ' + Math.max(0, Math.ceil(restZeit)) + 's', 10, 20);\n            ctx.textAlign = 'center';\n            ctx.fillText(Math.round(tempo * 3.6) + ' km\/h', W \/ 2, 20);\n            ctx.textAlign = 'right';\n            var rechtsText = (modus === 'endlos')\n                ? Math.round(position) + ' m \u00b7 \ud83d\ude97 ' + ueberholt\n                : zielTextKurz();\n            ctx.fillText(rechtsText, W - 10, 20);\n        }\n\n        function zielTextKurz() {\n            var m = modus;\n            if (!m || m === 'endlos') return '';\n            if (m.ziel === 'strecke' || m.ziel === 'ped') return Math.round(position) + '\/' + m.streckeZiel + ' m';\n            if (m.ziel === 'ueberholen') return '\ud83d\ude97 ' + ueberholt + '\/' + m.anzahl;\n            if (m.ziel === 'ohnecrash') return crashes === 0 ? '\u2705 sauber' : '\ud83d\udca5';\n            if (m.ziel === 'hydrant') return '\ud83d\udca7 ' + hyd + '\/' + m.anzahl;\n            if (m.ziel === 'katze') return '\ud83d\udc08 ' + katze + '\/1';\n            if (m.ziel === 'blaulicht') return Math.round(position) + '\/' + m.streckeZiel + ' m \ud83d\udcef' + Math.round(blaulichtSek) + 's';\n            return '';\n        }\n\n        function schleife(zeitstempel) {\n            if (!laeuft) return;\n            var dt = Math.min(0.05, (zeitstempel - letzterFrame) \/ 1000);\n            letzterFrame = zeitstempel;\n            update(dt);\n            if (laeuft) {\n                zeichnen();\n                animId = requestAnimationFrame(schleife);\n            }\n        }\n\n        \/\/ ============ Start \/ Ende ============\n        function spielStart(gewaehlterModus) {\n            modus = gewaehlterModus;\n            nachtModus = (modus !== 'endlos' && modus.nacht);\n            laeuft = true;\n            playerX = 0; tempo = 0; position = 0;\n            ueberholt = 0; crashes = 0; personenCrash = false;\n            unverwundbarBis = 0; blitzBis = 0;\n            entities = [];\n            naechsterSpawnZ = 120; naechsterBannerZ = 200; naechsteBrueckeZ = 600;\n            naechstesHausZ = 35; naechsteLaterneZ = 35; naechsterBaumZ = 38; naechsteKircheZ = 700;\n            naechsterHydrantZ = 180; naechsteKatzeZ = 650;\n            ortsschildGesetzt = false; feuerwehrhausGesetzt = false;\n            hyd = 0; katze = 0; blaulichtSek = 0; rotlicht = 0;\n            restZeit = (modus === 'endlos') ? 90 : modus.zeitLimit;\n\n            startOverlay.style.display = 'none';\n            endeOverlay.style.display = 'none';\n            ranglisteOverlay.style.display = 'none';\n\n            try { localStorage.setItem('ffc_last_bracket', tier); } catch (e) {}\n            if (hornAn) hornStart();\n\n            letzterFrame = performance.now();\n            cancelAnimationFrame(animId);\n            animId = requestAnimationFrame(schleife);\n        }\n\n        function spielEnde(missionErfolg) {\n            laeuft = false;\n            cancelAnimationFrame(animId);\n            hornStop();\n\n            if (modus === 'endlos') {\n                var score = Math.round(position) + ueberholt * 25;\n                endtitelEl.textContent = '\ud83c\udfc1 Fahrt beendet!';\n                endtextEl.innerHTML = 'Strecke: <strong>' + Math.round(position) + ' m<\/strong><br>' +\n                    '\u00dcberholt: <strong>' + ueberholt + '<\/strong> (+' + (ueberholt * 25) + ')<br>' +\n                    'Gesamt: <strong>' + score + '<\/strong>';\n                eintragBereich.style.display = 'block';\n                eintragBereich.dataset.score = score;\n                nameInput.value = '';\n                eintragBtn.disabled = false;\n                eintragStatus.textContent = '';\n                if (position >= 800) ffBadgeSpeichern('einsatzfahrt', 'bronze');\n            } else {\n                var geschafft = missionErfolg === true;\n                endtitelEl.textContent = geschafft ? '\u2705 Mission geschafft!' : '\u274c Mission fehlgeschlagen';\n                endtextEl.innerHTML = geschafft\n                    ? 'Stark gefahren! ' + modus.titel + ' ist erledigt.'\n                    : 'Nicht schlimm - einfach nochmal versuchen!';\n                eintragBereich.style.display = 'none';\n                if (geschafft) missionSpeichern(modus.id);\n            }\n            endeOverlay.style.display = 'flex';\n            missionenAnzeigen();\n        }\n\n        wrap.querySelector('.ffc-endlos-btn').addEventListener('click', function() { spielStart('endlos'); });\n        wrap.querySelector('.ffc-neustart-btn').addEventListener('click', function() {\n            endeOverlay.style.display = 'none';\n            startOverlay.style.display = 'flex';\n        });\n\n        \/\/ Altersstufen-Chips\n        try { var gespeichert = localStorage.getItem('ffc_last_bracket'); if (gespeichert && TIERS[gespeichert]) tier = gespeichert; } catch (e) {}\n        function chipsAktualisieren() {\n            wrap.querySelectorAll('.ffc-tier-chip').forEach(function(chip) {\n                chip.classList.toggle('aktiv', chip.dataset.stufe === tier);\n            });\n        }\n        wrap.querySelectorAll('.ffc-tier-chip').forEach(function(chip) {\n            chip.addEventListener('click', function() { tier = chip.dataset.stufe; chipsAktualisieren(); });\n        });\n        chipsAktualisieren();\n        missionenAnzeigen();\n\n        \/\/ ============ Eingabe: Joystick ============\n        var joystick = wrap.querySelector('.ffc-joystick');\n        var stick = wrap.querySelector('.ffc-stick');\n        var joyAktiv = false;\n        var joyPointerId = null;\n        var tastatur = { links: false, rechts: false, hoch: false, runter: false };\n\n        function joyAuswerten(clientX, clientY) {\n            var rect = joystick.getBoundingClientRect();\n            var mx = rect.left + rect.width \/ 2;\n            var my = rect.top + rect.height \/ 2;\n            var radius = rect.width \/ 2 - 10;\n            var dx = (clientX - mx) \/ radius;\n            var dy = (clientY - my) \/ radius;\n            var laenge = Math.sqrt(dx * dx + dy * dy);\n            if (laenge > 1) { dx \/= laenge; dy \/= laenge; }\n\n            input.steer = Math.max(-1, Math.min(1, dx));\n            input.accel = Math.max(-1, Math.min(1, -dy)); \/\/ hoch = Gas\n\n            stick.style.marginLeft = (-27 + dx * radius * 0.8) + 'px';\n            stick.style.marginTop  = (-27 + dy * radius * 0.8) + 'px';\n        }\n        function joyLoslassen() {\n            joyAktiv = false;\n            joyPointerId = null;\n            input.steer = 0;\n            input.accel = 0;\n            stick.style.marginLeft = '-27px';\n            stick.style.marginTop = '-27px';\n            tastaturAnwenden();\n        }\n        joystick.addEventListener('pointerdown', function(e) {\n            e.preventDefault();\n            joyAktiv = true;\n            joyPointerId = e.pointerId;\n            try { joystick.setPointerCapture(e.pointerId); } catch (err) {}\n            joyAuswerten(e.clientX, e.clientY);\n        });\n        joystick.addEventListener('pointermove', function(e) {\n            if (!joyAktiv || e.pointerId !== joyPointerId) return;\n            e.preventDefault();\n            joyAuswerten(e.clientX, e.clientY);\n        });\n        joystick.addEventListener('pointerup', joyLoslassen);\n        joystick.addEventListener('pointercancel', joyLoslassen);\n        joystick.addEventListener('contextmenu', function(e) { e.preventDefault(); });\n\n        \/\/ Tastatur (PC): mappt auf dieselben analogen Werte\n        function tastaturAnwenden() {\n            if (joyAktiv) return; \/\/ Joystick hat Vorrang\n            input.steer = (tastatur.rechts ? 1 : 0) - (tastatur.links ? 1 : 0);\n            input.accel = (tastatur.hoch ? 1 : 0) - (tastatur.runter ? 1 : 0);\n        }\n        document.addEventListener('keydown', function(e) {\n            if (!laeuft) return;\n            if (e.key === 'ArrowLeft') { tastatur.links = true; e.preventDefault(); }\n            if (e.key === 'ArrowRight') { tastatur.rechts = true; e.preventDefault(); }\n            if (e.key === 'ArrowUp') { tastatur.hoch = true; e.preventDefault(); }\n            if (e.key === 'ArrowDown') { tastatur.runter = true; e.preventDefault(); }\n            tastaturAnwenden();\n        });\n        document.addEventListener('keyup', function(e) {\n            if (e.key === 'ArrowLeft') tastatur.links = false;\n            if (e.key === 'ArrowRight') tastatur.rechts = false;\n            if (e.key === 'ArrowUp') tastatur.hoch = false;\n            if (e.key === 'ArrowDown') tastatur.runter = false;\n            tastaturAnwenden();\n        });\n\n        \/\/ ============ Rangliste ============\n        function rangHtml(liste) {\n            var html = '';\n            liste.forEach(function(e, i) {\n                var div = document.createElement('div');\n                div.textContent = e.name;\n                html += '<div class=\"ffc-rang-zeile\"><span class=\"ffc-rang-platz\">' + (i + 1) + '.<\/span>' +\n                    '<span class=\"ffc-rang-name\">' + div.innerHTML + '<\/span>' +\n                    '<span class=\"ffc-rang-score\">' + e.score + '<\/span><\/div>';\n            });\n            return html;\n        }\n        function ranglisteHolen(stufe, callback) {\n            var fd = new FormData();\n            fd.append('action', 'ff_efahrt_rangliste_holen');\n            fd.append('nonce', NONCE);\n            fd.append('altersstufe', stufe);\n            fetch(AJAXURL, { method: 'POST', body: fd })\n                .then(function(r) { return r.json(); })\n                .then(function(data) { callback((data.success && data.data) ? data.data : []); })\n                .catch(function() { callback(null); });\n        }\n        var vollStufe = tier;\n        function vollRanglisteLaden() {\n            wrap.querySelectorAll('.ffc-voll-tabs .ffc-tab-btn').forEach(function(b) {\n                b.classList.toggle('aktiv', b.dataset.stufe === vollStufe);\n            });\n            vollRangInhalt.innerHTML = 'L\u00e4dt \u2026';\n            ranglisteHolen(vollStufe, function(liste) {\n                if (liste === null) { vollRangInhalt.innerHTML = '<p class=\"ffc-rang-leer\">Rangliste konnte nicht geladen werden.<\/p>'; return; }\n                if (!liste.length) { vollRangInhalt.innerHTML = '<p class=\"ffc-rang-leer\">Noch keine Eintr\u00e4ge \u2013 sei die\/der Erste! \ud83d\ude92<\/p>'; return; }\n                vollRangInhalt.innerHTML = rangHtml(liste);\n            });\n        }\n        wrap.querySelectorAll('.ffc-voll-tabs .ffc-tab-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() { vollStufe = btn.dataset.stufe; vollRanglisteLaden(); });\n        });\n        wrap.querySelector('.ffc-rang-oeffnen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'flex';\n            vollStufe = tier;\n            vollRanglisteLaden();\n        });\n        wrap.querySelector('.ffc-rang-schliessen-btn').addEventListener('click', function() {\n            ranglisteOverlay.style.display = 'none';\n        });\n\n        eintragBtn.addEventListener('click', function() {\n            var name = nameInput.value.trim();\n            if (!name) { eintragStatus.textContent = 'Bitte einen Namen eingeben.'; return; }\n            eintragBtn.disabled = true;\n            eintragStatus.textContent = 'Wird gespeichert \u2026';\n\n            var fd = new FormData();\n            fd.append('action', 'ff_efahrt_score_speichern');\n            fd.append('nonce', NONCE);\n            fd.append('name', name);\n            fd.append('score', parseInt(eintragBereich.dataset.score || '0'));\n            fd.append('spieler_id', ffsSpielerId());\n            fd.append('altersstufe', tier);\n\n            fetch(AJAXURL, { method: 'POST', body: fd })\n                .then(function(r) { return r.json(); })\n                .then(function(data) {\n                    if (data.success) {\n                        eintragStatus.textContent = (data.data && data.data.verbessert === false)\n                            ? 'Dein bisheriger Eintrag war schon besser oder gleich gut \u2013 bleibt unver\u00e4ndert.'\n                            : '\u2705 In der Rangliste eingetragen!';\n                    } else if (data.data && data.data.grund === 'name_vergeben') {\n                        eintragStatus.textContent = '\u26a0\ufe0f Dieser Name ist schon vergeben \u2013 bitte einen anderen w\u00e4hlen.';\n                        eintragBtn.disabled = false;\n                    } else {\n                        eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                        eintragBtn.disabled = false;\n                    }\n                })\n                .catch(function() {\n                    eintragStatus.textContent = 'Konnte nicht gespeichert werden.';\n                    eintragBtn.disabled = false;\n                });\n        });\n\n        \/\/ Vorschau-Standbild zeichnen, damit hinter dem Start-Overlay etwas zu sehen ist\n        restZeit = 90; modus = 'endlos';\n        zeichnen();\n        modus = null;\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-escape\">\n            <div class=\"ffe-wrap\" id=\"ffe-wrap-1\">\n        <style>\n            .ffe-wrap { max-width: 440px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffe-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 24px; color: #fff !important; text-align: center; position: relative; overflow: hidden; min-height: 460px !important; }\n            .ffe-title { font-size: 20px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffe-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 14px; }\n            .ffe-hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; font-size: 13px; font-weight: 700; color: #fff !important; }\n            .ffe-fortschritt { width: 100%; height: 6px; background: rgba(255,255,255,0.12); border-radius: 3px; margin-bottom: 18px; overflow: hidden; }\n            .ffe-fortschritt-balken { height: 100%; background: var(--ff-red, #CC0000); border-radius: 3px; transition: width 0.4s; }\n\n            .ffe-screen { display: none; }\n            .ffe-screen.aktiv { display: block; }\n\n            .ffe-story { font-size: 15px; color: #fff !important; line-height: 1.7; margin-bottom: 20px; }\n            .ffe-frage { font-size: 16px; font-weight: 700; color: #fff !important; margin-bottom: 16px; }\n\n            .ffe-optionen { display: flex; flex-direction: column; gap: 10px; margin-bottom: 10px; }\n            .ffe-option-btn { background: rgba(255,255,255,0.06); border: 2px solid rgba(255,255,255,0.15); color: #fff !important; padding: 12px 16px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; font-family: inherit; }\n            .ffe-option-btn:hover:not(:disabled) { border-color: var(--ff-red, #CC0000); }\n            .ffe-option-btn.richtig { border-color: #3fae4a; background: rgba(63,174,74,0.2); }\n            .ffe-option-btn.falsch { border-color: var(--ff-red, #CC0000); background: rgba(204,0,0,0.2); }\n\n            .ffe-code-input { width: 100%; box-sizing: border-box; padding: 12px 14px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.25) !important; background: rgba(255,255,255,0.08) !important; color: #fff !important; font-size: 16px; text-align: center; font-family: inherit; margin-bottom: 12px; letter-spacing: 0.05em; }\n            .ffe-code-hinweis { font-size: 12px; color: gold !important; min-height: 16px; margin-bottom: 10px; }\n\n            .ffe-liste { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }\n            .ffe-karte { background: rgba(255,255,255,0.06); border: 2px solid rgba(255,255,255,0.15); border-radius: 8px; padding: 12px 14px; display: flex; align-items: center; gap: 12px; cursor: pointer; text-align: left; }\n            .ffe-karte .icon { font-size: 22px; }\n            .ffe-karte .text { flex: 1; font-size: 14px; font-weight: 600; color: #fff !important; }\n            .ffe-karte .platz { font-weight: 900; color: gold !important; }\n            .ffe-karte.richtig { border-color: #3fae4a; background: rgba(63,174,74,0.15); cursor: default; }\n\n            .ffe-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 12px 30px; border-radius: 6px; font-weight: 700; font-size: 15px; cursor: pointer; font-family: inherit; }\n            .ffe-btn:hover { background: var(--ff-red-hover, #aa0000); }\n            .ffe-btn.sichtbar-nach-loesung { display: none; margin-top: 14px; }\n            .ffe-btn.sichtbar-nach-loesung.sichtbar { display: inline-block; }\n\n            .ffe-ergebnis { font-size: 15px; margin: 14px 0; color: #fff !important; }\n            .ffe-ergebnis strong { color: gold !important; }\n        <\/style>\n\n        <div class=\"ffe-box\">\n            <div class=\"ffe-title\">\ud83d\udeaa Escape-Room: Der verrauchte Flur<\/div>\n            <div class=\"ffe-untertitel\">L\u00f6st die R\u00e4tsel, bevor der Rauch zu dicht wird!<\/div>\n\n            <div class=\"ffe-hud\">\n                <span>R\u00e4tsel <span class=\"ffe-nr\">0<\/span>\/3<\/span>\n                <span>\u23f1\ufe0f <span class=\"ffe-zeit\">0<\/span>s<\/span>\n            <\/div>\n            <div class=\"ffe-fortschritt\"><div class=\"ffe-fortschritt-balken\" style=\"width:0%\"><\/div><\/div>\n\n            <!-- INTRO -->\n            <div class=\"ffe-screen aktiv\" data-screen=\"intro\">\n                <p class=\"ffe-story\">Du sitzt im Gruppenraum, als pl\u00f6tzlich der Rauchmelder losgeht.\n                Der Flur f\u00fcllt sich mit Rauch. Findet den Weg raus - Schritt f\u00fcr Schritt,\n                R\u00e4tsel f\u00fcr R\u00e4tsel!<\/p>\n                <button class=\"ffe-btn ffe-start-btn\" type=\"button\">\ud83d\udeaa Los geht's<\/button>\n            <\/div>\n\n            <!-- STATION A: MULTIPLE CHOICE -->\n            <div class=\"ffe-screen\" data-screen=\"stationA\">\n                <p class=\"ffe-story ffe-storyA\"><\/p>\n                <div class=\"ffe-frage ffe-frageA\"><\/div>\n                <div class=\"ffe-optionen ffe-optionenA\"><\/div>\n                <button class=\"ffe-btn ffe-weiterA-btn sichtbar-nach-loesung\" type=\"button\">Weiter \u2192<\/button>\n            <\/div>\n\n            <!-- STATION B: CODE\/TEXT -->\n            <div class=\"ffe-screen\" data-screen=\"stationB\">\n                <p class=\"ffe-story ffe-storyB\"><\/p>\n                <div class=\"ffe-frage ffe-frageB\"><\/div>\n                <input type=\"text\" class=\"ffe-code-input\" placeholder=\"L\u00f6sung eingeben\" maxlength=\"20\">\n                <div class=\"ffe-code-hinweis\"><\/div>\n                <button class=\"ffe-btn ffe-code-pruefen-btn\" type=\"button\">Pr\u00fcfen<\/button>\n                <button class=\"ffe-btn ffe-weiterB-btn sichtbar-nach-loesung\" type=\"button\">Weiter \u2192<\/button>\n            <\/div>\n\n            <!-- STATION C: REIHENFOLGE -->\n            <div class=\"ffe-screen\" data-screen=\"stationC\">\n                <p class=\"ffe-story ffe-storyC\"><\/p>\n                <div class=\"ffe-liste\"><\/div>\n            <\/div>\n\n            <!-- ENDE -->\n            <div class=\"ffe-screen\" data-screen=\"ende\">\n                <p class=\"ffe-story\">\ud83c\udf89 Geschafft! Ihr seid sicher entkommen und habt alles richtig gemacht.<\/p>\n                <div class=\"ffe-ergebnis\">\n                    Zeit: <strong><span class=\"ffe-endzeit\">0<\/span> Sekunden<\/strong><br>\n                    Fehlversuche: <strong><span class=\"ffe-endfehler\">0<\/span><\/strong>\n                <\/div>\n                <button class=\"ffe-btn ffe-neustart-btn\" type=\"button\">Nochmal fliehen<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var wrap = document.getElementById('ffe-wrap-1');\n        if (!wrap) return;\n\n        function ffBadgeSpeichern(spiel, abzeichen) {\n            try {\n                var rang = { bronze: 1, silber: 2, gold: 3 };\n                var daten = JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}');\n                if (!daten[spiel] || rang[abzeichen] > rang[daten[spiel]]) {\n                    daten[spiel] = abzeichen;\n                    localStorage.setItem('ff_sammelalbum', JSON.stringify(daten));\n                    try { window.dispatchEvent(new CustomEvent('ffBadgeAktualisiert')); } catch (e) {}\n                }\n            } catch (e) {}\n        }\n\n        \/\/ ---------- Variantenpools ----------\n        var STATIONEN_A = [\n            {\n                story: 'Im Flur h\u00e4ngt dicker Rauch. Vor dir: der Aufzug, die Treppe und ein Fenster im Erdgeschoss.',\n                frage: 'Wie verl\u00e4sst ihr das Geb\u00e4ude sicher?',\n                optionen: ['Aufzug nehmen', 'Treppe nehmen', 'Aus dem Fenster im 3. Stock springen'],\n                richtig: 1\n            },\n            {\n                story: 'Der Rauchmelder piept immer lauter.',\n                frage: 'Was ist als Erstes zu tun, wenn der Rauchmelder losgeht?',\n                optionen: ['Weiterschlafen', 'Ruhe bewahren und dem Fluchtplan folgen', 'Erstmal Fotos machen'],\n                richtig: 1\n            },\n            {\n                story: 'Vor dir ist eine geschlossene T\u00fcr, dahinter k\u00f6nnte Feuer sein.',\n                frage: 'Was tut ihr, bevor ihr die T\u00fcr \u00f6ffnet?',\n                optionen: ['Sofort aufrei\u00dfen', 'Mit dem Handr\u00fccken pr\u00fcfen, ob die Klinke hei\u00df ist', 'Dagegen treten'],\n                richtig: 1\n            },\n            {\n                story: 'Der Flur ist voller Rauch, der sich unter der Decke sammelt.',\n                frage: 'Wie bewegt ihr euch am besten durch den Rauch?',\n                optionen: ['Aufrecht und schnell laufen', 'Niedrig bleiben und kriechen', 'R\u00fcckw\u00e4rtsgehen'],\n                richtig: 1\n            },\n            {\n                story: 'Ihr habt es nach drau\u00dfen geschafft.',\n                frage: 'Was macht ihr direkt nach der Flucht aus dem Geb\u00e4ude?',\n                optionen: ['Nochmal reingehen, um Sachen zu holen', 'Zum vereinbarten Sammelplatz gehen', 'Einfach wegrennen'],\n                richtig: 1\n            },\n            {\n                story: 'Am Sammelplatz merkt ihr: Ein Freund fehlt noch!',\n                frage: 'Was ist jetzt richtig?',\n                optionen: ['Selbst wieder reingehen und suchen', 'Der Feuerwehr Bescheid geben, NICHT selbst reingehen', 'Abwarten und nichts sagen'],\n                richtig: 1\n            }\n        ];\n\n        var STATIONEN_B = [\n            {\n                story: 'Am Feuerl\u00f6scher, an dem ihr auf dem Weg nach drau\u00dfen vorbeikommt, h\u00e4ngt ein Zettel mit durcheinandergew\u00fcrfelten Buchstaben:',\n                frage: 'S \u00b7 C \u00b7 H \u00b7 E \u00b7 N \u00b7 L \u00b7 \u00d6',\n                loesungen: ['LOESCHEN', 'L\u00d6SCHEN']\n            },\n            {\n                story: '\u00dcber einer T\u00fcr auf eurem Fluchtweg leuchtet ein Schild mit vertauschten Buchstaben.',\n                frage: 'G \u00b7 A \u00b7 N \u00b7 S \u00b7 U \u00b7 A \u00b7 G',\n                loesungen: ['AUSGANG']\n            },\n            {\n                story: 'Ein Hinweisschild zeigt den Weg nach drau\u00dfen, die Buchstaben sind aber durcheinander.',\n                frage: 'G \u00b7 E \u00b7 W \u00b7 T \u00b7 H \u00b7 C \u00b7 U \u00b7 L \u00b7 F',\n                loesungen: ['FLUCHTWEG']\n            },\n            {\n                story: 'Drau\u00dfen angekommen sucht ihr den vereinbarten Treffpunkt - auf dem Schild sind die Buchstaben vertauscht.',\n                frage: 'P \u00b7 L \u00b7 A \u00b7 T \u00b7 Z \u00b7 S \u00b7 A \u00b7 M \u00b7 M \u00b7 E \u00b7 L',\n                loesungen: ['SAMMELPLATZ']\n            },\n            {\n                story: 'Sobald ihr sicher drau\u00dfen seid, m\u00fcsst ihr die Feuerwehr rufen - der Zettel mit dem Stichwort ist aber verrutscht.',\n                frage: 'R \u00b7 U \u00b7 N \u00b7 F \u00b7 O \u00b7 T',\n                loesungen: ['NOTRUF']\n            },\n            {\n                story: 'Der Rauchmelder hat euch gewarnt - auf dem Ger\u00e4t stehen die Buchstaben durcheinander.',\n                frage: 'M \u00b7 A \u00b7 R \u00b7 L \u00b7 A',\n                loesungen: ['ALARM']\n            }\n        ];\n\n        var STATIONEN_C = [\n            {\n                story: 'Drau\u00dfen angekommen, ruft ihr die Feuerwehr. Bringt die W-Fragen in die richtige Reihenfolge:',\n                karten: [\n                    { id: 0, icon: '\ud83d\udccd', text: 'Wo ist der Notfall?' },\n                    { id: 1, icon: '\u2757', text: 'Was ist geschehen?' },\n                    { id: 2, icon: '\ud83d\udd22', text: 'Wie viele Betroffene?' }\n                ]\n            },\n            {\n                story: 'Deine Jacke hat kurz Feuer gefangen. Bringt die richtigen Schritte in die richtige Reihenfolge:',\n                karten: [\n                    { id: 0, icon: '\ud83d\uded1', text: 'Stehenbleiben' },\n                    { id: 1, icon: '\u2b07\ufe0f', text: 'Hinlegen' },\n                    { id: 2, icon: '\ud83d\udd04', text: 'W\u00e4lzen' }\n                ]\n            },\n            {\n                story: 'An der Wand h\u00e4ngt ein Ablaufplan f\u00fcr den Alarmfall. Bringt die Schritte in die richtige Reihenfolge:',\n                karten: [\n                    { id: 0, icon: '\ud83d\udea8', text: 'Alarm h\u00f6ren' },\n                    { id: 1, icon: '\ud83d\udeaa', text: 'Ruhig zum Sammelplatz gehen' },\n                    { id: 2, icon: '\ud83d\ude4b', text: 'Melden, dass alle da sind' }\n                ]\n            },\n            {\n                story: 'Vor euch ist eine geschlossene T\u00fcr - dahinter k\u00f6nnte Feuer sein. Bringt die richtigen Schritte in die richtige Reihenfolge:',\n                karten: [\n                    { id: 0, icon: '\u270b', text: 'Handr\u00fccken an die T\u00fcr halten' },\n                    { id: 1, icon: '\u2744\ufe0f', text: 'Ist sie k\u00fchl: vorsichtig \u00f6ffnen' },\n                    { id: 2, icon: '\ud83d\udd25', text: 'Ist sie hei\u00df: anderen Weg suchen' }\n                ]\n            }\n        ];\n\n        function ffeZufallsIndex(laenge) { return Math.floor(Math.random() * laenge); }\n        function ffeMischen(arr) {\n            var kopie = arr.slice();\n            for (var i = kopie.length - 1; i > 0; i--) {\n                var j = Math.floor(Math.random() * (i + 1));\n                var tmp = kopie[i]; kopie[i] = kopie[j]; kopie[j] = tmp;\n            }\n            return kopie;\n        }\n\n        var nrAnzeige = wrap.querySelector('.ffe-nr');\n        var zeitAnzeige = wrap.querySelector('.ffe-zeit');\n        var balken = wrap.querySelector('.ffe-fortschritt-balken');\n        var fehler = 0;\n        var startZeit = null;\n        var zeitTimer = null;\n        var naechsterCIndex = 0;\n        var aktuelleStationC = null;\n        var aktuelleStationB = null;\n\n        function ffeZeigeScreen(name, fortschritt) {\n            wrap.querySelectorAll('.ffe-screen').forEach(function(s) {\n                s.classList.toggle('aktiv', s.dataset.screen === name);\n            });\n            balken.style.width = fortschritt + '%';\n        }\n\n        \/\/ ---------- Station A ----------\n        function ffeStationAAufbauen() {\n            var variante = STATIONEN_A[ffeZufallsIndex(STATIONEN_A.length)];\n            wrap.querySelector('.ffe-storyA').textContent = variante.story;\n            wrap.querySelector('.ffe-frageA').textContent = variante.frage;\n            var optionenWrap = wrap.querySelector('.ffe-optionenA');\n            optionenWrap.innerHTML = '';\n            variante.optionen.forEach(function(text, i) {\n                var btn = document.createElement('button');\n                btn.type = 'button';\n                btn.className = 'ffe-option-btn';\n                btn.textContent = text;\n                btn.addEventListener('click', function() {\n                    if (btn.disabled) return;\n                    optionenWrap.querySelectorAll('.ffe-option-btn').forEach(function(b, j) {\n                        b.disabled = true;\n                        if (j === variante.richtig) b.classList.add('richtig');\n                        else if (j === i) b.classList.add('falsch');\n                    });\n                    if (i !== variante.richtig) fehler++;\n                    wrap.querySelector('.ffe-weiterA-btn').classList.add('sichtbar');\n                });\n                optionenWrap.appendChild(btn);\n            });\n        }\n        wrap.querySelector('.ffe-weiterA-btn').addEventListener('click', function() {\n            nrAnzeige.textContent = '2';\n            ffeZeigeScreen('stationB', 40);\n            ffeStationBAufbauen();\n        });\n\n        \/\/ ---------- Station B ----------\n        var codeInput = wrap.querySelector('.ffe-code-input');\n        var codeHinweis = wrap.querySelector('.ffe-code-hinweis');\n        function ffeStationBAufbauen() {\n            aktuelleStationB = STATIONEN_B[ffeZufallsIndex(STATIONEN_B.length)];\n            wrap.querySelector('.ffe-storyB').textContent = aktuelleStationB.story;\n            wrap.querySelector('.ffe-frageB').textContent = aktuelleStationB.frage;\n            codeInput.value = '';\n            codeInput.disabled = false;\n            codeHinweis.textContent = '';\n            wrap.querySelector('.ffe-code-pruefen-btn').disabled = false;\n            wrap.querySelector('.ffe-weiterB-btn').classList.remove('sichtbar');\n        }\n        wrap.querySelector('.ffe-code-pruefen-btn').addEventListener('click', function() {\n            var wert = codeInput.value.trim().toUpperCase();\n            if (aktuelleStationB.loesungen.indexOf(wert) !== -1) {\n                codeHinweis.textContent = '\u2705 Richtig gel\u00f6st!';\n                codeHinweis.style.color = '#3fae4a';\n                codeInput.disabled = true;\n                wrap.querySelector('.ffe-code-pruefen-btn').disabled = true;\n                wrap.querySelector('.ffe-weiterB-btn').classList.add('sichtbar');\n            } else {\n                fehler++;\n                codeHinweis.textContent = '\u274c Nicht ganz - nochmal versuchen!';\n                codeHinweis.style.color = '';\n            }\n        });\n        wrap.querySelector('.ffe-weiterB-btn').addEventListener('click', function() {\n            nrAnzeige.textContent = '3';\n            ffeZeigeScreen('stationC', 70);\n            ffeStationCAufbauen();\n        });\n\n        \/\/ ---------- Station C ----------\n        var notrufListe = wrap.querySelector('.ffe-liste');\n        function ffeStationCAufbauen() {\n            aktuelleStationC = STATIONEN_C[ffeZufallsIndex(STATIONEN_C.length)];\n            wrap.querySelector('.ffe-storyC').textContent = aktuelleStationC.story;\n            naechsterCIndex = 0;\n            notrufListe.innerHTML = '';\n            ffeMischen(aktuelleStationC.karten).forEach(function(k) {\n                var el = document.createElement('div');\n                el.className = 'ffe-karte';\n                el.dataset.id = k.id;\n                el.innerHTML = '<span class=\"icon\">' + k.icon + '<\/span><span class=\"text\">' + k.text + '<\/span><span class=\"platz\"><\/span>';\n                el.addEventListener('click', function() { ffeStationCTippen(el); });\n                notrufListe.appendChild(el);\n            });\n        }\n        function ffeStationCTippen(el) {\n            if (el.classList.contains('richtig')) return;\n            var id = parseInt(el.dataset.id);\n            if (id === naechsterCIndex) {\n                naechsterCIndex++;\n                el.classList.add('richtig');\n                el.querySelector('.platz').textContent = naechsterCIndex;\n                if (naechsterCIndex === aktuelleStationC.karten.length) {\n                    setTimeout(ffeSpielEnde, 400);\n                }\n            } else {\n                fehler++;\n            }\n        }\n\n        function ffeSpielEnde() {\n            clearInterval(zeitTimer);\n            var sekunden = Math.floor((Date.now() - startZeit) \/ 1000);\n            wrap.querySelector('.ffe-endzeit').textContent = sekunden;\n            wrap.querySelector('.ffe-endfehler').textContent = fehler;\n            nrAnzeige.textContent = '3';\n            ffeZeigeScreen('ende', 100);\n\n            var abzeichen = fehler === 0 ? 'gold' : (fehler <= 2 ? 'silber' : 'bronze');\n            ffBadgeSpeichern('escape', abzeichen);\n        }\n\n        function ffeSpielStart() {\n            fehler = 0;\n            nrAnzeige.textContent = '1';\n\n            ffeStationAAufbauen();\n            ffeZeigeScreen('stationA', 10);\n\n            startZeit = Date.now();\n            clearInterval(zeitTimer);\n            zeitTimer = setInterval(function() {\n                zeitAnzeige.textContent = Math.floor((Date.now() - startZeit) \/ 1000);\n            }, 1000);\n        }\n\n        wrap.querySelector('.ffe-start-btn').addEventListener('click', ffeSpielStart);\n        wrap.querySelector('.ffe-neustart-btn').addEventListener('click', ffeSpielStart);\n    })();\n    <\/script>\n        <\/div>\n    <div class=\"ffss-spiel\" id=\"ffss-spiel-sammelalbum\">\n            <div class=\"ffa-wrap\">\n        <style>\n            .ffa-wrap { max-width: 480px; margin: 20px auto; font-family: 'Oswald', sans-serif; }\n            .ffa-box { background: var(--ff-blue-dark, #1C2B4B); border-radius: 12px; border-top: 4px solid var(--ff-red, #CC0000); padding: 24px; color: #fff !important; text-align: center; }\n            .ffa-title { font-size: 22px; font-weight: 700; margin-bottom: 4px; color: #fff !important; }\n            .ffa-untertitel { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin-bottom: 20px; }\n\n            .ffa-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 10px; }\n            .ffa-slot { background: rgba(255,255,255,0.05); border: 2px solid rgba(255,255,255,0.12); border-radius: 10px; padding: 14px 8px; }\n            .ffa-slot.erreicht { border-color: gold; background: rgba(255,215,0,0.08); }\n            .ffa-slot .icon { font-size: 26px; margin-bottom: 4px; }\n            .ffa-slot .name { font-size: 11px; font-weight: 700; color: #fff !important; margin-bottom: 6px; line-height: 1.3; min-height: 28px; }\n            .ffa-abzeichen { font-size: 26px; }\n            .ffa-abzeichen.leer { opacity: 0.25; }\n\n            .ffa-fortschritt-text { font-size: 13px; color: var(--ff-text-muted, #a0b0c8) !important; margin: 14px 0 4px; }\n\n            .ffa-diplom { display: none; margin-top: 20px; padding: 20px; background: rgba(255,215,0,0.1); border: 2px solid gold; border-radius: 10px; }\n            .ffa-diplom.sichtbar { display: block; }\n            .ffa-diplom h3 { font-size: 20px; color: gold !important; margin-bottom: 8px; }\n            .ffa-diplom p { font-size: 13px; color: #fff !important; margin-bottom: 14px; line-height: 1.6; }\n            .ffa-btn { background: var(--ff-red, #CC0000); color: #fff !important; border: none; padding: 10px 24px; border-radius: 6px; font-weight: 700; font-size: 13px; cursor: pointer; font-family: inherit; }\n            .ffa-btn:hover { background: var(--ff-red-hover, #aa0000); }\n\n        <\/style>\n\n        <div class=\"ffa-box\">\n            <div class=\"ffa-title\">\ud83c\udfc5 L\u00f6schzwerge-Sammelalbum<\/div>\n            <div class=\"ffa-untertitel\">Spielt und gewinnt, um alle Abzeichen zu sammeln!<\/div>\n\n            <div class=\"ffa-grid\">\n                <div class=\"ffa-slot\" data-spiel=\"loeschangriff\">\n                    <div class=\"icon\">\ud83d\udd25<\/div>\n                    <div class=\"name\">L\u00f6schangriff<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"memory\">\n                    <div class=\"icon\">\ud83e\udde0<\/div>\n                    <div class=\"name\">Willmatshofen Memory<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"notruf\">\n                    <div class=\"icon\">\ud83d\udcde<\/div>\n                    <div class=\"name\">Notruf-Reihenfolge<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"quiz\">\n                    <div class=\"icon\">\ud83e\uddef<\/div>\n                    <div class=\"name\">Feuerwehr-Quiz<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"schlauch\">\n                    <div class=\"icon\">\ud83d\udebf<\/div>\n                    <div class=\"name\">Schlauch-Verbindung<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"escape\">\n                    <div class=\"icon\">\ud83d\udeaa<\/div>\n                    <div class=\"name\">Escape-Room<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"fahrsimulator\">\n                    <div class=\"icon\">\ud83d\ude92<\/div>\n                    <div class=\"name\">Einsatzfahrt-Simulator<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"strahlrohr\">\n                    <div class=\"icon\">\ud83c\udfaf<\/div>\n                    <div class=\"name\">Strahlrohr-Ziel<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"deich\">\n                    <div class=\"icon\">\ud83c\udf0a<\/div>\n                    <div class=\"name\">Deich-Verteidigung<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n                <div class=\"ffa-slot\" data-spiel=\"einsatzfahrt\">\n                    <div class=\"icon\">\ud83d\udea8<\/div>\n                    <div class=\"name\">Einsatzfahrt 3D<\/div>\n                    <div class=\"ffa-abzeichen leer\">\u26aa<\/div>\n                <\/div>\n            <\/div>\n\n            <div class=\"ffa-fortschritt-text\"><span class=\"ffa-anzahl\">0<\/span> von 10 Abzeichen gesammelt<\/div>\n\n            <div class=\"ffa-diplom\">\n                <h3>\ud83c\udf89 Diplom: Feuerwehr-Profi<\/h3>\n                <p>Herzlichen Gl\u00fcckwunsch! Du hast alle 10 Feuerwehr-Spiele gemeistert\n                und bist offiziell ein Willmatshofer Feuerwehr-Profi. \ud83d\ude92<\/p>\n                <button class=\"ffa-btn ffa-drucken-btn\" type=\"button\">\ud83d\udda8\ufe0f Diplom ausdrucken<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    (function() {\n        var ABZEICHEN_ICON = { bronze: '\ud83e\udd49', silber: '\ud83e\udd48', gold: '\ud83e\udd47' };\n\n        function ladeDaten() {\n            try { return JSON.parse(localStorage.getItem('ff_sammelalbum') || '{}'); }\n            catch (e) { return {}; }\n        }\n\n        function ffaAktualisieren() {\n            var daten = ladeDaten();\n            var anzahl = 0;\n\n            document.querySelectorAll('.ffa-slot').forEach(function(slot) {\n                var spiel = slot.dataset.spiel;\n                var abzeichenEl = slot.querySelector('.ffa-abzeichen');\n                if (daten[spiel]) {\n                    anzahl++;\n                    slot.classList.add('erreicht');\n                    abzeichenEl.textContent = ABZEICHEN_ICON[daten[spiel]] || '\ud83e\udd49';\n                    abzeichenEl.classList.remove('leer');\n                } else {\n                    slot.classList.remove('erreicht');\n                    abzeichenEl.textContent = '\u26aa';\n                    abzeichenEl.classList.add('leer');\n                }\n            });\n\n            document.querySelectorAll('.ffa-anzahl').forEach(function(el) { el.textContent = anzahl; });\n            document.querySelectorAll('.ffa-diplom').forEach(function(el) {\n                el.classList.toggle('sichtbar', anzahl === 10);\n            });\n        }\n\n        \/\/ Sofort beim Laden anzeigen ...\n        ffaAktualisieren();\n\n        \/\/ ... UND jedes Mal, wenn irgendwo auf der Seite ein Abzeichen dazu-\n        \/\/ kommt (die Spiele l\u00f6sen dieses Event in ffBadgeSpeichern() aus) -\n        \/\/ wichtig, weil auf der Spiele-\u00dcbersichtsseite alle Spiele gleich-\n        \/\/ zeitig geladen sind und das Sammelalbum sonst nur den Stand vom\n        \/\/ allerersten Seitenaufruf zeigen w\u00fcrde.\n        window.addEventListener('ffBadgeAktualisiert', ffaAktualisieren);\n\n        \/\/ Zus\u00e4tzliches Sicherheitsnetz: auch beim Sichtbarwerden der Kachel\n        \/\/ (z.B. Tab-Wechsel auf der Spiele-\u00dcbersichtsseite) neu pr\u00fcfen.\n        document.addEventListener('visibilitychange', function() {\n            if (!document.hidden) ffaAktualisieren();\n        });\n\n        \/\/ Diplom drucken: Inhalt in einem eigenen, sauberen Fenster ohne den\n        \/\/ Rest der Seite \u00f6ffnen - robuster als Druck-CSS, weil es egal ist,\n        \/\/ wie tief das Diplom auf der eigentlichen Seite verschachtelt ist.\n        document.querySelectorAll('.ffa-drucken-btn').forEach(function(btn) {\n            btn.addEventListener('click', function() {\n                var diplomBox = btn.closest('.ffa-diplom');\n                var titel = diplomBox.querySelector('h3').textContent;\n                var text  = diplomBox.querySelector('p').textContent;\n\n                var druckFenster = window.open('', '_blank', 'width=700,height=500');\n                if (!druckFenster) { alert('Bitte Pop-ups f\u00fcr diese Seite erlauben, um das Diplom zu drucken.'); return; }\n\n                druckFenster.document.write(\n                    '<!DOCTYPE html><html><head><meta charset=\"utf-8\">' +\n                    '<title>Diplom<\/title>' +\n                    '<style>' +\n                    'body { font-family: \"Oswald\", Arial, sans-serif; text-align: center; padding: 60px; margin: 0; }' +\n                    '.rahmen { border: 6px solid gold; border-radius: 12px; padding: 50px 40px; max-width: 600px; margin: 0 auto; }' +\n                    'h1 { font-size: 22px; color: #1C2B4B; text-transform: uppercase; letter-spacing: 0.1em; margin-bottom: 20px; }' +\n                    'h3 { font-size: 30px; color: #1C2B4B; margin: 0 0 20px; }' +\n                    'p { font-size: 16px; color: #333; line-height: 1.7; }' +\n                    '<\/style><\/head><body>' +\n                    '<div class=\"rahmen\"><h1>\ud83c\udfc5 Feuerwehr Willmatshofen<\/h1><h3>' + titel + '<\/h3><p>' + text + '<\/p><\/div>' +\n                    '<\/body><\/html>'\n                );\n                druckFenster.document.close();\n                druckFenster.focus();\n                setTimeout(function() { druckFenster.print(); }, 300);\n            });\n        });\n    })();\n    <\/script>\n        <\/div>\n\n    <script>\n    function ffssWaehlen(spiel) {\n        document.querySelectorAll('.ffss-kachel').forEach(function(k) {\n            k.classList.toggle('aktiv', k.dataset.spiel === spiel);\n        });\n        document.querySelectorAll('.ffss-spiel').forEach(function(s) {\n            s.classList.toggle('aktiv', s.id === 'ffss-spiel-' + spiel);\n        });\n        var ziel = document.getElementById('ffss-spiel-' + spiel);\n        if (ziel) ziel.scrollIntoView({ behavior: 'smooth', block: 'start' });\n    }\n    <\/script>\n    <\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"site-sidebar-layout":"no-sidebar","site-content-layout":"","ast-site-content-layout":"full-width-container","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-1248","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spiele - Feuerwehr Willmatshofen<\/title>\n<meta name=\"description\" content=\"Die Freiwillige Feuerwehr Willmatshofen \u2013 ehrenamtlich f\u00fcr unsere Gemeinde. Aktuelle Eins\u00e4tze, Termine und Infos zur Mitgliedschaft.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ff-willmatshofen.de\/spiele\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spiele - Feuerwehr Willmatshofen\" \/>\n<meta property=\"og:description\" content=\"Die Freiwillige Feuerwehr Willmatshofen \u2013 ehrenamtlich f\u00fcr unsere Gemeinde. Aktuelle Eins\u00e4tze, Termine und Infos zur Mitgliedschaft.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ff-willmatshofen.de\/spiele\/\" \/>\n<meta property=\"og:site_name\" content=\"Feuerwehr Willmatshofen\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-15T14:28:10+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/spiele\\\/\",\"url\":\"https:\\\/\\\/ff-willmatshofen.de\\\/spiele\\\/\",\"name\":\"Spiele - Feuerwehr Willmatshofen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/#website\"},\"datePublished\":\"2026-07-15T13:40:09+00:00\",\"dateModified\":\"2026-07-15T14:28:10+00:00\",\"description\":\"Die Freiwillige Feuerwehr Willmatshofen \u2013 ehrenamtlich f\u00fcr unsere Gemeinde. Aktuelle Eins\u00e4tze, Termine und Infos zur Mitgliedschaft.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/spiele\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/ff-willmatshofen.de\\\/spiele\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/spiele\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Start\",\"item\":\"https:\\\/\\\/ff-willmatshofen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Spiele\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/#website\",\"url\":\"https:\\\/\\\/ff-willmatshofen.de\\\/\",\"name\":\"Feuerwehr Willmatshofen\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/#organization\"},\"alternateName\":\"Freiwillige Feuerwehr Willmatshofen\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/ff-willmatshofen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/#organization\",\"name\":\"Feuerwehr Willmatshofen\",\"alternateName\":\"Freiwillige Feuerwehr Willmatshofen\",\"url\":\"https:\\\/\\\/ff-willmatshofen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/cropped-Feuerwehr-Logo-web-300x300-1.png\",\"contentUrl\":\"https:\\\/\\\/ff-willmatshofen.de\\\/wp-content\\\/uploads\\\/2026\\\/04\\\/cropped-Feuerwehr-Logo-web-300x300-1.png\",\"width\":300,\"height\":300,\"caption\":\"Feuerwehr Willmatshofen\"},\"image\":{\"@id\":\"https:\\\/\\\/ff-willmatshofen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/instagram.com\\\/ffwillmatshofen\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spiele - Feuerwehr Willmatshofen","description":"Die Freiwillige Feuerwehr Willmatshofen \u2013 ehrenamtlich f\u00fcr unsere Gemeinde. Aktuelle Eins\u00e4tze, Termine und Infos zur Mitgliedschaft.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ff-willmatshofen.de\/spiele\/","og_locale":"de_DE","og_type":"article","og_title":"Spiele - Feuerwehr Willmatshofen","og_description":"Die Freiwillige Feuerwehr Willmatshofen \u2013 ehrenamtlich f\u00fcr unsere Gemeinde. Aktuelle Eins\u00e4tze, Termine und Infos zur Mitgliedschaft.","og_url":"https:\/\/ff-willmatshofen.de\/spiele\/","og_site_name":"Feuerwehr Willmatshofen","article_modified_time":"2026-07-15T14:28:10+00:00","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/ff-willmatshofen.de\/spiele\/","url":"https:\/\/ff-willmatshofen.de\/spiele\/","name":"Spiele - Feuerwehr Willmatshofen","isPartOf":{"@id":"https:\/\/ff-willmatshofen.de\/#website"},"datePublished":"2026-07-15T13:40:09+00:00","dateModified":"2026-07-15T14:28:10+00:00","description":"Die Freiwillige Feuerwehr Willmatshofen \u2013 ehrenamtlich f\u00fcr unsere Gemeinde. Aktuelle Eins\u00e4tze, Termine und Infos zur Mitgliedschaft.","breadcrumb":{"@id":"https:\/\/ff-willmatshofen.de\/spiele\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ff-willmatshofen.de\/spiele\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/ff-willmatshofen.de\/spiele\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Start","item":"https:\/\/ff-willmatshofen.de\/"},{"@type":"ListItem","position":2,"name":"Spiele"}]},{"@type":"WebSite","@id":"https:\/\/ff-willmatshofen.de\/#website","url":"https:\/\/ff-willmatshofen.de\/","name":"Feuerwehr Willmatshofen","description":"","publisher":{"@id":"https:\/\/ff-willmatshofen.de\/#organization"},"alternateName":"Freiwillige Feuerwehr Willmatshofen","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ff-willmatshofen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/ff-willmatshofen.de\/#organization","name":"Feuerwehr Willmatshofen","alternateName":"Freiwillige Feuerwehr Willmatshofen","url":"https:\/\/ff-willmatshofen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/ff-willmatshofen.de\/#\/schema\/logo\/image\/","url":"https:\/\/ff-willmatshofen.de\/wp-content\/uploads\/2026\/04\/cropped-Feuerwehr-Logo-web-300x300-1.png","contentUrl":"https:\/\/ff-willmatshofen.de\/wp-content\/uploads\/2026\/04\/cropped-Feuerwehr-Logo-web-300x300-1.png","width":300,"height":300,"caption":"Feuerwehr Willmatshofen"},"image":{"@id":"https:\/\/ff-willmatshofen.de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/instagram.com\/ffwillmatshofen"]}]}},"_links":{"self":[{"href":"https:\/\/ff-willmatshofen.de\/wp-json\/wp\/v2\/pages\/1248","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ff-willmatshofen.de\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ff-willmatshofen.de\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ff-willmatshofen.de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ff-willmatshofen.de\/wp-json\/wp\/v2\/comments?post=1248"}],"version-history":[{"count":10,"href":"https:\/\/ff-willmatshofen.de\/wp-json\/wp\/v2\/pages\/1248\/revisions"}],"predecessor-version":[{"id":1266,"href":"https:\/\/ff-willmatshofen.de\/wp-json\/wp\/v2\/pages\/1248\/revisions\/1266"}],"wp:attachment":[{"href":"https:\/\/ff-willmatshofen.de\/wp-json\/wp\/v2\/media?parent=1248"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}