{"id":11,"date":"2025-05-23T13:48:49","date_gmt":"2025-05-23T13:48:49","guid":{"rendered":"https:\/\/plzprofi.de\/start\/"},"modified":"2026-04-22T08:03:59","modified_gmt":"2026-04-22T08:03:59","slug":"start","status":"publish","type":"page","link":"https:\/\/plzprofi.de\/lt\/","title":{"rendered":"Start"},"content":{"rendered":"\n<link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet\/dist\/leaflet.css\" \/>\n\n<style>\n  :root { font-size: 90%; }\n\n  \/* === Grundlayout f\u00fcr Seite \/ Sektionen === *\/\n  body {\n    background: #050814;\n    color: #ffffff;\n    font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n  }\n\n  \/* === TIPP DES TAGES BANNER === *\/\n  .plzprofi-topbar-wrap {\n    background: linear-gradient(90deg, rgba(15, 23, 42, 0.8) 0%, rgba(30, 41, 59, 0.8) 50%, rgba(15, 23, 42, 0.8) 100%);\n    border: 1px solid rgba(56, 189, 248, 0.3);\n    border-radius: 12px;\n    margin-bottom: 16px;\n    color: #e2e8f0;\n    font-size: 13px;\n    padding: 10px 16px;\n    display: none;\n    justify-content: center;\n    align-items: center;\n    position: relative;\n    z-index: 1000;\n    box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n  }\n\n  .plzprofi-topbar-content {\n    display: flex;\n    align-items: center;\n    gap: 10px;\n    text-align: center;\n    line-height: 1.4;\n  }\n\n  .plzprofi-topbar-icon {\n    font-size: 16px;\n    animation: gentle-bounce 2s infinite ease-in-out;\n  }\n\n  .plzprofi-topbar-link {\n    color: #38bdf8;\n    text-decoration: none;\n    font-weight: 600;\n    margin-left: 6px;\n    padding: 2px 8px;\n    border-radius: 999px;\n    background: rgba(56, 189, 248, 0.1);\n    transition: all 0.2s ease;\n    white-space: nowrap;\n  }\n  \n  .plzprofi-topbar-link:hover {\n    background: rgba(56, 189, 248, 0.25);\n    color: #bae6fd;\n  }\n\n  .plzprofi-topbar-close {\n    position: absolute;\n    right: 12px;\n    background: transparent;\n    border: none;\n    color: #64748b;\n    cursor: pointer;\n    font-size: 16px;\n    padding: 4px;\n    transition: color 0.2s;\n  }\n\n  .plzprofi-topbar-close:hover {\n    color: #f8fafc;\n  }\n\n  @keyframes gentle-bounce {\n    0%, 100% { transform: translateY(0); }\n    50% { transform: translateY(-3px); }\n  }\n\n  @media (max-width: 600px) {\n    .plzprofi-topbar-content { flex-direction: column; gap: 4px; font-size: 12px; }\n    .plzprofi-topbar-close { top: 4px; right: 8px; }\n  }\n\n  \/* === HERO BEREICH === *\/\n  .plzprofi-hero {\n    margin: 32px 16px 24px;\n    padding: 48px 32px 40px;\n    background:\n      radial-gradient(circle at top left, rgba(59, 130, 246, 0.22), transparent 55%),\n      radial-gradient(circle at top right, rgba(168, 85, 247, 0.18), transparent 55%),\n      #050814;\n    border-radius: 28px;\n    border: 1px solid rgba(148, 163, 184, 0.18);\n    box-shadow: 0 30px 80px rgba(15, 23, 42, 0.9), 0 0 0 1px rgba(15, 23, 42, 0.6);\n    overflow: hidden;\n  }\n\n  .plzprofi-hero-inner { max-width: 1280px; margin: 0 auto; display: flex; gap: 48px; align-items: center; }\n  .plzprofi-hero-left { flex: 1 1 50%; }\n  .plzprofi-hero-right { flex: 1 1 50%; display: flex; justify-content: center; }\n\n  .hero-kicker {\n    display: inline-flex; align-items: center; gap: 8px; padding: 4px 10px; border-radius: 999px;\n    font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; background: rgba(15, 23, 42, 0.8);\n    border: 1px solid rgba(56, 189, 248, 0.35); color: #7dd3fc; margin-bottom: 14px;\n  }\n  .hero-kicker::before {\n    content: \"\"; width: 6px; height: 6px; border-radius: 999px; background: #22c55e;\n    box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.9); animation: plzprofi-pulse-dot 1.6s infinite ease-out;\n  }\n\n  .plzprofi-hero-left h1 { font-size: clamp(32px, 4vw, 40px); line-height: 1.1; margin: 0 0 14px; }\n  .plzprofi-hero-left p { margin: 0 0 24px; font-size: 15px; max-width: 36rem; color: #e5e7eb; }\n\n  .hero-btn {\n    display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 12px 26px;\n    border-radius: 999px; font-size: 14px; font-weight: 500; color: #ffffff; text-decoration: none;\n    background: linear-gradient(135deg, #2563eb, #1d4ed8); box-shadow: 0 18px 40px rgba(37, 99, 235, 0.55);\n    border: none; cursor: pointer; transition: transform 0.15s ease, filter 0.15s ease;\n  }\n  .hero-btn:hover { transform: translateY(-1px); filter: brightness(1.05); }\n\n  .hero-card {\n    width: 100%; max-width: 520px; aspect-ratio: 4 \/ 3; border-radius: 24px; position: relative; overflow: hidden;\n    background: radial-gradient(circle at center, rgba(59, 130, 246, 0.25), rgba(15, 23, 42, 0.98)), #020617;\n    box-shadow: 0 24px 80px rgba(15, 23, 42, 0.9), 0 0 0 1px rgba(148, 163, 184, 0.28);\n  }\n  .hero-card::before {\n    content: \"\"; position: absolute; inset: 0;\n    background-image: url('https:\/\/plzprofi.de\/wp-content\/uploads\/2025\/11\/DE-AT-Map-bearbeitet.png');\n    background-size: cover; background-position: center; opacity: 0.95; mix-blend-mode: screen;\n  }\n\n  @media (max-width: 960px) {\n    .plzprofi-hero-inner { flex-direction: column; align-items: flex-start; }\n    .plzprofi-hero-right { width: 100%; }\n  }\n\n  \/* === Tool Layout === *\/\n  .wrapper { max-width: 1280px; margin: 0 auto; padding: 16px 16px 40px; }\n\n  .panel {\n    position: relative; text-align: center; padding: 8px; display: flex; gap: 10px;\n    align-items: center; justify-content: center; flex-wrap: wrap;\n  }\n\n  label, input, button, select { font-size: 14px; }\n  \n  \/* NEU: Autocomplete Wrapper & Styles *\/\n  .search-input-wrapper { position: relative; display: inline-block; text-align: left; width: 240px; }\n  .search-input-wrapper input[type=\"text\"] { width: 100%; padding: 6px 8px; border: none; border-radius: 4px; box-sizing: border-box; }\n  \n  .main-autocomplete {\n    position: absolute; top: 110%; left: 0; right: 0; background: #1e293b; border: 1px solid #334155; \n    border-radius: 6px; z-index: 9999; display: none; box-shadow: 0 10px 25px rgba(0,0,0,0.8); overflow: hidden;\n  }\n  .main-sugg {\n    padding: 8px 12px; cursor: pointer; border-bottom: 1px solid rgba(255,255,255,0.05); \n    font-size: 13px; color: #fff; transition: background 0.1s; outline: none;\n  }\n  .main-sugg:hover, .main-sugg:focus { background: #38bdf8; color: #020617; }\n  .main-sugg strong { color: #38bdf8; transition: color 0.1s; margin-right: 4px; }\n  .main-sugg:hover strong, .main-sugg:focus strong { color: #020617; }\n\n  input[type=\"number\"] { width: 64px; padding: 5px 6px; border-radius: 4px; border: none; }\n  input[type=\"range\"] { vertical-align: middle; width: 140px; -webkit-appearance: none; height: 6px; background: #444; border-radius: 3px; outline: none; accent-color: #0af; }\n  input[type=\"range\"]::-webkit-slider-thumb { -webkit-appearance: none; width: 16px; height: 16px; background: #00bfff; border-radius: 50%; border: 2px solid #fff; cursor: pointer; }\n  #radiusLabel { margin: 0 5px; display: inline-block; min-width: 30px; }\n\n  button { padding: 6px 10px; background: #2a2a2a; color: #fff; border: none; cursor: pointer; border-radius: 6px; }\n  button:hover { background: #333; }\n  #btnSearch { background: #3b82f6; font-weight: bold; padding: 8px 16px;}\n  #btnSearch:hover { background: #2563eb; }\n\n  .seg { display: inline-flex; background: #2a2a2a; border-radius: 999px; overflow: hidden; }\n  .seg-btn { padding: 6px 12px; border-radius: 999px; background: transparent; border: none; color: #e5e7eb; cursor: pointer; }\n  .seg-btn.active { background: #00bfff; color: #00121a; }\n  \n  #countrySwitch, #countrySwitch * { translate: no; }\n  #countrySwitch .seg-label::after { content: attr(data-label); }\n\n  \/* === Speed Gadget & Result Badges === *\/\n  .result-badges { display: flex; gap: 4px; align-items: center; }\n  .badge { padding: 3px 6px; border-radius: 999px; background: rgba(0, 191, 255, 0.12); border: 1px solid rgba(0, 191, 255, 0.35); color: #d7f6ff; font-size: 11px; white-space: nowrap; }\n  \n  .badge-road {\n    background: rgba(148, 163, 184, 0.1) !important;\n    border: 1px solid rgba(148, 163, 184, 0.2) !important;\n    color: #94a3b8 !important;\n    transition: all 0.3s ease;\n    cursor: default;\n  }\n  \n  .badge-road.active {\n    background: rgba(34, 197, 94, 0.15) !important;\n    border-color: rgba(34, 197, 94, 0.5) !important;\n    color: #4ade80 !important;\n    font-weight: bold;\n  }\n\n  .badge-time {\n    background: rgba(234, 179, 8, 0.15) !important;\n    border: 1px solid rgba(234, 179, 8, 0.5) !important;\n    color: #fde047 !important;\n    font-size: 11px;\n    font-weight: bold;\n    padding: 3px 6px;\n    border-radius: 999px;\n    white-space: nowrap;\n    display: none;\n    align-items: center;\n    gap: 3px;\n  }\n  .badge-time.active {\n    display: inline-flex;\n  }\n\n  .legend-box {\n    display: flex; justify-content: space-around; font-size: 11px; color: #94a3b8; \n    background: #1f2937; padding: 8px; border-radius: 6px; margin: 0 12px 10px 12px;\n    border: 1px solid rgba(255,255,255,0.05);\n  }\n  .legend-item { display: flex; align-items: center; gap: 6px; font-weight: 500; }\n  .legend-dot { width: 8px; height: 8px; border-radius: 50%; }\n\n  .loading-dots:after {\n    content: '...';\n    animation: plzprofi-dots 1.5s steps(5, end) infinite;\n  }\n  @keyframes plzprofi-dots {\n    0%, 20% { color: rgba(0,0,0,0); text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0); }\n    40% { color: #4ade80; text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0); }\n    60% { text-shadow: .25em 0 0 #4ade80, .5em 0 0 rgba(0,0,0,0); }\n    80%, 100% { text-shadow: .25em 0 0 #4ade80, .5em 0 0 #4ade80; }\n  }\n\n  #main { display: flex; justify-content: center; align-items: flex-start; gap: 16px; margin-top: 16px; }\n\n  \/* === Linke Spalte (Kompass & Verlauf) === *\/\n  #leftCol { width: 220px; display: flex; flex-direction: column; gap: 16px; flex-shrink: 0; }\n\n  .card { background: #111827; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); padding: 12px; }\n  .card h3 { margin: 0 0 10px 0; font-size: 15px; border-bottom: 1px solid rgba(255,255,255,0.1); padding-bottom: 6px; }\n\n  .compass-module {\n    display: flex; align-items: center; gap: 12px; background: #1f2937; padding: 10px;\n    border-radius: 8px; border: 1px solid rgba(148, 163, 184, 0.1); justify-content: flex-start;\n  }\n\n  .compass-canvas-wrap {\n    position: relative; width: 64px; height: 64px; border-radius: 50%;\n    background: radial-gradient(circle, #0f172a 0%, #020617 100%);\n    box-shadow: inset 0 0 10px rgba(0, 191, 255, 0.2); border: 2px solid #334155; cursor: pointer; flex-shrink: 0;\n  }\n  #compassCanvas { position: absolute; top: 0; left: 0; border-radius: 50%; width: 100%; height: 100%; }\n\n  .compass-controls { display: flex; flex-direction: column; gap: 8px; flex: 1; align-items: flex-start; }\n  \n  .compass-toggle-group {\n    display: inline-flex; background: #111827; border-radius: 999px; overflow: hidden; border: 1px solid rgba(148,163,184,0.2);\n  }\n  \n  .compass-toggle-btn {\n    display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; font-size: 11px; \n    border: none; background: transparent; color: #64748b; cursor: pointer; transition: 0.2s;\n  }\n  #btnCompOff.active { background: rgba(239, 68, 68, 0.15); color: #ef4444; font-weight: bold; }\n  #btnCompOn.active { background: rgba(34, 197, 94, 0.15); color: #22c55e; font-weight: bold; }\n\n  .compass-invert-btn {\n    display: inline-flex; align-items: center; gap: 4px; padding: 4px 8px; font-size: 11px; font-weight: 500;\n    background: #111827; color: #94a3b8; border: 1px solid rgba(148, 163, 184, 0.2); border-radius: 6px;\n    cursor: pointer; transition: all 0.2s;\n  }\n  .compass-invert-btn:hover { background: #334155; color: #fff; }\n  .compass-invert-btn.active { background: rgba(255, 68, 68, 0.15); border-color: #ff4444; color: #ff4444; }\n\n  .compass-quick-btns { display: flex; gap: 4px; margin-top: 10px; }\n  .compass-quick-btns button {\n    flex: 1; padding: 6px 0; background: #1f2937; font-size: 11px; font-weight: bold; color: #94a3b8;\n    border: 1px solid rgba(148, 163, 184, 0.2); transition: all 0.2s; border-radius: 4px;\n  }\n  .compass-quick-btns button:hover { background: #334155; color: #fff; }\n  .compass-quick-btns button.active { background: rgba(0, 191, 255, 0.15); border-color: #00bfff; color: #00bfff; }\n\n  #compassDegreeDisplay { font-size: 11px; color: #94a3b8; text-align: center; margin-top: 6px; background: #1f2937; padding: 4px; border-radius: 4px; }\n\n  #history-panel { width: 100%; box-sizing: border-box; }\n  #history-hint { margin: 0 0 8px; font-size: 11px; opacity: 0.65; }\n  #history-list { list-style: none; padding: 0; margin: 8px 0 0; }\n  #history-list li { \n    background: #1f2937; padding: 8px; border-radius: 6px; margin-bottom: 6px; \n    text-align: left; cursor: pointer; font-size: 13px;\n    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\n  }\n  #history-list li:hover { background: #374151; }\n  #clear-history { width: 100%; box-sizing: border-box; background: #003366; margin-top: 10px; }\n\n  \/* === Map & Results === *\/\n  #mapWrap { position: relative; width: 620px; height: 480px; border-radius: 10px; overflow: hidden; flex-shrink: 0; }\n  #map { width: 100%; height: 100%; }\n\n  #mapLoading {\n    position: absolute; inset: 0; background: rgba(0, 0, 0, 0.45);\n    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;\n    pointer-events: none; opacity: 0; transition: opacity 0.25s ease; z-index: 500;\n  }\n  #mapLoading.active { opacity: 1; pointer-events: auto; }\n  \n  #resultsCol { width: 380px; display: flex; flex-direction: column; gap: 10px; flex-shrink: 0; }\n  #results { height: 420px; overflow: auto; padding: 0; }\n  #results .header { position: sticky; top: 0; background: #020617; z-index: 1; padding: 10px 12px; border-bottom: 1px solid rgba(255, 255, 255, 0.1); }\n  .result-list { margin: 0; padding: 0; list-style: none; }\n  .result-item { display: flex; justify-content: space-between; align-items: center; padding: 12px; gap: 10px; border-bottom: 1px solid rgba(255, 255, 255, 0.06); }\n  .result-item:hover { background: #1f2937; }\n  .result-left { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 13px; flex: 1; }\n\n  .copy-plz {\n    cursor: pointer; color: #38bdf8; position: relative; transition: color 0.2s;\n    display: inline-flex; align-items: center;\n  }\n  .copy-plz:hover { color: #bae6fd; text-decoration: underline; }\n  .copy-plz::before {\n    content: '\ud83d\udccb'; font-size: 11px; margin-right: 5px; opacity: 0.4; transition: opacity 0.2s;\n  }\n  .copy-plz:hover::before { opacity: 1; }\n  .copy-plz.copied { color: #22c55e; text-decoration: none; }\n  .copy-plz.copied::before { content: '\u2705'; opacity: 1; }\n\n  .exp-panel { display: none; margin-top: 6px; }\n  .exp-panel.open { display: block; }\n  #controls .row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 6px; font-size: 13px; }\n\n  #candidateBox {\n    position: absolute; left: 50%; transform: translateX(-50%); top: 56px; width: 380px; max-height: 300px;\n    overflow: auto; background: #222; border: 1px solid #333; border-radius: 8px; display: none; z-index: 9999; text-align: left;\n  }\n  #candidateBox.open { display: block; }\n  #candidateBox .cand { padding: 10px 12px; cursor: pointer; border-bottom: 1px solid rgba(255, 255, 255, 0.06); }\n  #candidateBox .cand:hover { background: #2b2b2b; }\n\n  \/* === NEUER BERECHNEN BUTTON MIT STRASSEN-OPTIK === *\/\n  #btnCalcRoute {\n    position: relative;\n    width: 100%;\n    background: #2563eb; \/* Blau *\/\n    color: #ffffff;\n    border-radius: 6px;\n    padding: 10px;\n    font-weight: bold;\n    font-size: 14px;\n    transition: all 0.2s;\n    border: none;\n    cursor: pointer;\n    overflow: hidden;\n    box-shadow: 0 4px 15px rgba(37, 99, 235, 0.4);\n  }\n  \/* Das gestrichelte Leitlinien-Muster *\/\n  #btnCalcRoute::before {\n    content: \"\";\n    position: absolute;\n    top: 50%;\n    left: 0;\n    right: 0;\n    height: 3px;\n    background: repeating-linear-gradient(90deg, transparent, transparent 8px, rgba(255, 255, 255, 0.4) 8px, rgba(255, 255, 255, 0.4) 20px);\n    transform: translateY(-50%);\n    z-index: 0;\n  }\n  \/* Der Text liegt im Vordergrund und blockiert die Linie hinter der Schrift *\/\n  #btnCalcRoute span {\n    position: relative;\n    z-index: 1;\n    background: #2563eb;\n    padding: 0 10px;\n    border-radius: 4px;\n    transition: background 0.2s;\n  }\n  #btnCalcRoute:hover { background: #1d4ed8; }\n  #btnCalcRoute:hover span { background: #1d4ed8; }\n  \n  \/* Lade\/Erfolgs-Status im Button *\/\n  #btnCalcRoute.is-loading { background: #d97706; pointer-events: none; box-shadow: none; }\n  #btnCalcRoute.is-loading span { background: #d97706; }\n  #btnCalcRoute.is-success { background: #059669; }\n  #btnCalcRoute.is-success span { background: #059669; }\n\n\n  @media (max-width: 1200px) {\n    #main { flex-direction: column; align-items: center; }\n    #leftCol, #resultsCol, #mapWrap { width: 100%; max-width: 800px; }\n    #leftCol { flex-direction: row; flex-wrap: wrap; }\n    .card { flex: 1; min-width: 300px; }\n  }\n\n  \/* =========================\n     INFO & FAQ FOOTER\n     ========================= *\/\n  .plzprofi-undersearch { margin-top: 48px; padding: 40px 16px 40px; border-top: 1px solid rgba(148, 163, 184, 0.1); }\n  .plzprofi-undersearch-head { margin: 0 0 32px 0; text-align: center; }\n  .plzprofi-undersearch-head h2 { margin: 0 0 8px 0; font-size: 28px; }\n  .plzprofi-undersearch-sub { margin: 0; color: #94a3b8; font-size: 15px; max-width: 600px; margin: 0 auto; line-height: 1.5; }\n  .plzprofi-undersearch-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; margin-bottom: 48px; max-width: 1280px; margin-left: auto; margin-right: auto; }\n  .plzprofi-undersearch-card { border-radius: 16px; padding: 24px; border: 1px solid rgba(148, 163, 184, 0.15); background: radial-gradient(circle at top left, rgba(59, 130, 246, 0.08), transparent 60%), #0b1220; box-shadow: 0 10px 30px rgba(0,0,0,0.2); transition: transform 0.2s ease; }\n  .plzprofi-undersearch-card:hover { transform: translateY(-3px); border-color: rgba(56, 189, 248, 0.3); }\n  .plzprofi-chip { display: inline-flex; align-items: center; padding: 4px 10px; border-radius: 999px; font-size: 11px; letter-spacing: 0.05em; text-transform: uppercase; background: rgba(56, 189, 248, 0.15); color: #38bdf8; margin-bottom: 12px; font-weight: bold; }\n  .plzprofi-undersearch-card h3 { margin: 0 0 12px 0; font-size: 18px; color: #f8fafc; }\n  .plzprofi-undersearch-card p { margin: 0; color: #cbd5e1; font-size: 14px; line-height: 1.6; }\n  .plzprofi-eu-network { background: #0b1220; border-radius: 20px; border: 1px solid rgba(148, 163, 184, 0.15); padding: 32px; max-width: 1280px; margin: 0 auto 48px; text-align: center; }\n  .plzprofi-eu-network h3 { margin: 0 0 12px 0; font-size: 22px; color: #ffffff; }\n  .plzprofi-eu-network p { color: #94a3b8; font-size: 15px; margin: 0 auto 24px; max-width: 600px; line-height: 1.5; }\n  .eu-links-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }\n  .eu-country-btn { display: inline-flex; align-items: center; gap: 8px; padding: 10px 20px; background: #1f2937; border: 1px solid rgba(148, 163, 184, 0.2); border-radius: 12px; color: #e2e8f0; text-decoration: none; font-weight: 500; font-size: 14px; transition: all 0.2s ease; }\n  .eu-country-btn:hover { background: #334155; border-color: #38bdf8; color: #fff; transform: translateY(-2px); }\n  .eu-country-btn.highlight { background: rgba(37, 99, 235, 0.2); border-color: rgba(37, 99, 235, 0.5); color: #60a5fa; }\n  .eu-country-btn.highlight:hover { background: rgba(37, 99, 235, 0.4); color: #fff; }\n  .plzprofi-faq-section { max-width: 1280px; margin: 0 auto; background: transparent; }\n  .plzprofi-faq-section h3 { margin: 0 0 24px 0; font-size: 22px; text-align: center; }\n  .plzprofi-faq-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 16px; margin-bottom: 32px; }\n  .plzprofi-faq-item { border-radius: 12px; border: 1px solid rgba(148, 163, 184, 0.15); background: #0b1220; padding: 20px; transition: background 0.2s; }\n  .plzprofi-faq-item:hover { background: #111827; }\n  .plzprofi-faq-item summary { cursor: pointer; font-weight: 600; list-style: none; color: #e2e8f0; font-size: 15px; position: relative; padding-right: 20px; }\n  .plzprofi-faq-item summary::-webkit-details-marker { display: none; }\n  .plzprofi-faq-item summary::after { content: \"\u25bc\"; position: absolute; right: 0; top: 0; font-size: 12px; color: #64748b; }\n  .plzprofi-faq-item[open] summary::after { content: \"\u25b2\"; color: #38bdf8; }\n  .plzprofi-faq-body { margin-top: 12px; color: #94a3b8; font-size: 14px; line-height: 1.6; border-top: 1px solid rgba(255,255,255,0.05); padding-top: 12px; }\n  .faq-cta-wrap { text-align: center; }\n<\/style>\n\n<div class=\"plzprofi-hero\">\n  <div class=\"plzprofi-hero-inner\">\n    <div class=\"plzprofi-hero-left\">\n      <span class=\"hero-kicker\">PLZ Profi \u00b7 Umkreissuche<\/span>\n      <h1>Finden Sie St\u00e4dte in Ihrem Umkreis<\/h1>\n      <p>Entdecken Sie mit unserer PLZ Umkreissuche schnell und einfach St\u00e4dte und Postleitzahlen in Ihrer Umgebung.<\/p>\n      <a href=\"#plzprofi-tool\" class=\"hero-btn\"><span>Jetzt Suche starten<\/span><\/a>\n    <\/div>\n    <div class=\"plzprofi-hero-right\">\n      <div class=\"hero-card\"><\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div id=\"plzprofi-tool\" class=\"wrapper\">\n  \n  <div class=\"plzprofi-topbar-wrap\" id=\"plzTopBanner\">\n    <div class=\"plzprofi-topbar-content\">\n      <span class=\"plzprofi-topbar-icon\" id=\"plzTopIcon\">\ud83d\udca1<\/span>\n      <span id=\"plzTopText\">Lade Tipp des Tages&#8230;<\/span>\n      <a href=\"#\" id=\"plzTopLink\" class=\"plzprofi-topbar-link\" style=\"display: none;\"><\/a>\n    <\/div>\n    <button class=\"plzprofi-topbar-close\" onclick=\"document.getElementById('plzTopBanner').style.display='none'\" title=\"Schlie\u00dfen\">\u2716<\/button>\n  <\/div>\n\n  <script>\n    (function() {\n      \/\/ 1. Die Tipps exakt wie vom User gew\u00fcnscht\n      const tips = [\n        {\n          icon: \"\ud83c\udf0d\",\n          text: \"Schon gewusst? PLZ Profi gibt es auch f\u00fcr \u00d6sterreich, Tschechien und weitere EU-L\u00e4nder!\",\n          linkText: \"Zur EU-\u00dcbersicht\",\n          linkUrl: \"\/eu-laender\/\" \n        },\n        {\n          icon: \"\ud83c\uddea\ud83c\uddf8\",\n          text: \"Neu dabei: Unsere Umkreissuche unterst\u00fctzt jetzt auch Spanien und Belgien!\",\n          linkText: \"Zur EU-\u00dcbersicht\",\n          linkUrl: \"\/eu-laender\/\"\n        },\n        {\n          icon: \"\ud83c\udded\ud83c\uddfa\",\n          text: \"Erweitere deinen Radius nach Osten: Pr\u00e4zise PLZ-Suchen f\u00fcr Ungarn und Tschechien sind ab sofort verf\u00fcgbar.\"\n        },\n        {\n          icon: \"\ud83e\udded\",\n          text: \"Nutze den roten 'Umkehren'-Modus im Kompass, um bestimmte Himmelsrichtungen gezielt auszuschlie\u00dfen.\"\n        },\n        {\n          icon: \"\ud83d\udccb\",\n          text: \"Klicke in der Ergebnisliste einfach auf eine Postleitzahl (blau hervorgehoben), um sie sofort zu kopieren!\"\n        },\n        {\n          icon: \"\ud83c\udfaf\",\n          text: \"Zu viele Ergebnisse? Nutze den Filter 'Umfang' (Top 10 \/ Top 20), um die Karte \u00fcbersichtlich zu halten und nur die wichtigsten Leitregionen anzuzeigen.\"\n        },\n        {\n          icon: \"\ud83d\udcca\",\n          text: \"Lade dein Einzugsgebiet mit einem Klick als PDF, Excel oder CSV herunter, um die Daten in deinem System weiterzuverarbeiten.\"\n        },\n        {\n          icon: \"\u26f0\ufe0f\",\n          text: \"Gerade in bergigen oder l\u00e4ndlichen Gebieten weicht die reale Route oft ab. Nutze die Fahrstrecken-Berechnung f\u00fcr exakte Werte!\"\n        },\n        {\n          icon: \"\u23f1\ufe0f\",\n          text: \"Zeit sparen: PLZ Profi merkt sich deine letzten Suchanfragen lokal in deinem Browser. Ein Klick im Verlauf reicht, um eine Suche neu zu laden!\"\n        },\n        {\n          icon: \"\u26a1\",\n          text: \"Schnelleingabe am Kompass: Nutze die Buttons wie 'N', 'SW' oder 'O', um den Richtungsfilter mit nur einem Klick exakt einzurasten.\"\n        },\n        {\n          icon: \"\ud83d\udcf1\",\n          text: \"PLZ Profi ist f\u00fcr Smartphones optimiert. Plane oder pr\u00fcfe deine Gebiete bequem direkt auf dem Handy oder Tablet.\"\n        },\n        {\n          icon: \"\ud83d\udd00\",\n          text: \"Sortierung anpassen: Du kannst die Ergebnisliste nicht nur nach Distanz, sondern auch alphabetisch nach Ort oder aufsteigend nach Postleitzahl sortieren.\"\n        },\n        {\n          icon: \"\u2709\ufe0f\",\n          text: \"Fehlt dir ein wichtiges Feature oder ein spezielles Land? Schreib uns dein Feedback oder Ideen direkt an kontakt@plzprofi.de!\"\n        }\n      ];\n\n      \/\/ Zufallsgenerator w\u00e4hlt einen Tipp aus\n      const randomTip = tips[Math.floor(Math.random() * tips.length)];\n\n      \/\/ Inhalte ins HTML f\u00fcllen\n      document.getElementById(\"plzTopIcon\").innerText = randomTip.icon;\n      document.getElementById(\"plzTopText\").innerText = randomTip.text;\n\n      const linkEl = document.getElementById(\"plzTopLink\");\n      if (randomTip.linkText && randomTip.linkUrl) {\n        linkEl.innerText = randomTip.linkText + \" \u2794\";\n        linkEl.href = randomTip.linkUrl;\n        linkEl.style.display = \"inline-block\";\n      }\n\n      \/\/ Banner einblenden\n      document.getElementById(\"plzTopBanner\").style.display = \"flex\";\n    })();\n  <\/script>\n\n  <div class=\"panel\">\n    <div class=\"seg notranslate\" id=\"countrySwitch\" translate=\"no\">\n      <button class=\"seg-btn active notranslate\" data-cc=\"DE\" translate=\"no\" type=\"button\"><span class=\"flag\">\ud83c\udde9\ud83c\uddea<\/span> <span class=\"seg-label notranslate\" translate=\"no\" data-label=\"DE\"><\/span><\/button>\n      <button class=\"seg-btn notranslate\" data-cc=\"AT\" translate=\"no\" type=\"button\"><span class=\"flag\">\ud83c\udde6\ud83c\uddf9<\/span> <span class=\"seg-label notranslate\" translate=\"no\" data-label=\"AT\"><\/span><\/button>\n    <\/div>\n    \n    <label for=\"searchInput\">PLZ oder Ort:<\/label>\n    <div class=\"search-input-wrapper\">\n      <input type=\"text\" id=\"searchInput\" placeholder=\"z.B. 95028 oder Hof\" autocomplete=\"off\" \/>\n      <div id=\"mainAutocomplete\" class=\"main-autocomplete\"><\/div>\n    <\/div>\n    \n    <button id=\"btnCandidates\" title=\"Zeigt alle exakten Treffer in einem separaten Fenster\">Ortsauswahl \u25bc<\/button>\n    <label for=\"radiusInput\">Radius (1\u2013100 km):<\/label>\n    <input type=\"number\" id=\"radiusNumber\" min=\"1\" max=\"100\" value=\"30\" \/>\n    <span id=\"radiusLabel\">30<\/span> km\n    <input type=\"range\" id=\"radiusInput\" min=\"1\" max=\"100\" value=\"30\" \/>\n    <button id=\"btnSearch\">Suchen<\/button>\n    <div id=\"candidateBox\"><\/div>\n  <\/div>\n\n  <div id=\"main\">\n    \n    <div id=\"leftCol\">\n      <div class=\"card\" id=\"compassCard\">\n        <h3>Kompass<\/h3>\n        <div class=\"compass-module\">\n          <div class=\"compass-canvas-wrap\" id=\"compassWrap\" title=\"Klicken &#038; Ziehen zum Rotieren\">\n            <canvas id=\"compassCanvas\" width=\"64\" height=\"64\"><\/canvas>\n          <\/div>\n          <div class=\"compass-controls\">\n            <div class=\"compass-toggle-group\">\n              <button type=\"button\" class=\"compass-toggle-btn active\" id=\"btnCompOff\">\n                <svg viewBox=\"0 0 24 24\" width=\"10\" height=\"10\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"><path d=\"M18.36 6.64a9 9 0 1 1-12.73 0\"><\/path><line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"12\"><\/line><\/svg> Aus\n              <\/button>\n              <button type=\"button\" class=\"compass-toggle-btn\" id=\"btnCompOn\">\n                <svg viewBox=\"0 0 24 24\" width=\"10\" height=\"10\" stroke=\"currentColor\" stroke-width=\"2.5\" fill=\"none\"><path d=\"M18.36 6.64a9 9 0 1 1-12.73 0\"><\/path><line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"12\"><\/line><\/svg> Ein\n              <\/button>\n            <\/div>\n            <button type=\"button\" class=\"compass-invert-btn\" id=\"btnCompInvert\">\n              <span>\ud83d\udd04<\/span> Umkehren\n            <\/button>\n          <\/div>\n        <\/div>\n        <div id=\"compassDegreeDisplay\">Winkel: 0\u00b0 (Norden)<\/div>\n        <div class=\"compass-quick-btns\">\n          <button type=\"button\" data-dir=\"0\">N<\/button>\n          <button type=\"button\" data-dir=\"45\">NO<\/button>\n          <button type=\"button\" data-dir=\"90\">O<\/button>\n          <button type=\"button\" data-dir=\"135\">SO<\/button>\n        <\/div>\n        <div class=\"compass-quick-btns\" style=\"margin-top:4px;\">\n          <button type=\"button\" data-dir=\"180\">S<\/button>\n          <button type=\"button\" data-dir=\"225\">SW<\/button>\n          <button type=\"button\" data-dir=\"270\">W<\/button>\n          <button type=\"button\" data-dir=\"315\">NW<\/button>\n        <\/div>\n      <\/div>\n\n      <div id=\"history-panel\" class=\"card\">\n        <h3>Suchverlauf<\/h3>\n        <div id=\"history-hint\">wird beim L\u00e4nderwechsel zur\u00fcckgesetzt<\/div>\n        <ul id=\"history-list\"><\/ul>\n        <button id=\"clear-history\">Verlauf l\u00f6schen<\/button>\n      <\/div>\n    <\/div>\n\n    <div id=\"mapWrap\">\n      <div id=\"map\"><\/div>\n      <div id=\"mapLoading\">\n        <span style=\"color:white; font-size:14px; background: rgba(0,0,0,0.8); padding: 8px 16px; border-radius: 8px;\">Kartendaten laden&#8230;<\/span>\n      <\/div>\n    <\/div>\n\n    <div id=\"resultsCol\">\n      <div id=\"controls\" class=\"card\">\n        <div class=\"row\">\n          <label for=\"sortSelect\">Sortierung:<\/label>\n          <select id=\"sortSelect\" style=\"flex:1;\">\n            <option value=\"dist-asc\" selected>Distanz \u2191<\/option>\n            <option value=\"plz-asc\">PLZ \u2191<\/option>\n            <option value=\"name-asc\">Ort A\u2013Z<\/option>\n          <\/select>\n        <\/div>\n        <div class=\"row\">\n          <label for=\"limitSelect\">Umfang:<\/label>\n          <select id=\"limitSelect\" style=\"flex:1;\">\n            <option value=\"top10\" selected>Top 10<\/option>\n            <option value=\"top20\">Top 20<\/option>\n            <option value=\"all\">Alle<\/option>\n          <\/select>\n        <\/div>\n        <div class=\"row exp-wrap\" style=\"margin-top: 10px;\">\n          <button class=\"exp-toggle\" id=\"expToggle\" style=\"width:100%\">Export \u25bc<\/button>\n          <div class=\"exp-panel\" id=\"expPanel\">\n            <div class=\"row\" style=\"margin-top:4px; justify-content: center;\">\n              <button id=\"btnExportCsv\">CSV<\/button>\n              <button id=\"btnExportXlsx\">XLSX<\/button>\n              <button id=\"btnExportPdf\">PDF<\/button>\n              <button id=\"btnExportTxt\">TXT<\/button>\n            <\/div>\n            <div style=\"font-size:11px; opacity:0.6; margin-top:6px; text-align:center;\">\u2022 Exportiert die sichtbare Liste<\/div>\n          <\/div>\n        <\/div>\n\n        <div class=\"routing-section\" style=\"margin-top: 16px; padding-top: 16px; border-top: 1px solid rgba(255,255,255,0.08);\">\n          <div class=\"row\" style=\"justify-content: space-between; margin-bottom: 8px;\">\n            <label for=\"speedSlider\" style=\"font-size: 13px; color: #94a3b8; font-weight: bold;\">\u00d8 Fahrgeschwindigkeit:<\/label>\n            <div style=\"font-size: 14px; font-weight: bold; color: #38bdf8;\"><span id=\"speedLabel\">60<\/span> km\/h<\/div>\n          <\/div>\n          <input type=\"range\" id=\"speedSlider\" min=\"30\" max=\"130\" value=\"60\" step=\"1\" style=\"width: 100%; margin-bottom: 12px; accent-color: #10b981;\">\n          \n          <button id=\"btnCalcRoute\">\n            <span>Fahrstrecke berechnen<\/span>\n          <\/button>\n        <\/div>\n      <\/div>\n\n      <div id=\"results\" class=\"card\">\n        <div class=\"header\" style=\"padding-bottom: 4px;\">\n          <div id=\"resTitle\"><strong>Ergebnisse<\/strong><\/div>\n          <div id=\"resMeta\" style=\"font-size: 12px; opacity: 0.8;\">Bitte Suche ausf\u00fchren.<\/div>\n        <\/div>\n        \n        <div class=\"legend-box\">\n          <span class=\"legend-item\"><div class=\"legend-dot\" style=\"background:#fde047;\"><\/div> Zeit<\/span>\n          <span class=\"legend-item\"><div class=\"legend-dot\" style=\"background:#4ade80;\"><\/div> Strecke<\/span>\n          <span class=\"legend-item\"><div class=\"legend-dot\" style=\"background:#38bdf8;\"><\/div> Luft<\/span>\n        <\/div>\n\n        <ul class=\"result-list\" id=\"resList\"><\/ul>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <section class=\"plzprofi-undersearch\">\n    <header class=\"plzprofi-undersearch-head\">\n      <h2>Das smarte Dispo-Tool f\u00fcr die Logistik<\/h2>\n      <p class=\"plzprofi-undersearch-sub\">Entwickelt f\u00fcr Speditionen, Transportunternehmen und die t\u00e4gliche Gebietsplanung. Unsere Features sparen dir wertvolle Zeit bei der Disposition und Tourenplanung.<\/p>\n    <\/header>\n\n    <div class=\"plzprofi-undersearch-grid\">\n      <article class=\"plzprofi-undersearch-card\">\n        <span class=\"plzprofi-chip\">Richtungsfilter<\/span>\n        <h3>Der interaktive Kompass<\/h3>\n        <p>Grenze dein Einzugsgebiet exakt ein. Du suchst R\u00fcckladungen, aber nur in Richtung Norden? Aktiviere den Kompass, w\u00e4hle deine Himmelsrichtung und alle irrelevanten Postleitzahlen verschwinden sofort aus deiner Liste. Ideal f\u00fcr gezielte Frachtanfragen.<\/p>\n      <\/article>\n\n      <article class=\"plzprofi-undersearch-card\">\n        <span class=\"plzprofi-chip\">Workflow<\/span>\n        <h3>1-Klick PLZ Kopie<\/h3>\n        <p>Nie wieder Tippfehler beim Inserieren in Transportb\u00f6rsen. Klicke in der Ergebnisliste einfach auf die gew\u00fcnschte PLZ, und sie liegt sofort sauber formatiert in deiner Zwischenablage \u2013 bereit zum Einf\u00fcgen in dein System.<\/p>\n      <\/article>\n\n      <article class=\"plzprofi-undersearch-card\">\n        <span class=\"plzprofi-chip\">Organisation<\/span>\n        <h3>Daten-Export &#038; Verlauf<\/h3>\n        <p>Lade dir dein spezifisches Einzugsgebiet mit einem Klick als <strong>Excel (XLSX), CSV oder PDF<\/strong> herunter, um es f\u00fcr Angebote oder dein TMS zu nutzen. Dein intelligenter Suchverlauf speichert zudem automatisch deine letzten Anfragen.<\/p>\n      <\/article>\n    <\/div>\n\n    <div class=\"plzprofi-eu-network\">\n      <h3>PLZ-Suche f\u00fcr ganz Europa<\/h3>\n      <p>Internationale Touren erfordern verl\u00e4ssliche Daten \u00fcber die Grenzen hinaus. Wir bauen unser System stetig aus, damit du europaweit den perfekten Umkreis ermitteln kannst.<\/p>\n      <div class=\"eu-links-grid\">\n        <a href=\"https:\/\/plzprofi.de\/eu-laender\/de\/\" class=\"eu-country-btn\"><span class=\"flag\">\ud83c\udde9\ud83c\uddea<\/span> Deutschland<\/a>\n        <a href=\"https:\/\/plzprofi.de\/eu-laender\/at\/\" class=\"eu-country-btn\"><span class=\"flag\">\ud83c\udde6\ud83c\uddf9<\/span> \u00d6sterreich<\/a>\n        <a href=\"https:\/\/plzprofi.de\/eu-laender\/cz\/\" class=\"eu-country-btn\"><span class=\"flag\">\ud83c\udde8\ud83c\uddff<\/span> Tschechien<\/a>\n        <a href=\"https:\/\/plzprofi.de\/eu-laender\/es\/\" class=\"eu-country-btn\"><span class=\"flag\">\ud83c\uddea\ud83c\uddf8<\/span> Spanien<\/a>\n        <a href=\"\/eu-laender\/\" class=\"eu-country-btn highlight\">\ud83c\udf0d Alle EU-L\u00e4nder ansehen<\/a>\n      <\/div>\n    <\/div>\n\n    <div class=\"plzprofi-faq-section\">\n      <h3>Kurze Fragen, schnelle Antworten<\/h3>\n      <div class=\"plzprofi-faq-grid\">\n        <details class=\"plzprofi-faq-item\">\n          <summary>Wie funktioniert die Umkreissuche?<\/summary>\n          <div class=\"plzprofi-faq-body\">Du gibst eine Postleitzahl oder einen Ortsnamen ein und w\u00e4hlst einen Radius (bis 100 km). Das Tool berechnet sofort alle umliegenden PLZ-Gebiete basierend auf der genauen Geokoordinate (Luftlinie) des Startpunktes.<\/div>\n        <\/details>\n\n        <details class=\"plzprofi-faq-item\">\n          <summary>Was bewirkt die Einstellung &#8222;Top 10 \/ Alle&#8220;?<\/summary>\n          <div class=\"plzprofi-faq-body\">Um die Karte lesbar zu halten, gruppiert das System bei &#8222;Top 10&#8220; oder &#8222;Top 20&#8220; die Ergebnisse nach den ersten zwei Ziffern der Postleitzahl (Leitregion). W\u00e4hlst du &#8222;Alle&#8220;, siehst du s\u00e4mtliche Details in der Liste, w\u00e4hrend die Karte nur den Startpunkt anzeigt, um Performance-Einbr\u00fcche zu vermeiden.<\/div>\n        <\/details>\n\n        <details class=\"plzprofi-faq-item\">\n          <summary>Wie nutze ich die &#8222;Umkehren&#8220;-Funktion am Kompass?<\/summary>\n          <div class=\"plzprofi-faq-body\">Die Umkehren-Funktion (roter Modus) ist ideal f\u00fcr das Ausschlussverfahren. Wenn du z.B. eine Tour planst, aber auf keinen Fall Richtung S\u00fcden fahren willst, richtest du den Kompass auf S\u00fcden aus und klickst auf &#8222;Umkehren&#8220;. Dir werden dann alle Orte angezeigt, <em>au\u00dfer<\/em> jene im S\u00fcden.<\/div>\n        <\/details>\n\n        <details class=\"plzprofi-faq-item\">\n          <summary>Ist die Nutzung von PLZ Profi wirklich kostenlos?<\/summary>\n          <div class=\"plzprofi-faq-body\">Ja. Wir haben PLZ Profi entwickelt, um den Arbeitsalltag in der Disposition sp\u00fcrbar zu erleichtern. Die Basis-Funktionen wie Karte, Kompass und CSV\/Excel-Exporte stehen dir kostenfrei zur Verf\u00fcgung.<\/div>\n        <\/details>\n      <\/div>\n\n      <div class=\"faq-cta-wrap\" style=\"margin-top: 32px;\">\n        <a href=\"\/faq\/\" class=\"hero-btn\" style=\"background: transparent; border: 1px solid rgba(56, 189, 248, 0.4); box-shadow: none; color: #38bdf8;\">\n          <span>Zur vollst\u00e4ndigen FAQ<\/span>\n        <\/a>\n      <\/div>\n    <\/div>\n  <\/section>\n<\/div>\n\n<script src=\"https:\/\/unpkg.com\/leaflet\/dist\/leaflet.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/xlsx@0.18.5\/dist\/xlsx.full.min.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/jspdf@2.5.1\/dist\/jspdf.umd.min.js\"><\/script>\n\n<script>\n  window.copyPLZ = function(plz, element) {\n    navigator.clipboard.writeText(plz).then(() => {\n      element.classList.add('copied');\n      setTimeout(() => element.classList.remove('copied'), 1500);\n    }).catch(err => {\n      const ta = document.createElement('textarea'); ta.value = plz;\n      document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta);\n      element.classList.add('copied'); setTimeout(() => element.classList.remove('copied'), 1500);\n    });\n  };\n\n  const DATA_URLS = { DE: 'https:\/\/plzprofi.de\/wp-content\/uploads\/geo\/plz-de-short.geojson', AT: 'https:\/\/plzprofi.de\/wp-content\/uploads\/geo\/plz-at-clean.geojson' };\n  let currentCountry = 'DE';\n  let geoData = [], geoLoaded = false, allMatches = [], viewResults = [], lastCenter = null, searchActive = false;\n\n  let map = L.map('map').setView([51.1657, 10.4515], 6);\n  L.tileLayer('https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png', { attribution: '\u00a9 OpenStreetMap' }).addTo(map);\n  let markerLayerGroup = L.layerGroup().addTo(map);\n  let circleLayer;\n\n  const resultIcon = new L.Icon({ iconUrl: 'https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/images\/marker-icon.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowUrl: 'https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/images\/marker-shadow.png', shadowSize: [41, 41] });\n  const searchIcon = new L.Icon({ iconUrl: 'https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/images\/marker-icon.png', iconSize: [33, 54], iconAnchor: [16, 54], popupAnchor: [1, -40], shadowUrl: 'https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/images\/marker-shadow.png', shadowSize: [54, 54] });\n\n  const compassCanvas = document.getElementById(\"compassCanvas\"), ctx = compassCanvas.getContext(\"2d\");\n  const compassDegreeDisplay = document.getElementById(\"compassDegreeDisplay\");\n  const quickBtns = document.querySelectorAll(\".compass-quick-btns button\");\n  \n  const btnCompOff = document.getElementById(\"btnCompOff\");\n  const btnCompOn = document.getElementById(\"btnCompOn\");\n  const btnCompInvert = document.getElementById(\"btnCompInvert\");\n\n  let isCompassActive = false;\n  let isCompassInverted = false;\n  let compassAngle = 0, isDraggingCompass = false, compassConeWidth = 90;\n\n  function setCompassActive(state) {\n    isCompassActive = state;\n    if(state) {\n      btnCompOn.classList.add('active');\n      btnCompOff.classList.remove('active');\n    } else {\n      btnCompOff.classList.add('active');\n      btnCompOn.classList.remove('active');\n    }\n    drawCompass(); updateQuickBtnUI(); if(searchActive) applySortAndRender();\n  }\n\n  btnCompOn.addEventListener('click', () => setCompassActive(true));\n  btnCompOff.addEventListener('click', () => setCompassActive(false));\n  \n  btnCompInvert.addEventListener('click', () => {\n    isCompassInverted = !isCompassInverted;\n    btnCompInvert.classList.toggle('active', isCompassInverted);\n    drawCompass(); if(searchActive) applySortAndRender();\n  });\n\n  function getDirectionName(deg) {\n    if (deg >= 337.5 || deg < 22.5) return \"Norden\"; if (deg >= 22.5 && deg < 67.5) return \"Nord-Ost\";\n    if (deg >= 67.5 && deg < 112.5) return \"Osten\"; if (deg >= 112.5 && deg < 157.5) return \"S\u00fcd-Ost\";\n    if (deg >= 157.5 && deg < 202.5) return \"S\u00fcden\"; if (deg >= 202.5 && deg < 247.5) return \"S\u00fcd-West\";\n    if (deg >= 247.5 && deg < 292.5) return \"Westen\"; if (deg >= 292.5 && deg < 337.5) return \"Nord-West\"; return \"\";\n  }\n\n  function drawCompass() {\n    const w = compassCanvas.width, h = compassCanvas.height, cx = w\/2, cy = h\/2, r = w\/2 - 2;\n    ctx.clearRect(0, 0, w, h); ctx.strokeStyle = \"rgba(148, 163, 184, 0.2)\"; ctx.lineWidth = 1; ctx.beginPath();\n    ctx.moveTo(cx, 0); ctx.lineTo(cx, h); ctx.moveTo(0, cy); ctx.lineTo(w, cy); ctx.stroke();\n    ctx.fillStyle = \"rgba(148, 163, 184, 0.7)\"; ctx.font = \"10px sans-serif\"; ctx.textAlign = \"center\"; ctx.textBaseline = \"middle\";\n    ctx.fillText(\"N\", cx, 8); ctx.fillText(\"S\", cx, h - 8); ctx.fillText(\"W\", 8, cy); ctx.fillText(\"O\", w - 8, cy);\n\n    if (isCompassActive) {\n      const startAngle = (compassAngle - compassConeWidth \/ 2 - 90) * Math.PI \/ 180;\n      const endAngle = (compassAngle + compassConeWidth \/ 2 - 90) * Math.PI \/ 180;\n      ctx.beginPath(); ctx.moveTo(cx, cy); ctx.arc(cx, cy, r, startAngle, endAngle); ctx.closePath();\n      const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, r);\n      grad.addColorStop(0, \"rgba(0, 191, 255, 0.1)\"); grad.addColorStop(1, \"rgba(0, 191, 255, 0.6)\");\n      ctx.fillStyle = isCompassInverted ? \"rgba(255, 68, 68, 0.4)\" : grad; ctx.fill();\n      ctx.strokeStyle = isCompassInverted ? \"#ff4444\" : \"#00bfff\"; ctx.lineWidth = 2; ctx.stroke();\n    }\n    compassDegreeDisplay.textContent = isCompassActive ? `Winkel: ${Math.round(compassAngle)}\u00b0 (${getDirectionName(compassAngle)})` : \"Kompass deaktiviert\";\n  }\n\n  function updateQuickBtnUI() {\n    quickBtns.forEach(b => {\n      const dir = parseInt(b.dataset.dir);\n      b.classList.toggle('active', isCompassActive && Math.abs(compassAngle - dir) < 2);\n    });\n  }\n\n  function handleCompassInteraction(e) {\n    if (!isDraggingCompass) return;\n    const rect = compassCanvas.getBoundingClientRect();\n    const clientX = e.touches ? e.touches[0].clientX : e.clientX, clientY = e.touches ? e.touches[0].clientY : e.clientY;\n    const x = clientX - rect.left - rect.width \/ 2, y = clientY - rect.top - rect.height \/ 2;\n    compassAngle = (Math.atan2(x, -y) * 180 \/ Math.PI + 360) % 360;\n    if(!isCompassActive) setCompassActive(true); \n    else { drawCompass(); updateQuickBtnUI(); if (searchActive) applySortAndRender(); }\n  }\n\n  compassCanvas.addEventListener('mousedown', (e) => { isDraggingCompass = true; handleCompassInteraction(e); });\n  window.addEventListener('mouseup', () => { isDraggingCompass = false; });\n  compassCanvas.addEventListener('mousemove', handleCompassInteraction);\n  quickBtns.forEach(btn => {\n    btn.addEventListener('click', (e) => {\n      compassAngle = parseInt(e.target.dataset.dir); setCompassActive(true);\n    });\n  });\n  drawCompass();\n\n  function setCountry(code) {\n    currentCountry = code; geoLoaded = false; searchActive = false; lastCenter = null; allMatches = []; viewResults = [];\n    markerLayerGroup.clearLayers(); if (circleLayer) map.removeLayer(circleLayer);\n    document.getElementById(\"resTitle\").innerHTML = '<strong>Ergebnisse<\/strong>';\n    document.getElementById(\"resMeta\").textContent = 'Daten werden geladen...'; document.getElementById(\"resList\").innerHTML = '';\n    document.getElementById(\"mapLoading\").classList.add('active');\n    \n    renderHistory();\n    \n    fetch(DATA_URLS[code]).then(r => r.json()).then(data => {\n      let feats; if (Array.isArray(data)) feats = data; else if (Array.isArray(data.features)) feats = data.features;\n      geoData = feats || []; geoLoaded = true; document.getElementById(\"resMeta\").textContent = 'Bitte Suche ausf\u00fchren.';\n    }).finally(() => document.getElementById(\"mapLoading\").classList.remove('active'));\n  }\n  \n  function lockCountryLabels() {\n    document.getElementById('countrySwitch').querySelectorAll('.seg-btn').forEach(btn => {\n      const code = btn.dataset.cc || ''; const lab = btn.querySelector('.seg-label');\n      if (lab) { lab.setAttribute('data-label', code); lab.textContent = ''; }\n    });\n  }\n  lockCountryLabels();\n  new MutationObserver(lockCountryLabels).observe(document.getElementById('countrySwitch'), { subtree: true, childList: true, characterData: true });\n\n  document.querySelectorAll('#countrySwitch .seg-btn').forEach(b => {\n    b.addEventListener('click', () => {\n      document.querySelectorAll('#countrySwitch .seg-btn').forEach(x => x.classList.remove('active'));\n      b.classList.add('active'); \n      localStorage.removeItem('plzHistory_DE');\n      localStorage.removeItem('plzHistory_AT');\n      setCountry(b.dataset.cc); \n      lockCountryLabels(); \n    });\n  });\n  setCountry(currentCountry);\n\n  function getCenter(coords, type) {\n    if (type === 'Point') return [coords[1], coords[0]];\n    if (type === 'MultiPoint') { let la=0, lo=0; coords.forEach(c => {lo+=c[0]; la+=c[1];}); return [la\/coords.length, lo\/coords.length]; }\n    let arr; if (type === 'Polygon') arr = coords[0] || []; else if (type === 'MultiPolygon') arr = (coords || []).flat(1); else arr = (coords || []).flat(2);\n    let la = 0, lo = 0; arr.forEach(c => { lo += c[0]; la += c[1]; });\n    const len = arr.length || 1; return [la \/ len, lo \/ len];\n  }\n  function haversine(lat1, lon1, lat2, lon2) {\n    const R = 6371, toRad = x => x * Math.PI \/ 180, dLat = toRad(lat2 - lat1), dLon = toRad(lon2 - lon1);\n    const a = Math.sin(dLat \/ 2) ** 2 + Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon \/ 2) ** 2;\n    return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n  }\n  function getBearing(lat1, lon1, lat2, lon2) {\n    const toRad = x => x * Math.PI \/ 180, toDeg = x => x * 180 \/ Math.PI;\n    const dLon = toRad(lon2 - lon1);\n    const y = Math.sin(dLon) * Math.cos(toRad(lat2));\n    const x = Math.cos(toRad(lat1)) * Math.sin(toRad(lat2)) - Math.sin(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.cos(dLon);\n    return (toDeg(Math.atan2(y, x)) + 360) % 360;\n  }\n  function normalizeText(str) { return (str || '').toString().normalize('NFD').replace(\/\\p{Diacritic}\/gu, '').toLowerCase().trim(); }\n  function safeOrt(f) {\n    const raw = (f.properties.ort || f.properties.note || f.properties.name || '').toString().trim(), plz = (f.properties.plz || '').toString();\n    return raw.replace(new RegExp('^' + plz + '\\\\s*'), '').trim();\n  }\n  function formatPlzCountry(plz) {\n    const p = String(plz || '');\n    return currentCountry === 'DE' ? p.padStart(5, '0') : p.padStart(4, '0');\n  }\n\n  const mainInput = document.getElementById('searchInput');\n  const mainAutoBox = document.getElementById('mainAutocomplete');\n\n  function renderMainSuggestions() {\n    const rawVal = mainInput.value.trim();\n    const val = normalizeText(rawVal);\n    \n    if (val.length < 2) {\n      mainAutoBox.style.display = 'none';\n      return;\n    }\n\n    const isNumSearch = \/^\\d\/.test(val);\n    const searchNum = rawVal.replace(\/\\D\/g, '');\n    const searchText = normalizeText(rawVal.replace(\/\\d\/g, '').trim());\n\n    const hits = geoData.filter(f => {\n      const p = formatPlzCountry(f.properties.plz);\n      const o = normalizeText(safeOrt(f));\n\n      if (isNumSearch) {\n        if (!p.startsWith(searchNum)) return false;\n        if (searchText.length > 0 && !o.includes(searchText)) return false;\n        return true;\n      } else {\n        if (o === val || o.startsWith(val)) return true;\n        const words = o.split(\/[\\s,-]+\/);\n        if (words.some(w => w.startsWith(val))) return true;\n        return false;\n      }\n    }).slice(0, 3); \n\n    if (hits.length > 0) {\n      mainAutoBox.innerHTML = hits.map((f, i) => {\n        const p = formatPlzCountry(f.properties.plz);\n        const o = safeOrt(f);\n        return `<div class=\"main-sugg\" tabindex=\"0\" data-val=\"${p} ${o}\" data-idx=\"${i}\"><strong>${p}<\/strong> ${o}<\/div>`;\n      }).join('');\n      mainAutoBox.style.display = 'block';\n    } else {\n      mainAutoBox.style.display = 'none';\n    }\n  }\n\n  mainInput.addEventListener('input', renderMainSuggestions);\n  mainInput.addEventListener('focus', renderMainSuggestions);\n\n  mainInput.addEventListener('keydown', e => {\n    if (e.key === 'Tab' || e.key === 'ArrowDown') {\n      const suggs = document.querySelectorAll('#mainAutocomplete .main-sugg');\n      if (suggs.length > 0) {\n        e.preventDefault(); \n        suggs[0].focus();\n      }\n    } else if (e.key === 'Enter') {\n      document.getElementById('btnSearch').click();\n      mainAutoBox.style.display = 'none';\n    }\n  });\n\n  mainAutoBox.addEventListener('keydown', e => {\n    const active = document.activeElement;\n    if (!active.classList.contains('main-sugg')) return;\n    \n    const suggs = Array.from(document.querySelectorAll('.main-sugg'));\n    const idx = suggs.indexOf(active);\n\n    if (e.key === 'ArrowDown') {\n      e.preventDefault();\n      if (idx < suggs.length - 1) suggs[idx + 1].focus();\n    } else if (e.key === 'ArrowUp') {\n      e.preventDefault();\n      if (idx > 0) suggs[idx - 1].focus();\n      else mainInput.focus();\n    } else if (e.key === 'Enter') {\n      e.preventDefault();\n      active.click();\n    } else if (e.key === 'Escape' || e.key === 'Tab') {\n      mainAutoBox.style.display = 'none';\n    }\n  });\n\n  document.addEventListener('click', e => {\n    const sugg = e.target.closest('.main-sugg');\n    if (sugg) {\n      mainInput.value = sugg.getAttribute('data-val');\n      mainAutoBox.style.display = 'none';\n      document.getElementById('btnSearch').click(); \n    } else if (!e.target.closest('.search-input-wrapper')) {\n      mainAutoBox.style.display = 'none';\n    }\n  });\n\n\n  const btnCandidates = document.getElementById(\"btnCandidates\"), candBox = document.getElementById(\"candidateBox\");\n  let candidatesOpen = false;\n  function toggleCandidates(open) {\n    candidatesOpen = (open !== undefined) ? open : !candidatesOpen;\n    candBox.classList.toggle('open', candidatesOpen); btnCandidates.textContent = candidatesOpen ? 'Ortsauswahl \u25b2' : 'Ortsauswahl \u25bc';\n  }\n  btnCandidates.addEventListener('click', () => {\n    const list = candidatesFor(document.getElementById('searchInput').value.trim()); renderCandidates(list); toggleCandidates();\n  });\n\n  function candidatesFor(inputRaw) {\n    const input = normalizeText(inputRaw);\n    const searchNum = inputRaw.replace(\/\\D\/g, '');\n    const searchText = normalizeText(inputRaw.replace(\/\\d\/g, '').trim());\n    \n    return (geoData || []).filter(f => {\n      const p = formatPlzCountry(f.properties.plz);\n      const o = safeOrt(f);\n      const normOrt = normalizeText(o);\n      const combined = normalizeText(`${p} ${o}`);\n\n      \/\/ Sucht exakt nach \"95028 Hof\" oder \"95028 H\"\n      if (combined === input || combined.startsWith(input)) return true;\n      \n      if (searchNum.length > 0 && searchText.length > 0) return p.startsWith(searchNum) && normOrt.includes(searchText);\n      if (searchNum.length > 0) return p.startsWith(searchNum);\n      if (searchText.length > 0) return normOrt === input || normOrt.split(\/[\\s,-]+\/).includes(input) || normOrt.startsWith(input);\n      return false;\n    }).sort((a, b) => String(a.properties.plz || '').localeCompare(String(b.properties.plz || '')));\n  }\n\n  function renderCandidates(list) {\n    if (!list.length) { candBox.classList.remove('open'); btnCandidates.textContent = 'Ortsauswahl \u25bc'; return; }\n    candBox.innerHTML = list.slice(0, 60).map((c, i) => `<div class=\"cand\" data-i=\"${i}\">${formatPlzCountry(c.properties.plz)} ${safeOrt(c)}<\/div>`).join('');\n    candBox.querySelectorAll('.cand').forEach(el => {\n      el.addEventListener('click', () => {\n        const idx = parseInt(el.getAttribute('data-i'), 10); toggleCandidates(false);\n        runSearch(list[idx], getRadius(), document.getElementById('searchInput').value.trim());\n      });\n    });\n  }\n\n  \/\/ === HIER WURDE NUR DIESE FUNKTION F\u00dcR DIE KOMBI-SUCHE ERWEITERT ===\n  function bestCandidate(cands, inputRaw) {\n    const input = normalizeText(inputRaw);\n    const searchNum = inputRaw.replace(\/\\D\/g, '');\n    const searchText = normalizeText(inputRaw.replace(\/\\d\/g, '').trim());\n    \n    \/\/ Pr\u00fcft als Erstes, ob es eine exakte PLZ+Ort Kombi ist\n    const exactCombined = cands.find(f => normalizeText(`${formatPlzCountry(f.properties.plz)} ${safeOrt(f)}`) === input);\n    if (exactCombined) return exactCombined;\n\n    if (searchNum.length >= 4) { \n       const hit = cands.find(f => formatPlzCountry(f.properties.plz) === searchNum); \n       if (hit) return hit; \n    }\n    \n    if (searchText.length > 0) {\n      const exactOrt = cands.find(f => normalizeText(safeOrt(f)) === searchText); \n      if (exactOrt) return exactOrt;\n    }\n    \n    return cands[0];\n  }\n\n\n  function getRadius() { return Math.min(100, Math.max(1, Number(document.getElementById(\"radiusInput\").value) || 30)); }\n\n  document.getElementById(\"btnSearch\").addEventListener(\"click\", () => {\n    toggleCandidates(false); const inputRaw = document.getElementById('searchInput').value.trim(); const radius = getRadius();\n    if (!inputRaw || isNaN(radius)) return alert(\"Bitte g\u00fcltige PLZ oder Ortsnamen eingeben.\");\n    if (!geoLoaded) return alert(\"Kartendaten laden noch...\");\n    const cands = candidatesFor(inputRaw); if (!cands.length) return alert(\"Ort nicht gefunden.\");\n    runSearch(bestCandidate(cands, inputRaw), radius, inputRaw);\n  });\n\n  function runSearch(refFeature, radius, inputRaw) {\n    if (typeof gtag === 'function') gtag('event', 'search_executed', { country: currentCountry, radius: radius, search_term: inputRaw });\n    const [centerLat, centerLon] = getCenter(refFeature.geometry.coordinates, refFeature.geometry.type);\n    lastCenter = { centerLat, centerLon, ref: refFeature };\n\n    if (circleLayer) map.removeLayer(circleLayer);\n    circleLayer = L.circle([centerLat, centerLon], { radius: radius * 1000, color: \"#1b5e20\", fillColor: \"#81c784\", fillOpacity: 0.15, weight: 2 }).addTo(map);\n    map.fitBounds(circleLayer.getBounds(), { padding: [24, 24] });\n\n    recomputeMatches(radius); applySortAndRender();\n    const plz = formatPlzCountry(refFeature.properties.plz); const ort = safeOrt(refFeature);\n    saveSearch({ q: inputRaw, plz: plz, ort: ort, radius: radius }); searchActive = true;\n    \n    const btnCalc = document.getElementById(\"btnCalcRoute\");\n    btnCalc.innerHTML = \"<span>Fahrstrecke berechnen<\/span>\";\n    btnCalc.classList.remove('is-loading');\n    btnCalc.classList.remove('is-success');\n  }\n\n  function recomputeMatches(radius) {\n    if (!lastCenter) return; const { centerLat, centerLon, ref } = lastCenter; const targetNameNorm = normalizeText(safeOrt(ref));\n    allMatches = geoData.map(f => {\n      const [lat, lon] = getCenter(f.geometry.coordinates, f.geometry.type); if (!isFinite(lat) || !isFinite(lon)) return null;\n      const dist = haversine(centerLat, centerLon, lat, lon), bearing = getBearing(centerLat, centerLon, lat, lon);\n      return { plz: formatPlzCountry(f.properties.plz), ort: safeOrt(f), lat, lon, dist, bearing };\n    }).filter(p => p && p.dist <= radius).filter(p => normalizeText(p.ort) !== targetNameNorm);\n  }\n\n  function limitByPrefix(arr, n) {\n    const unique = new Map();\n    for (const x of arr) { const prefix = x.plz.slice(0, 2); if (!unique.has(prefix)) unique.set(prefix, x); if (unique.size >= n) break; }\n    return Array.from(unique.values());\n  }\n\n  async function getRoadDistance(lat1, lon1, lat2, lon2) {\n      try {\n          const baseUrl = currentCountry === 'AT' \n              ? 'https:\/\/routing.api.plzprofi.de\/at' \n              : 'https:\/\/routing.api.plzprofi.de';\n              \n          const url = `${baseUrl}\/route\/v1\/driving\/${lon1},${lat1};${lon2},${lat2}?overview=false`;\n          \n          const response = await fetch(url);\n          if (response.status === 429) return { error: 'limit' };\n          const data = await response.json();\n          return data.code === 'Ok' ? { dist: data.routes[0].distance \/ 1000 } : null;\n      } catch (e) { return null; }\n  }\n\n  const speedSlider = document.getElementById(\"speedSlider\");\n  const speedLabel = document.getElementById(\"speedLabel\");\n  \n  speedSlider.addEventListener(\"input\", (e) => {\n    const speed = e.target.value;\n    speedLabel.innerText = speed;\n    \n    viewResults.slice(0, 10).forEach((p, i) => {\n        if (p.roadDist) {\n            const timeBadge = document.getElementById(`time-${i}`);\n            if (timeBadge) {\n                const hours = p.roadDist \/ parseInt(speed);\n                const h = Math.floor(hours), m = Math.round((hours - h) * 60);\n                timeBadge.innerHTML = `\u23f1 ${h > 0 ? h+'h ' : ''}${m}m`;\n            }\n        }\n    });\n  });\n\n  document.getElementById(\"btnCalcRoute\").addEventListener(\"click\", async () => {\n      if (!lastCenter || !viewResults.length) return alert(\"Bitte starte zuerst eine normale Suche!\");\n\n      const btn = document.getElementById(\"btnCalcRoute\");\n      btn.innerHTML = '<span>\u23f3 Berechne Fahrstrecken...<\/span>';\n      btn.classList.add('is-loading');\n      btn.disabled = true;\n\n      const speed = parseInt(speedSlider.value);\n\n      const fetchPromises = viewResults.slice(0, 10).map(async (p, i) => {\n          const roadBadge = document.getElementById(`road-${i}`);\n          if (!roadBadge) return;\n          \n          roadBadge.innerHTML = `<span class=\"loading-dots\"><\/span>`;\n          \n          const data = await getRoadDistance(lastCenter.centerLat, lastCenter.centerLon, p.lat, p.lon);\n          \n          if (data && data.error === 'limit') {\n              roadBadge.innerHTML = \"\u26a0\ufe0f Limit\";\n          } else if (data) {\n              p.roadDist = data.dist; \n              \n              const hours = data.dist \/ speed;\n              const h = Math.floor(hours), m = Math.round((hours - h) * 60);\n              \n              roadBadge.innerHTML = `${data.dist.toFixed(1)} km`;\n              roadBadge.classList.add('active');\n              \n              const timeBadge = document.getElementById(`time-${i}`);\n              if(timeBadge) {\n                 timeBadge.innerHTML = `\u23f1 ${h > 0 ? h+'h ' : ''}${m}m`;\n                 timeBadge.classList.add('active');\n              }\n              \n          } else {\n              roadBadge.innerHTML = \"Fehler\";\n          }\n      });\n\n      await Promise.all(fetchPromises);\n      \n      btn.innerHTML = '<span>\u2705 Erfolgreich berechnet<\/span>';\n      btn.classList.remove('is-loading');\n      btn.classList.add('is-success');\n      setTimeout(() => { btn.disabled = false; }, 1000);\n  });\n\n  function applySortAndRender() {\n    if (!lastCenter) return; let filteredMatches = allMatches;\n    if (isCompassActive) {\n      filteredMatches = allMatches.filter(p => {\n        let diff = Math.abs(p.bearing - compassAngle); if (diff > 180) diff = 360 - diff;\n        let inCone = diff <= (compassConeWidth \/ 2); return isCompassInverted ? !inCone : inCone;\n      });\n    }\n\n    const sortVal = document.getElementById(\"sortSelect\").value;\n    if(sortVal === 'dist-asc') filteredMatches.sort((a,b) => a.dist - b.dist);\n    else if(sortVal === 'plz-asc') filteredMatches.sort((a,b) => a.plz.localeCompare(b.plz));\n    else if(sortVal === 'name-asc') filteredMatches.sort((a,b) => a.ort.localeCompare(b.ort));\n\n    const limitVal = document.getElementById(\"limitSelect\").value;\n    let view = filteredMatches;\n    if (limitVal === 'top10') view = limitByPrefix(filteredMatches, 10);\n    else if (limitVal === 'top20') view = limitByPrefix(filteredMatches, 20);\n\n    viewResults = view;\n    \n    viewResults.forEach(p => p.roadDist = null);\n    \n    const cityName = safeOrt(lastCenter.ref) || ''; const radiusNow = getRadius();\n    document.getElementById(\"resTitle\").innerHTML = `<strong>Stadt: ${cityName}<\/strong>`;\n    \n    let compassBadge = \"\";\n    if (isCompassActive) {\n      if (isCompassInverted) { compassBadge = ` &nbsp;|&nbsp; <span style=\"color: #ef4444; font-weight: bold;\">\ud83e\udded Kompass: Umgekehrt<\/span>`; }\n      else { compassBadge = ` &nbsp;|&nbsp; <span style=\"color: #22c55e; font-weight: bold;\">\ud83e\udded Kompass aktiv<\/span>`; }\n    }\n    \n    document.getElementById(\"resMeta\").innerHTML = `${viewResults.length} Treffer im Umkreis (${radiusNow} km)${compassBadge}`;\n\n    const resListEl = document.getElementById(\"resList\");\n    resListEl.innerHTML = viewResults.map((p, i) => {\n      let roadBadgeHtml = '';\n      let timeBadgeHtml = `<span class=\"badge badge-time\" id=\"time-${i}\"><\/span>`;\n      \n      if (i < 10) {\n        roadBadgeHtml = `<span class=\"badge badge-road\" id=\"road-${i}\" title=\"Klicke auf 'Fahrstrecke berechnen'\">--- km<\/span>`;\n      } else {\n        roadBadgeHtml = `<span class=\"badge badge-road\" style=\"cursor: default;\" title=\"Wird nur f\u00fcr die Top 10 berechnet\">--- km<\/span>`;\n      }\n\n      return `<li class=\"result-item\">\n          <div class=\"result-left\">\n            <strong class=\"copy-plz\" title=\"PLZ kopieren\" onclick=\"copyPLZ('${p.plz}', this)\">${p.plz}<\/strong> ${p.ort}\n          <\/div>\n          <div class=\"result-badges\">\n            ${timeBadgeHtml}\n            ${roadBadgeHtml}\n            <span class=\"badge\" title=\"Luftlinie\">${p.dist.toFixed(1)} km<\/span>\n          <\/div>\n       <\/li>`;\n    }).join('');\n\n    markerLayerGroup.clearLayers();\n    markerLayerGroup.addLayer(L.marker([lastCenter.centerLat, lastCenter.centerLon], { icon: searchIcon }).bindPopup(`Gesuchter Ort: ${formatPlzCountry(lastCenter.ref.properties.plz)} ${cityName}`));\n    \n    if (limitVal !== 'all') {\n      viewResults.forEach(p => markerLayerGroup.addLayer(L.marker([p.lat, p.lon], { icon: resultIcon }).bindPopup(`${p.plz} ${p.ort}`)));\n    }\n    \n    const btnCalc = document.getElementById(\"btnCalcRoute\");\n    btnCalc.innerHTML = \"<span>Fahrstrecke berechnen<\/span>\";\n    btnCalc.classList.remove('is-loading');\n    btnCalc.classList.remove('is-success');\n  }\n\n  document.getElementById(\"radiusInput\").addEventListener(\"input\", (e) => {\n    document.getElementById(\"radiusNumber\").value = e.target.value; document.getElementById(\"radiusLabel\").innerText = e.target.value;\n    if (searchActive && circleLayer) { circleLayer.setRadius(e.target.value * 1000); recomputeMatches(e.target.value); applySortAndRender(); }\n  });\n  document.getElementById(\"radiusNumber\").addEventListener(\"input\", (e) => {\n    let val = Math.min(100, Math.max(1, Number(e.target.value) || 30));\n    document.getElementById(\"radiusInput\").value = val; document.getElementById(\"radiusLabel\").innerText = val;\n    if (searchActive && circleLayer) { circleLayer.setRadius(val * 1000); recomputeMatches(val); applySortAndRender(); }\n  });\n  document.getElementById(\"sortSelect\").addEventListener(\"change\", () => { if(searchActive) applySortAndRender(); });\n  document.getElementById(\"limitSelect\").addEventListener(\"change\", () => { if(searchActive) applySortAndRender(); });\n\n  function historyKey() { return 'plzHistory_' + currentCountry; }\n  \n  function saveSearch(entry) {\n    if (!entry.plz && !entry.q) return; \n    let key = historyKey(); let h = JSON.parse(localStorage.getItem(key) || \"[]\");\n    h = h.filter(e => !(e.plz === entry.plz && e.radius === entry.radius)); \n    h.unshift(entry); if (h.length > 10) h = h.slice(0, 10);\n    localStorage.setItem(key, JSON.stringify(h)); renderHistory();\n  }\n  \n  function renderHistory() {\n    const list = document.getElementById(\"history-list\"); list.innerHTML = \"\"; \n    const h = JSON.parse(localStorage.getItem(historyKey()) || \"[]\");\n    for (const e of h) {\n      const li = document.createElement(\"li\"); \n      const dispName = `${e.plz || e.q} ${e.ort || ''}`.trim();\n      li.textContent = `${dispName} (${e.radius} km)`;\n      li.title = li.textContent;\n      li.onclick = () => { \n        document.getElementById(\"searchInput\").value = e.plz || e.q; \n        document.getElementById(\"radiusInput\").value = e.radius; \n        document.getElementById(\"radiusNumber\").value = e.radius; \n        document.getElementById(\"radiusLabel\").innerText = e.radius; \n        document.getElementById(\"btnSearch\").click(); \n      };\n      list.appendChild(li);\n    }\n  }\n  \n  function clearHistory(silent) { localStorage.removeItem(historyKey()); renderHistory(); }\n  document.getElementById(\"clear-history\").addEventListener(\"click\", () => clearHistory(false));\n  renderHistory();\n  \n  document.getElementById(\"expToggle\").addEventListener(\"click\", () => { document.getElementById(\"expPanel\").classList.toggle(\"open\"); });\n\n  function downloadBlob(blob, filename) {\n    const url = URL.createObjectURL(blob); const a = document.createElement('a');\n    a.href = url; a.download = filename; document.body.appendChild(a); a.click(); a.remove();\n    setTimeout(() => URL.revokeObjectURL(url), 1000);\n  }\n\n  function exportMeta() {\n    const r = getRadius(), limMap = { top10: 'Top 10', top20: 'Top 20', all: 'Alle' };\n    const sortMap = { 'dist-asc': 'Distanz \u2191', 'plz-asc': 'PLZ \u2191', 'name-asc': 'Ort A\u2013Z' };\n    let city = ''; if (lastCenter && lastCenter.ref) { city = (formatPlzCountry(lastCenter.ref.properties.plz) + ' ' + safeOrt(lastCenter.ref)).trim(); }\n    return { title: `Suchergebnis \u00b7 ${currentCountry} \u00b7 Radius ${r} km \u00b7 Umfang ${limMap[document.getElementById(\"limitSelect\").value] || 'Alle'} \u00b7 Sortierung ${sortMap[document.getElementById(\"sortSelect\").value]}`, city };\n  }\n\n  function visibleColumns() {\n    const byDist = (document.getElementById(\"sortSelect\").value === 'dist-asc');\n    return { byDist, header: byDist ? ['PLZ', 'Ort', 'Distanz_km'] : ['PLZ', 'Ort'] };\n  }\n\n  document.getElementById(\"btnExportCsv\").addEventListener(\"click\", () => {\n    if (!viewResults.length) return; const meta = exportMeta(), cols = visibleColumns();\n    const rows = viewResults.map(r => cols.byDist ? [r.plz, r.ort, r.dist ? r.dist.toFixed(2) : \"\"] : [r.plz, r.ort]);\n    const csv = [[meta.title], meta.city ? [`Gesuchter Ort: ${meta.city}`] : [], [], cols.header, ...rows]\n      .filter(r => r.length > 0).map(r => r.map(x => String(x).replace(\/\"\/g, '\"\"')).map(x => `\"${x}\"`).join(',')).join('\\n');\n    downloadBlob(new Blob([csv], { type: 'text\/csv;charset=utf-8;' }), `plzprofi_${currentCountry}_${Date.now()}.csv`);\n  });\n\n  document.getElementById(\"btnExportXlsx\").addEventListener(\"click\", () => {\n    if (!viewResults.length) return; const meta = exportMeta(), cols = visibleColumns();\n    const sheet = [[meta.title]]; if (meta.city) sheet.push([`Gesuchter Ort: ${meta.city}`]); sheet.push([]); sheet.push(cols.header);\n    viewResults.forEach(r => sheet.push(cols.byDist ? [r.plz, r.ort, r.dist ? Number(r.dist.toFixed(2)) : \"\"] : [r.plz, r.ort]));\n    const ws = XLSX.utils.aoa_to_sheet(sheet), wb = XLSX.utils.book_new();\n    XLSX.utils.book_append_sheet(wb, ws, \"Ergebnisse\"); XLSX.writeFile(wb, `plzprofi_${currentCountry}_${Date.now()}.xlsx`);\n  });\n\n  document.getElementById(\"btnExportPdf\").addEventListener(\"click\", () => {\n    if (!viewResults.length) return; const meta = exportMeta(), cols = visibleColumns();\n    const { jsPDF } = window.jspdf; const doc = new jsPDF({ unit: 'pt', format: 'a4' });\n    doc.setFontSize(12); doc.text(meta.title, 40, 40); let y = 58;\n    if (meta.city) { doc.setFontSize(11); doc.text(`Gesuchter Ort: ${meta.city}`, 40, y); y += 18; }\n    doc.setFontSize(10); doc.text(cols.byDist ? 'PLZ   Ort                               Dist(km)' : 'PLZ   Ort', 40, y); y += 14;\n    for (const r of viewResults) {\n      const line = cols.byDist ? `${r.plz.padEnd(5)}  ${(r.ort || '').padEnd(30)}  ${(r.dist ? r.dist.toFixed(1) : \"\").padStart(7)}` : `${r.plz.padEnd(5)}  ${(r.ort || '')}`;\n      doc.text(line.substring(0, 95), 40, y); y += 14; if (y > 780) { doc.addPage(); y = 40; }\n    }\n    doc.save(`plzprofi_${currentCountry}_${Date.now()}.pdf`);\n  });\n\n  document.getElementById(\"btnExportTxt\").addEventListener(\"click\", () => {\n    if (!viewResults.length) return; const meta = exportMeta(), cols = visibleColumns();\n    const lines = [meta.title, meta.city ? `Gesuchter Ort: ${meta.city}` : '', '', cols.byDist ? 'PLZ | Ort | Distanz(km)' : 'PLZ | Ort', ...viewResults.map(r => cols.byDist ? `${r.plz} | ${r.ort} | ${r.dist ? r.dist.toFixed(1) : \"\"}` : `${r.plz} | ${r.ort}`)].filter(l => l !== '').join('\\n');\n    downloadBlob(new Blob([lines], { type: 'text\/plain;charset=utf-8;' }), `plzprofi_${currentCountry}_${Date.now()}.txt`);\n  });\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>PLZ Profi \u00b7 Umkreissuche Finden Sie St\u00e4dte in Ihrem Umkreis Entdecken Sie mit unserer PLZ Umkreissuche schnell und einfach St\u00e4dte und Postleitzahlen in Ihrer Umgebung. Jetzt Suche starten \ud83d\udca1 Lade Tipp des Tages&#8230; \u2716 \ud83c\udde9\ud83c\uddea \ud83c\udde6\ud83c\uddf9 PLZ oder Ort: Ortsauswahl \u25bc Radius (1\u2013100 km): 30 km Suchen Kompass Aus Ein \ud83d\udd04 Umkehren Winkel: 0\u00b0 (Norden) [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"no-title","meta":{"footnotes":""},"class_list":["post-11","page","type-page","status-publish","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/plzprofi.de\/lt\/wp-json\/wp\/v2\/pages\/11","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/plzprofi.de\/lt\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/plzprofi.de\/lt\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/plzprofi.de\/lt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/plzprofi.de\/lt\/wp-json\/wp\/v2\/comments?post=11"}],"version-history":[{"count":90,"href":"https:\/\/plzprofi.de\/lt\/wp-json\/wp\/v2\/pages\/11\/revisions"}],"predecessor-version":[{"id":664,"href":"https:\/\/plzprofi.de\/lt\/wp-json\/wp\/v2\/pages\/11\/revisions\/664"}],"wp:attachment":[{"href":"https:\/\/plzprofi.de\/lt\/wp-json\/wp\/v2\/media?parent=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}