{"id":2171,"date":"2026-06-15T07:12:23","date_gmt":"2026-06-15T05:12:23","guid":{"rendered":"https:\/\/cad-kompass.de\/?p=2171"},"modified":"2026-06-26T17:59:14","modified_gmt":"2026-06-26T15:59:14","slug":"rettungsring","status":"publish","type":"post","link":"https:\/\/cad-kompass.de\/?p=2171","title":{"rendered":"Rettungsring"},"content":{"rendered":"\n<!--\n    (c) CAD-Kompass. Alle Rechte vorbehalten.\n    Dieses Tool einschliesslich Quellcode, Design und Logik ist geistiges\n    Eigentum von CAD-Kompass. Jegliche Vervielfaeltigung, Weitergabe oder\n    Einbindung auf fremden Webseiten ist ohne ausdrueckliche schriftliche\n    Genehmigung untersagt.\n-->\n<style>\n    .zz-box {\n        --zz-primary: #3f5f75;\n        --zz-primary-dark: #2c4a5e;\n        --zz-primary-deep: #1e3548;\n        --zz-accent: #e8913a;\n        --zz-ink: #1e293b;\n        --zz-text: #334155;\n        --zz-muted: #64748b;\n        --zz-faint: #94a3b8;\n        --zz-border: #c8d6e0;\n        --zz-surface: #f7f9fb;\n        background: var(--zz-surface);\n        border: 2px solid var(--zz-primary);\n        border-radius: 2px;\n        margin: 28px 0;\n        overflow: hidden;\n        position: relative;\n        font-family: inherit;\n        color: var(--zz-text);\n        line-height: 1.6;\n    }\n\n    \/* Top bar (Tool-Lab-Standard) *\/\n    .zz-header {\n        background: linear-gradient(135deg, var(--zz-primary-deep) 0%, var(--zz-primary-dark) 100%);\n        padding: 20px 28px 18px;\n        position: relative;\n        overflow: hidden;\n    }\n    .zz-header::after {\n        content: '';\n        position: absolute;\n        bottom: 0;\n        left: 0;\n        right: 0;\n        height: 3px;\n        background: repeating-linear-gradient(\n                90deg,\n                var(--zz-primary) 0px,\n                var(--zz-primary) 8px,\n                transparent 8px,\n                transparent 12px\n        );\n    }\n    .zz-header-top {\n        display: flex;\n        align-items: center;\n        gap: 12px;\n        margin-bottom: 6px;\n    }\n    .zz-header-icon {\n        width: 36px;\n        height: 36px;\n        flex-shrink: 0;\n        opacity: 0.85;\n    }\n    .zz-box .zz-box-title {\n        font-size: 1.15rem;\n        font-weight: 700;\n        color: #fff;\n        margin: 0;\n        padding: 0;\n        letter-spacing: 0.02em;\n        display: inline;\n    }\n    .zz-box .zz-box-desc {\n        font-size: 0.85rem;\n        color: rgba(255,255,255,0.65);\n        margin: 0;\n        padding: 0;\n        line-height: 1.5;\n        display: block;\n    }\n\n    \/* Body *\/\n    .zz-body {\n        padding: 22px 28px 24px;\n    }\n\n    \/* Privacy *\/\n    .zz-privacy {\n        background: #f0fdf4;\n        border: 1px solid #bbf7d0;\n        border-radius: 3px;\n        padding: 9px 14px;\n        margin-bottom: 20px;\n        font-size: 0.8rem;\n        color: #15803d;\n        line-height: 1.5;\n        display: flex;\n        align-items: center;\n        gap: 8px;\n    }\n    .zz-privacy::before {\n        content: '\\1F512';\n        flex-shrink: 0;\n        font-size: 0.9rem;\n    }\n\n    \/* Section label *\/\n    .zz-section-label {\n        display: flex;\n        align-items: center;\n        gap: 10px;\n        margin-bottom: 14px;\n        font-size: 0.72rem;\n        font-weight: 700;\n        text-transform: uppercase;\n        letter-spacing: 0.1em;\n        color: var(--zz-muted);\n    }\n    .zz-section-label::before,\n    .zz-section-label::after {\n        content: '';\n        height: 1px;\n        background: var(--zz-border);\n        flex: 1;\n    }\n    .zz-section-label::before {\n        max-width: 20px;\n    }\n\n    \/* Buttons (Tool-Lab-Standard) *\/\n    .zz-btn {\n        padding: 10px 24px;\n        font-size: 0.9rem;\n        font-family: inherit;\n        background: var(--zz-primary);\n        color: #fff;\n        border: none;\n        border-radius: 2px;\n        cursor: pointer;\n        white-space: nowrap;\n        font-weight: 600;\n        letter-spacing: 0.02em;\n        transition: background 0.15s;\n        position: relative;\n    }\n    .zz-btn:hover {\n        background: var(--zz-primary-dark);\n        color: #fff;\n    }\n    .zz-btn:disabled {\n        background: var(--zz-faint);\n        cursor: not-allowed;\n    }\n    .zz-btn::before {\n        content: '';\n        position: absolute;\n        left: 0;\n        top: 0;\n        bottom: 0;\n        width: 3px;\n        background: rgba(255,255,255,0.25);\n        border-radius: 2px 0 0 2px;\n    }\n    .zz-btn:focus-visible {\n        outline: 2px solid var(--zz-primary);\n        outline-offset: 2px;\n    }\n\n    \/* ====== Spielfl\u00e4che ====== *\/\n    .zz-stage {\n        position: relative;\n        background-color: #fdfdfd;\n        background-image: linear-gradient(#eef2f6 1px, transparent 1px), linear-gradient(90deg, #eef2f6 1px, transparent 1px);\n        background-size: 28px 28px;\n        border: 1px solid var(--zz-border);\n        border-radius: 2px;\n        padding: 22px;\n        margin-bottom: 18px;\n    }\n\n    \/* Arbeitsfl\u00e4che (stilisiertes Civil 3D) *\/\n    .zz-work {\n        position: relative;\n        max-width: 600px;\n        margin: 0 auto;\n        background: #fdfdfd;\n        border: 1px solid #9fb0bd;\n        border-radius: 3px;\n        overflow: hidden;\n        box-shadow: 0 10px 28px rgba(30,53,72,0.18), 0 2px 6px rgba(30,53,72,0.10);\n        cursor: pointer;\n        user-select: none;\n        -webkit-user-select: none;\n    }\n    .zz-work-titlebar {\n        display: flex;\n        align-items: center;\n        gap: 10px;\n        background: linear-gradient(180deg, var(--zz-primary), var(--zz-primary-dark));\n        color: #fff;\n        padding: 7px 12px;\n        font-size: 0.76rem;\n        font-weight: 600;\n    }\n    .zz-work-titlebar .zz-work-appicon {\n        width: 13px;\n        height: 13px;\n        border-radius: 2px;\n        background: var(--zz-accent);\n        flex-shrink: 0;\n    }\n    .zz-work-canvas {\n        position: relative;\n        height: 230px;\n        background: #fdfdfd;\n        transition: filter 0.15s ease;\n    }\n    .zz-work-canvas svg {\n        position: absolute;\n        inset: 0;\n        width: 100%;\n        height: 100%;\n    }\n    .zz-draw-line {\n        stroke-dasharray: 700;\n        stroke-dashoffset: 700;\n    }\n    .zz-work.zz-working .zz-draw-line {\n        animation: zzDrawing 6s linear infinite;\n    }\n    @keyframes zzDrawing {\n        0% { stroke-dashoffset: 700; }\n        100% { stroke-dashoffset: 0; }\n    }\n\n    \/* Freeze-Zustand *\/\n    .zz-work.zz-frozen .zz-work-canvas {\n        filter: grayscale(0.9) brightness(1.04);\n    }\n    .zz-work.zz-frozen .zz-draw-line {\n        animation-play-state: paused;\n    }\n    .zz-freeze-flag {\n        position: absolute;\n        top: 10px;\n        right: 10px;\n        display: none;\n        align-items: center;\n        gap: 7px;\n        background: rgba(255,255,255,0.92);\n        border: 1px solid #cdd6dd;\n        border-radius: 2px;\n        padding: 5px 10px;\n        font-size: 0.72rem;\n        font-weight: 700;\n        color: #b8432f;\n    }\n    .zz-work.zz-frozen .zz-freeze-flag {\n        display: flex;\n    }\n    .zz-freeze-flag .zz-hourglass {\n        width: 13px;\n        height: 13px;\n        animation: zzFlip 1s ease-in-out infinite;\n    }\n    @keyframes zzFlip {\n        0%, 40% { transform: rotate(0deg); }\n        60%, 100% { transform: rotate(180deg); }\n    }\n\n    .zz-work-status {\n        display: flex;\n        align-items: center;\n        justify-content: space-between;\n        gap: 10px;\n        background: #e9edf1;\n        border-top: 1px solid #d4dde4;\n        color: #8a98a3;\n        font-family: 'SF Mono', 'Consolas', monospace;\n        font-size: 0.7rem;\n        padding: 5px 12px;\n        white-space: nowrap;\n        overflow: hidden;\n    }\n    .zz-work-status .zz-save-led {\n        width: 9px;\n        height: 9px;\n        border-radius: 50%;\n        background: #b9c4cc;\n        flex-shrink: 0;\n    }\n    .zz-work.zz-frozen .zz-save-led {\n        background: #b8432f;\n    }\n\n    \/* Punkt in der Mitte: Meldetext *\/\n    .zz-work-msg {\n        position: absolute;\n        left: 50%;\n        top: 50%;\n        transform: translate(-50%, -50%);\n        background: rgba(255,255,255,0.92);\n        border: 1px solid #cdd6dd;\n        border-radius: 2px;\n        padding: 8px 16px;\n        font-size: 0.8rem;\n        font-weight: 700;\n        color: var(--zz-ink);\n        display: none;\n        text-align: center;\n        line-height: 1.45;\n        max-width: 90%;\n    }\n    .zz-work-msg.zz-show {\n        display: block;\n    }\n    .zz-work-msg small {\n        display: block;\n        font-weight: 600;\n        font-size: 0.7rem;\n        color: var(--zz-muted);\n        margin-top: 2px;\n    }\n\n    \/* Freigabe-Schleier + Pille *\/\n    .zz-veil {\n        position: absolute;\n        inset: 0;\n        z-index: 2;\n        background: rgba(247,249,251,0.65);\n        border-radius: 2px;\n        cursor: pointer;\n    }\n    .zz-veil.zz-gone {\n        display: none;\n    }\n    .zz-cta {\n        position: absolute;\n        top: 50%;\n        left: 50%;\n        z-index: 3;\n        display: flex;\n        flex-direction: column;\n        align-items: center;\n        justify-content: center;\n        gap: 5px;\n        background: var(--zz-primary);\n        color: #fff;\n        font-size: 0.78rem;\n        font-weight: 700;\n        letter-spacing: 0.02em;\n        line-height: 1.45;\n        padding: 11px 18px 10px;\n        border-radius: 2px;\n        box-shadow: 0 4px 14px rgba(30,53,72,0.35);\n        cursor: pointer;\n        white-space: normal;\n        text-align: center;\n        max-width: 96%;\n        animation: zzPulse 1.6s ease-in-out infinite;\n    }\n    .zz-cta svg {\n        width: 16px;\n        height: 16px;\n        flex-shrink: 0;\n    }\n    .zz-cta.zz-gone {\n        display: none;\n    }\n    @keyframes zzPulse {\n        0%, 100% { transform: translate(-50%, -50%) scale(1); }\n        50% { transform: translate(-50%, -50%) scale(1.05); }\n    }\n\n    \/* HUD *\/\n    .zz-hud {\n        display: flex;\n        align-items: stretch;\n        gap: 12px;\n        margin-top: 16px;\n        flex-wrap: wrap;\n        max-width: 600px;\n        margin-left: auto;\n        margin-right: auto;\n    }\n    .zz-hud-cell {\n        background: #fff;\n        border: 1px solid var(--zz-border);\n        border-left: 3px solid var(--zz-primary);\n        border-radius: 0 2px 2px 0;\n        padding: 8px 14px;\n        min-width: 96px;\n    }\n    .zz-hud-label {\n        font-size: 0.66rem;\n        font-weight: 700;\n        color: var(--zz-muted);\n        text-transform: uppercase;\n        letter-spacing: 0.08em;\n    }\n    .zz-hud-value {\n        font-size: 1.25rem;\n        font-weight: 700;\n        color: var(--zz-ink);\n        font-variant-numeric: tabular-nums;\n    }\n    .zz-rounds {\n        display: flex;\n        gap: 5px;\n        margin-top: 9px;\n    }\n    .zz-round-dot {\n        width: 14px;\n        height: 14px;\n        border-radius: 50%;\n        background: #e1e8ee;\n        border: 1px solid #d0dae2;\n    }\n    .zz-round-dot.zz-done {\n        background: var(--zz-primary);\n        border-color: var(--zz-primary);\n    }\n    .zz-round-dot.zz-failed {\n        background: #dc2626;\n        border-color: #dc2626;\n    }\n\n    .zz-hint {\n        font-size: 0.8rem;\n        color: var(--zz-muted);\n        line-height: 1.5;\n        margin: 14px auto 0;\n        max-width: 600px;\n    }\n\n    \/* Ergebnis *\/\n    .zz-result {\n        display: none;\n        background: #fff;\n        border: 1px solid var(--zz-border);\n        border-left: 3px solid var(--zz-primary);\n        border-radius: 0 2px 2px 0;\n        padding: 18px 22px;\n        margin-top: 18px;\n        margin-bottom: 18px;\n    }\n    .zz-result.zz-open {\n        display: block;\n        animation: zzRise 0.35s ease;\n    }\n    @keyframes zzRise {\n        from { opacity: 0; transform: translateY(8px); }\n        to { opacity: 1; transform: none; }\n    }\n    .zz-result-num {\n        font-size: 1.7rem;\n        font-weight: 700;\n        color: var(--zz-ink);\n        line-height: 1.2;\n    }\n    .zz-result-num small {\n        font-size: 0.85rem;\n        font-weight: 600;\n        color: var(--zz-muted);\n    }\n    .zz-result-rank {\n        font-size: 1rem;\n        font-weight: 700;\n        color: var(--zz-primary-dark);\n        margin: 10px 0 4px;\n    }\n    .zz-result-spruch {\n        font-size: 0.88rem;\n        color: var(--zz-text);\n        margin: 0 0 14px;\n    }\n\n    \/* ====== Bordbuch ====== *\/\n    .zz-board {\n        background: #fff;\n        border: 1px solid var(--zz-border);\n        border-radius: 2px;\n        padding: 16px 20px;\n    }\n    .zz-board-list {\n        list-style: none;\n        margin: 0;\n        padding: 0;\n    }\n    .zz-board-list li {\n        display: flex;\n        align-items: baseline;\n        gap: 10px;\n        padding: 5px 4px;\n        border-bottom: 1px solid #eef2f6;\n        font-size: 0.85rem;\n    }\n    .zz-board-list li:last-child {\n        border-bottom: none;\n    }\n    .zz-board-list li.zz-me {\n        background: #f0f7ff;\n    }\n    .zz-board-rank {\n        width: 24px;\n        text-align: right;\n        color: var(--zz-muted);\n        font-variant-numeric: tabular-nums;\n        flex-shrink: 0;\n    }\n    .zz-board-name {\n        flex: 1;\n        color: var(--zz-ink);\n        font-weight: 600;\n        overflow: hidden;\n        text-overflow: ellipsis;\n        white-space: nowrap;\n    }\n    .zz-board-score {\n        font-weight: 700;\n        color: var(--zz-primary-dark);\n        font-variant-numeric: tabular-nums;\n    }\n    .zz-board-empty {\n        font-size: 0.82rem;\n        color: var(--zz-muted);\n        margin: 0;\n    }\n    .zz-board-form {\n        display: none;\n        margin-top: 14px;\n        padding-top: 14px;\n        border-top: 1px solid #eef2f6;\n    }\n    .zz-board-form.zz-open {\n        display: block;\n    }\n    .zz-board-form-label {\n        font-size: 0.82rem;\n        color: var(--zz-text);\n        margin: 0 0 8px;\n    }\n    .zz-board-row {\n        display: flex;\n        gap: 8px;\n        flex-wrap: wrap;\n    }\n    .zz-board-row input {\n        flex: 1;\n        min-width: 160px;\n        padding: 10px 12px;\n        font-size: 0.92rem;\n        border: 1px solid var(--zz-border);\n        border-radius: 2px;\n        font-family: inherit;\n        color: var(--zz-ink);\n        background: #fff;\n        transition: border-color 0.15s, box-shadow 0.15s;\n        -webkit-appearance: none;\n    }\n    .zz-board-row input:focus {\n        outline: none;\n        border-color: var(--zz-primary);\n        box-shadow: 0 0 0 2px rgba(63,95,117,0.12);\n    }\n    .zz-board-row input::placeholder {\n        color: var(--zz-faint);\n    }\n    .zz-board-status {\n        font-size: 0.78rem;\n        color: var(--zz-muted);\n        margin: 10px 0 0;\n        line-height: 1.5;\n    }\n    .zz-board-status:empty {\n        display: none;\n    }\n\n    \/* Disclaimer *\/\n    .zz-disclaimer {\n        font-size: 0.76rem;\n        color: var(--zz-faint);\n        font-style: italic;\n        margin: 20px 0 0;\n        line-height: 1.5;\n        padding-top: 14px;\n        border-top: 1px solid #eef2f6;\n    }\n\n    @media (prefers-reduced-motion: reduce) {\n        .zz-cta { animation: none; transform: translate(-50%, -50%); }\n        .zz-work.zz-working .zz-draw-line { animation: none; stroke-dashoffset: 0; }\n        .zz-freeze-flag .zz-hourglass { animation: none; }\n        .zz-result.zz-open { animation: none; }\n    }\n    @media (max-width: 600px) {\n        .zz-header { padding: 16px 20px 14px; }\n        .zz-body { padding: 18px 20px 20px; }\n        .zz-stage { padding: 12px; }\n        .zz-work-canvas { height: 190px; }\n    }\n<\/style>\n\n<div class=\"zz-box\">\n    <div class=\"zz-header\">\n        <div class=\"zz-header-top\">\n            <svg class=\"zz-header-icon\" viewBox=\"0 0 36 36\" fill=\"none\">\n                <circle cx=\"18\" cy=\"18\" r=\"12\" stroke=\"rgba(255,255,255,0.85)\" stroke-width=\"2.4\"\/>\n                <circle cx=\"18\" cy=\"18\" r=\"5.5\" stroke=\"rgba(255,255,255,0.5)\" stroke-width=\"1\"\/>\n                <line x1=\"18\" y1=\"6\" x2=\"18\" y2=\"12.5\" stroke=\"rgba(255,255,255,0.5)\" stroke-width=\"1.6\"\/>\n                <line x1=\"18\" y1=\"23.5\" x2=\"18\" y2=\"30\" stroke=\"rgba(255,255,255,0.5)\" stroke-width=\"1.6\"\/>\n                <line x1=\"6\" y1=\"18\" x2=\"12.5\" y2=\"18\" stroke=\"rgba(255,255,255,0.5)\" stroke-width=\"1.6\"\/>\n                <line x1=\"23.5\" y1=\"18\" x2=\"30\" y2=\"18\" stroke=\"rgba(255,255,255,0.5)\" stroke-width=\"1.6\"\/>\n            <\/svg>\n            <span class=\"zz-box-title\">Rettungsring<\/span>\n        <\/div>\n        <span class=\"zz-box-desc\">Civil 3D zeichnet vor sich hin, und irgendwann friert das Bild ein. Wer dann am schnellsten speichert, rettet die Arbeit. F\u00fcnf Runden, gemessen wird in Millisekunden.<\/span>\n    <\/div>\n\n    <div class=\"zz-body\">\n        <div class=\"zz-privacy\">Das Spiel l\u00e4uft komplett in deinem Browser. Erst wenn du dich ins Bordbuch eintr\u00e4gst, werden Rufzeichen und Bestzeit gespeichert und \u00f6ffentlich gelistet.<\/div>\n\n        <div class=\"zz-section-label\">Reaktionstest<\/div>\n        <div class=\"zz-stage\" id=\"zzStage\">\n            <div class=\"zz-work\" id=\"zzWork\">\n                <div class=\"zz-work-titlebar\">\n                    <span class=\"zz-work-appicon\"><\/span>\n                    <span>Civil 3D 2026 &ndash; [Lageplan_Entwurf.dwg]<\/span>\n                <\/div>\n                <div class=\"zz-work-canvas\">\n                    <svg viewBox=\"0 0 560 230\" preserveAspectRatio=\"none\" aria-hidden=\"true\">\n                        <path d=\"M20 180 Q 120 130, 220 155 T 420 125 T 545 140\" fill=\"none\" stroke=\"#d8e0e6\" stroke-width=\"1.2\"\/>\n                        <path d=\"M35 155 Q 140 100, 240 128 T 430 95 T 548 110\" fill=\"none\" stroke=\"#d8e0e6\" stroke-width=\"1.2\"\/>\n                        <path class=\"zz-draw-line\" d=\"M30 200 L 140 140 L 250 165 L 360 80 L 470 105 L 535 70\" fill=\"none\" stroke=\"#3f5f75\" stroke-width=\"2\"\/>\n                        <circle cx=\"140\" cy=\"140\" r=\"3.5\" fill=\"none\" stroke=\"#a9bac6\" stroke-width=\"1.4\"\/>\n                        <circle cx=\"360\" cy=\"80\" r=\"3.5\" fill=\"none\" stroke=\"#a9bac6\" stroke-width=\"1.4\"\/>\n                    <\/svg>\n                    <div class=\"zz-freeze-flag\">\n                        <svg class=\"zz-hourglass\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n                            <path d=\"M3 1 L11 1 L11 3 L8 7 L11 11 L11 13 L3 13 L3 11 L6 7 L3 3 Z\" fill=\"none\" stroke=\"#b8432f\" stroke-width=\"1.2\" stroke-linejoin=\"round\"\/>\n                            <path d=\"M5 2.5 L9 2.5 L7 5.5 Z\" fill=\"#b8432f\"\/>\n                        <\/svg>\n                        Eingefroren! Speichern!\n                    <\/div>\n                    <div class=\"zz-work-msg\" id=\"zzMsg\"><\/div>\n                <\/div>\n                <div class=\"zz-work-status\">\n                    <span id=\"zzStatusText\">Befehl: ACHSE &nbsp;Punkt angeben &hellip;<\/span>\n                    <span class=\"zz-save-led\" aria-hidden=\"true\"><\/span>\n                <\/div>\n            <\/div>\n\n            <div class=\"zz-veil\" id=\"zzVeil\"><\/div>\n            <div class=\"zz-cta\" id=\"zzCta\" role=\"button\" aria-label=\"Reaktionstest starten\">\n                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n                    <path d=\"M5 3 L5 17 L9 13.5 L11.5 19 L14 18 L11.5 12.5 L17 12.5 Z\" fill=\"currentColor\" stroke=\"none\"\/>\n                <\/svg>\n                <span>Klick zum Start. Speichere, sobald das Bild einfriert.<\/span>\n            <\/div>\n        <\/div>\n\n        <div class=\"zz-hud\">\n            <div class=\"zz-hud-cell\">\n                <div class=\"zz-hud-label\">Letzte Reaktion<\/div>\n                <div class=\"zz-hud-value\"><span id=\"zzLast\">&ndash;<\/span><\/div>\n            <\/div>\n            <div class=\"zz-hud-cell\">\n                <div class=\"zz-hud-label\">Runden<\/div>\n                <div class=\"zz-rounds\" id=\"zzRounds\">\n                    <span class=\"zz-round-dot\"><\/span><span class=\"zz-round-dot\"><\/span><span class=\"zz-round-dot\"><\/span><span class=\"zz-round-dot\"><\/span><span class=\"zz-round-dot\"><\/span>\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <p class=\"zz-hint\">Sobald die Zeichnung einfriert (Bild wird grau, Sanduhr erscheint), speicherst du: Klick auf die Zeichenfl\u00e4che, Leertaste oder ganz stilecht Strg+S. Wer vor dem Einfrieren speichert, kassiert einen Fehlstart mit 999 ms Strafzeit.<\/p>\n\n        <div class=\"zz-result\" id=\"zzResult\">\n            <div class=\"zz-result-num\"><span id=\"zzResAvg\">0<\/span>&thinsp;ms <small>im Schnitt (beste Runde: <span id=\"zzResBest\">0<\/span>&thinsp;ms)<\/small><\/div>\n            <div class=\"zz-result-rank\" id=\"zzResRank\"><\/div>\n            <p class=\"zz-result-spruch\" id=\"zzResSpruch\"><\/p>\n            <button type=\"button\" class=\"zz-btn\" id=\"zzAgain\">Noch ein Durchgang<\/button>\n        <\/div>\n\n        <div class=\"zz-section-label\">Bordbuch<\/div>\n        <div class=\"zz-board\">\n            <ol class=\"zz-board-list\" id=\"zzBoardList\"><\/ol>\n            <p class=\"zz-board-empty\" id=\"zzBoardEmpty\">Noch keine Eintr\u00e4ge. Der erste Rettungsring geh\u00f6rt dir.<\/p>\n            <div class=\"zz-board-form\" id=\"zzBoardForm\">\n                <p class=\"zz-board-form-label\" id=\"zzBoardFormLabel\">Trag dein Ergebnis ein:<\/p>\n                <div class=\"zz-board-row\">\n                    <input type=\"text\" id=\"zzName\" maxlength=\"12\" placeholder=\"Dein Rufzeichen (3&ndash;12 Zeichen)\" autocomplete=\"off\">\n                    <button type=\"button\" class=\"zz-btn\" id=\"zzSubmit\">Eintragen<\/button>\n                <\/div>\n            <\/div>\n            <p class=\"zz-board-status\" id=\"zzBoardStatus\"><\/p>\n        <\/div>\n\n        <p class=\"zz-disclaimer\">Im echten Leben hilft nur, was vor dem Einfrieren gespeichert war. Aber das wei\u00dft du ja.<\/p>\n    <\/div>\n<\/div>\n\n<script>\n(function () {\n    'use strict';\n\n    var ROUNDS = 5;\n    var FALSE_START_MS = 999;\n\n    var RANKS = [\n        { max: 220,  name: 'Blitzableiter',     text: 'Du speicherst, bevor der Schreck \u00fcberhaupt ankommt. Beeindruckend und leicht beunruhigend.' },\n        { max: 300,  name: 'Alte H\u00e4sin \/ alter Hase', text: 'Reflexe wie nach zehn Jahren Projektgesch\u00e4ft. Strg+S ist bei dir Muskelged\u00e4chtnis.' },\n        { max: 400,  name: 'Wachsamer Ausguck', text: 'Ordentliche Reaktion. Die Zeichnung h\u00e4tte \u00fcberlebt.' },\n        { max: 550,  name: 'Gem\u00fctlicher Smutje', text: 'Du hast erst den Kaffee abgestellt, dann gespeichert. Verst\u00e4ndlich.' },\n        { max: 9999, name: 'Tiefenentspannt',   text: 'Bis du speicherst, hat die Wiederherstellung schon dreimal gefragt. Zen hast du jedenfalls.' }\n    ];\n\n    var stage = document.getElementById('zzStage');\n    var work = document.getElementById('zzWork');\n    var msg = document.getElementById('zzMsg');\n    var statusText = document.getElementById('zzStatusText');\n    var lastEl = document.getElementById('zzLast');\n    var roundDots = document.querySelectorAll('#zzRounds .zz-round-dot');\n    var veil = document.getElementById('zzVeil');\n    var cta = document.getElementById('zzCta');\n    var resultEl = document.getElementById('zzResult');\n    var resAvg = document.getElementById('zzResAvg');\n    var resBest = document.getElementById('zzResBest');\n    var resRank = document.getElementById('zzResRank');\n    var resSpruch = document.getElementById('zzResSpruch');\n    var againBtn = document.getElementById('zzAgain');\n\n    var STATUS_LINES = [\n        'Befehl: ACHSE  Punkt angeben \u2026',\n        'Befehl: BRUCHKANTE  Objekte w\u00e4hlen \u2026',\n        'Befehl: QPROFIL  Station angeben \u2026',\n        'Befehl: DGM aktualisieren \u2026',\n        'Befehl: BEMASSUNG  Position w\u00e4hlen \u2026'\n    ];\n\n    \/* running: Durchgang aktiv. armed: Freeze sichtbar, warte auf Speichern. *\/\n    var state = null;\n\n    function freshState() {\n        return { running: false, armed: false, round: 0, times: [], armTimer: null, t0: 0, betweenTimer: null };\n    }\n    state = freshState();\n\n    function setDots() {\n        var i;\n        for (i = 0; i < roundDots.length; i++) {\n            roundDots[i].classList.remove('zz-done');\n            roundDots[i].classList.remove('zz-failed');\n            if (i < state.times.length) {\n                if (state.times[i] >= FALSE_START_MS) {\n                    roundDots[i].classList.add('zz-failed');\n                } else {\n                    roundDots[i].classList.add('zz-done');\n                }\n            }\n        }\n    }\n\n    function showMsg(main, sub) {\n        msg.textContent = '';\n        var span = document.createElement('span');\n        span.textContent = main;\n        msg.appendChild(span);\n        if (sub) {\n            var small = document.createElement('small');\n            small.textContent = sub;\n            msg.appendChild(small);\n        }\n        msg.classList.add('zz-show');\n    }\n\n    function hideMsg() {\n        msg.classList.remove('zz-show');\n    }\n\n    function armRound() {\n        if (!state.running) { return; }\n        hideMsg();\n        work.classList.add('zz-working');\n        work.classList.remove('zz-frozen');\n        statusText.textContent = STATUS_LINES[Math.floor(Math.random() * STATUS_LINES.length)];\n        var wait = 1800 + Math.random() * 3700;\n        state.armTimer = setTimeout(function () {\n            if (!state.running) { return; }\n            state.armed = true;\n            state.t0 = performance.now();\n            work.classList.remove('zz-working');\n            work.classList.add('zz-frozen');\n            statusText.textContent = 'Keine R\u00fcckmeldung \u2026';\n        }, wait);\n    }\n\n    function roundDone(ms, falseStart) {\n        state.armed = false;\n        clearTimeout(state.armTimer);\n        work.classList.remove('zz-frozen');\n        work.classList.remove('zz-working');\n        state.times.push(ms);\n        state.round += 1;\n        lastEl.textContent = ms + ' ms';\n        setDots();\n\n        if (falseStart) {\n            showMsg('Fehlstart: ' + FALSE_START_MS + ' ms Strafzeit.', 'Du hast gespeichert, bevor etwas passiert ist. Respekt, aber nein.');\n        } else {\n            showMsg(ms + ' ms. Gespeichert.', ms < 300 ? 'Saubere Rettung.' : 'Die Zeichnung hat es \u00fcberlebt.');\n        }\n\n        if (state.round >= ROUNDS) {\n            state.betweenTimer = setTimeout(end, 1100);\n        } else {\n            state.betweenTimer = setTimeout(armRound, 1400);\n        }\n    }\n\n    function react() {\n        if (!state.running) { return; }\n        if (state.armed) {\n            var ms = Math.max(1, Math.round(performance.now() - state.t0));\n            roundDone(ms, false);\n        } else {\n            roundDone(FALSE_START_MS, true);\n        }\n    }\n\n    function start() {\n        clearTimeout(state.armTimer);\n        clearTimeout(state.betweenTimer);\n        state = freshState();\n        state.running = true;\n        lastEl.textContent = '\u2013';\n        setDots();\n        hideMsg();\n        resultEl.classList.remove('zz-open');\n        veil.classList.add('zz-gone');\n        cta.classList.add('zz-gone');\n        armRound();\n    }\n\n    function end() {\n        state.running = false;\n        work.classList.remove('zz-working');\n        work.classList.remove('zz-frozen');\n        hideMsg();\n        statusText.textContent = 'Befehl: _';\n\n        var sum = 0;\n        var best = 99999;\n        var i;\n        for (i = 0; i < state.times.length; i++) {\n            sum += state.times[i];\n            if (state.times[i] < best) { best = state.times[i]; }\n        }\n        var avg = Math.round(sum \/ state.times.length);\n\n        var rank = RANKS[RANKS.length - 1];\n        for (i = RANKS.length - 1; i >= 0; i--) {\n            if (avg <= RANKS[i].max) { rank = RANKS[i]; }\n        }\n\n        resAvg.textContent = avg;\n        resBest.textContent = best;\n        resRank.textContent = 'Einstufung: ' + rank.name;\n        resSpruch.textContent = rank.text;\n        resultEl.classList.add('zz-open');\n\n        lastScore = avg;\n        submitted = false;\n        submitBtn.disabled = false;\n        if (lastScore >= 80) {\n            boardFormLabel.textContent = 'Dein Schnitt: ' + lastScore + ' ms. Trag dich ins Bordbuch ein (niedrigste Zeit gewinnt):';\n            if (!nameInput.value) {\n                var saved = '';\n                try { saved = localStorage.getItem(NAME_KEY) || ''; } catch (err) { saved = ''; }\n                nameInput.value = saved;\n            }\n            boardForm.classList.add('zz-open');\n        } else {\n            boardForm.classList.remove('zz-open');\n            boardStatus.textContent = 'Unter 80 ms glaubt dir das Bordbuch nicht. Sorry.';\n        }\n        loadBoard(null);\n    }\n\n    stage.addEventListener('click', function (e) {\n        var gate = e.target.closest ? e.target.closest('#zzCta, #zzVeil') : null;\n        if (gate) {\n            if (!state.running) { start(); }\n            return;\n        }\n        var onWork = e.target.closest ? e.target.closest('#zzWork') : null;\n        if (onWork) { react(); }\n    });\n\n    document.addEventListener('keydown', function (e) {\n        if (!state.running) { return; }\n        var isSpace = e.key === ' ' ? true : e.code === 'Space';\n        var isCtrlS = false;\n        if (e.key === 's') { isCtrlS = e.ctrlKey ? true : e.metaKey; }\n        if (e.key === 'S') { isCtrlS = e.ctrlKey ? true : e.metaKey; }\n        if (isSpace) {\n            e.preventDefault();\n            react();\n            return;\n        }\n        if (isCtrlS) {\n            e.preventDefault();\n            react();\n        }\n    });\n\n    againBtn.addEventListener('click', function () {\n        boardForm.classList.remove('zz-open');\n        boardStatus.textContent = '';\n        start();\n    });\n\n    \/* ====== Bordbuch: global \u00fcber REST, lokaler Fallback ====== *\/\n    var API_URL = '\/?rest_route=\/zenzorn\/v1\/scores\/rettungsring';\n    var LOCAL_BOARD_KEY = 'zz-board-rettungsring';\n    var NAME_KEY = 'zz-bordname';\n    var NAME_RE = \/^[A-Za-z0-9\u00c4\u00d6\u00dc\u00e4\u00f6\u00fc\u00df._\\- ]{3,12}$\/;\n\n    var boardList = document.getElementById('zzBoardList');\n    var boardEmpty = document.getElementById('zzBoardEmpty');\n    var boardForm = document.getElementById('zzBoardForm');\n    var boardFormLabel = document.getElementById('zzBoardFormLabel');\n    var boardStatus = document.getElementById('zzBoardStatus');\n    var nameInput = document.getElementById('zzName');\n    var submitBtn = document.getElementById('zzSubmit');\n\n    var boardToken = null;\n    var remoteMode = true;\n    var submitted = false;\n    var lastScore = 0;\n\n    function localRead() {\n        var raw = null;\n        try { raw = localStorage.getItem(LOCAL_BOARD_KEY); } catch (err) { raw = null; }\n        if (!raw) { return []; }\n        var list = [];\n        try { list = JSON.parse(raw); } catch (err) { list = []; }\n        return Array.isArray(list) ? list : [];\n    }\n\n    function localAdd(name, score) {\n        var list = localRead();\n        list.push({ name: name, score: score });\n        list.sort(function (a, b) { return a.score - b.score; });\n        list = list.slice(0, 10);\n        try { localStorage.setItem(LOCAL_BOARD_KEY, JSON.stringify(list)); } catch (err) { \/* localStorage gesperrt *\/ }\n        return list;\n    }\n\n    function renderBoard(list, own) {\n        boardList.textContent = '';\n        var shown = list.slice(0, 10);\n        boardEmpty.style.display = shown.length === 0 ? '' : 'none';\n        var ownMarked = false;\n        var i;\n        for (i = 0; i < shown.length; i++) {\n            var li = document.createElement('li');\n            var rank = document.createElement('span');\n            rank.className = 'zz-board-rank';\n            rank.textContent = (i + 1) + '.';\n            var nm = document.createElement('span');\n            nm.className = 'zz-board-name';\n            nm.textContent = shown[i].name;\n            var sc = document.createElement('span');\n            sc.className = 'zz-board-score';\n            sc.textContent = shown[i].score + ' ms';\n            li.appendChild(rank);\n            li.appendChild(nm);\n            li.appendChild(sc);\n            if (own) {\n                if (!ownMarked) {\n                    if (shown[i].name === own.name) {\n                        if (shown[i].score === own.score) {\n                            li.classList.add('zz-me');\n                            ownMarked = true;\n                        }\n                    }\n                }\n            }\n            boardList.appendChild(li);\n        }\n    }\n\n    function loadBoard(own) {\n        fetch(API_URL, { cache: 'no-store' })\n            .then(function (r) {\n                if (!r.ok) { throw new Error('http'); }\n                return r.json();\n            })\n            .then(function (data) {\n                remoteMode = true;\n                boardToken = data.token;\n                renderBoard(data.scores || [], own || null);\n            })\n            .catch(function () {\n                remoteMode = false;\n                boardToken = null;\n                renderBoard(localRead(), own || null);\n                boardStatus.textContent = 'Keine Verbindung zum Server. Das Bordbuch l\u00e4uft gerade nur lokal auf diesem Ger\u00e4t.';\n            });\n    }\n\n    function submitScore() {\n        if (submitted) { return; }\n        var name = nameInput.value.trim();\n        if (!NAME_RE.test(name)) {\n            boardStatus.textContent = 'Rufzeichen bitte 3 bis 12 Zeichen: Buchstaben, Zahlen, Punkt, Strich.';\n            return;\n        }\n        try { localStorage.setItem(NAME_KEY, name); } catch (err) { \/* localStorage gesperrt *\/ }\n        if (!remoteMode) {\n            var list = localAdd(name, lastScore);\n            submitted = true;\n            boardForm.classList.remove('zz-open');\n            renderBoard(list, { name: name, score: lastScore });\n            boardStatus.textContent = 'Lokal eingetragen (nur auf diesem Ger\u00e4t sichtbar).';\n            return;\n        }\n        submitBtn.disabled = true;\n        boardStatus.textContent = 'Wird eingetragen \u2026';\n        fetch(API_URL, {\n            method: 'POST',\n            headers: { 'Content-Type': 'application\/json' },\n            body: JSON.stringify({ name: name, score: lastScore, token: boardToken, website: '' })\n        })\n            .then(function (r) {\n                return r.json().then(function (d) { return { ok: r.ok, data: d }; });\n            })\n            .then(function (res) {\n                if (res.ok) {\n                    submitted = true;\n                    boardForm.classList.remove('zz-open');\n                    renderBoard(res.data.scores || [], { name: name, score: lastScore });\n                    boardStatus.textContent = 'Eingetragen. Willkommen im Bordbuch, ' + name + '.';\n                } else {\n                    submitBtn.disabled = false;\n                    var msgTxt = res.data ? res.data.message : '';\n                    boardStatus.textContent = msgTxt ? msgTxt : 'Der Eintrag wurde abgelehnt.';\n                    loadBoard(null);\n                }\n            })\n            .catch(function () {\n                submitBtn.disabled = false;\n                boardStatus.textContent = 'Verbindung fehlgeschlagen. Versuch es gleich nochmal.';\n            });\n    }\n\n    submitBtn.addEventListener('click', submitScore);\n    nameInput.addEventListener('keydown', function (e) {\n        if (e.key === 'Enter') { submitScore(); }\n    });\n\n    loadBoard(null);\n})();\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>Rettungsring Civil 3D zeichnet vor sich hin, und irgendwann friert das Bild ein. Wer dann am schnellsten speichert, rettet die [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"disabled","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":"","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":""},"categories":[41],"tags":[],"class_list":["post-2171","post","type-post","status-publish","format-standard","hentry","category-zen-zorn"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":false,"author_link":"https:\/\/cad-kompass.de\/?author=1"},"uagb_comment_info":0,"uagb_excerpt":"Rettungsring Civil 3D zeichnet vor sich hin, und irgendwann friert das Bild ein. Wer dann am schnellsten speichert, rettet die [&hellip;]","_links":{"self":[{"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/posts\/2171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2171"}],"version-history":[{"count":1,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/posts\/2171\/revisions"}],"predecessor-version":[{"id":2172,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=\/wp\/v2\/posts\/2171\/revisions\/2172"}],"wp:attachment":[{"href":"https:\/\/cad-kompass.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2171"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2171"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cad-kompass.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}