{"id":28037,"date":"2025-07-07T13:44:00","date_gmt":"2025-07-07T11:44:00","guid":{"rendered":"https:\/\/huset.se\/?page_id=28037"},"modified":"2025-07-12T13:37:30","modified_gmt":"2025-07-12T11:37:30","slug":"lediga_fastigheter","status":"publish","type":"page","link":"https:\/\/huset.se\/de\/lediga_fastigheter\/","title":{"rendered":"Leerstehende Immobilien"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"28037\" class=\"elementor elementor-28037\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-3fcf4f0 elementor-section-content-middle elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"3fcf4f0\" data-element_type=\"section\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-no\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-top-column elementor-element elementor-element-7e996f3\" data-id=\"7e996f3\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d2369b2 elementor-widget elementor-widget-text-editor\" data-id=\"d2369b2\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Interaktive Werkzeuge<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c60138d elementor-widget elementor-widget-heading\" data-id=\"c60138d\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Leerstehende Immobilien<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cf32b9b elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"cf32b9b\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-top-column elementor-element elementor-element-390a2a6\" data-id=\"390a2a6\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-589ea35 elementor-widget elementor-widget-image\" data-id=\"589ea35\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/huset.se\/wp-content\/uploads\/2023\/07\/Officebuilding2-scaled.webp\" title=\"B\u00fcrogeb\u00e4ude2\" alt=\"B\u00fcrogeb\u00e4ude2\" class=\"elementor-animation-grow\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-4ec5bab elementor-reverse-tablet elementor-reverse-mobile elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"4ec5bab\" data-element_type=\"section\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-021ff1f\" data-id=\"021ff1f\" data-element_type=\"column\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-6f79a8c elementor-widget elementor-widget-spacer\" data-id=\"6f79a8c\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-450a2eb elementor-widget elementor-widget-heading\" data-id=\"450a2eb\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Ein nahtloses Erlebnis - direkt auf Ihrer Website<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ee77ebd elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"ee77ebd\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-44eb803 elementor-widget elementor-widget-text-editor\" data-id=\"44eb803\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p data-start=\"232\" data-end=\"579\">F\u00fcr Immobilieneigent\u00fcmer und -makler mit mehreren Immobilien bieten wir jetzt eine ma\u00dfgeschneiderte L\u00f6sung an, um die vorgestellten Immobilien mit einer Eleganz und Zug\u00e4nglichkeit zu pr\u00e4sentieren, die bisher fehlte. Mit unserer neuen Funktion k\u00f6nnen Sie ganz einfach ein vollst\u00e4ndiges Modul f\u00fcr die Immobiliensuche in Ihre eigene Website integrieren - Sie m\u00fcssen nur etwas Code kopieren und einf\u00fcgen.<\/p><p data-start=\"581\" data-end=\"806\">Besucher erhalten direkten Zugang zu Ihren verf\u00fcgbaren Miet- oder Kaufobjekten, mit der M\u00f6glichkeit, nach Gebiet, Preis, Grundriss und mehr zu filtern - alles in einer exklusiven und benutzerfreundlichen Pr\u00e4sentation.<\/p><p data-start=\"808\" data-end=\"873\">Um die Erfahrung noch weiter zu verbessern, wird das Modul mit anderen kombiniert:<\/p><ul data-start=\"875\" data-end=\"1179\"><li data-start=\"875\" data-end=\"980\"><p data-start=\"877\" data-end=\"980\"><strong data-start=\"877\" data-end=\"899\">Digitale Anzeigen<\/strong> die es den Spekulanten erm\u00f6glicht, die Immobilie rund um die Uhr und unabh\u00e4ngig vom Standort zu erleben.<\/p><\/li><li data-start=\"981\" data-end=\"1179\"><p data-start=\"983\" data-end=\"1179\"><strong data-start=\"983\" data-end=\"1007\">Unser KI-Verkaufsassistent<\/strong>die nicht nur Fragen in mehreren Sprachen beantwortet, sondern auch Interessensbekundungen bearbeitet, Spekulanten ber\u00e4t und Ihnen die allt\u00e4glichen Aufgaben abnimmt - mit Pr\u00e4zision und Diskretion.<\/p><\/li><\/ul><p data-start=\"1181\" data-end=\"1329\">Das Ergebnis ist eine intelligente L\u00f6sung, die die Arbeit rationalisiert, das Markenerlebnis verbessert und Ihnen Zeit f\u00fcr die wertvollsten Kundengespr\u00e4che verschafft.<\/p><p data-start=\"1331\" data-end=\"1387\"><strong data-start=\"1331\" data-end=\"1387\">Vermitteln Sie nicht nur eine Eigenschaft. Vermitteln Sie ein Gef\u00fchl.<\/strong><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-97a6100 elementor-widget elementor-widget-heading\" data-id=\"97a6100\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Ein nahtloses Erlebnis - direkt auf Ihrer Website<\/h2>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-93cab3b elementor-reverse-tablet elementor-reverse-mobile elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"93cab3b\" data-element_type=\"section\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-636c3cc\" data-id=\"636c3cc\" data-element_type=\"column\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-34166f8 elementor-widget elementor-widget-spacer\" data-id=\"34166f8\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-55d4c8f elementor-widget elementor-widget-html\" data-id=\"55d4c8f\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Grundst\u00fccksfl\u00e4che Verf\u00fcgbarkeit<\/title>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <!-- Leaflet.js CSS -->\n  <link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/leaflet.css\" \/>\n  <!-- MarkerCluster CSS -->\n  <link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet.markercluster@1.4.1\/dist\/MarkerCluster.css\" \/>\n  <link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet.markercluster@1.4.1\/dist\/MarkerCluster.Default.css\" \/>\n  <!-- noUiSlider CSS -->\n  <link rel=\"stylesheet\" href=\"https:\/\/cdn.jsdelivr.net\/npm\/nouislider@15.7.1\/dist\/nouislider.min.css\" \/>\n  <style>\n    \/* CSS Reset for property listing component to prevent style conflicts *\/\n    #property-listing-component,\n    #property-listing-component * {\n      box-sizing: border-box !important;\n      margin: 0 !important;\n      padding: 0 !important;\n      font-family: Arial, sans-serif !important;\n      line-height: normal !important;\n      text-align: left !important;\n      font-size: 16px !important;\n      color: #333 !important;\n    }\n    \n    \/* Global styles - not affecting property listing *\/\n    body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f5f5f5; }\n    \n    \/* Property Listing App - Isolated CSS with ID-based scoping and !important flags *\/\n    #property-listing-component {\n      font-family: Arial, sans-serif !important;\n      max-width: 900px !important;\n      margin: 0 auto !important;\n      padding: 1em !important;\n      background: #fff !important;\n      border-radius: 8px !important;\n      box-shadow: 0 2px 10px rgba(0,0,0,0.1) !important;\n      \/* Reset properties that might be inherited *\/\n      color: #333 !important;\n      line-height: 1.4 !important;\n      font-size: 16px !important;\n      text-align: left !important;\n      \/* Prevent external styles from affecting layout *\/\n      width: auto !important;\n      height: auto !important;\n      min-height: 0 !important;\n      min-width: 0 !important;\n      max-height: none !important;\n      position: relative !important;\n      top: auto !important;\n      left: auto !important;\n      right: auto !important;\n      bottom: auto !important;\n      float: none !important;\n      clear: none !important;\n      z-index: auto !important;\n    }\n    \/* Map container *\/\n    #property-listing-component #map {\n      height: 400px !important;\n      max-width: 600px !important;\n      margin: 2em auto !important;\n      border-radius: 12px !important;\n      box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important;\n      z-index: 1 !important;\n    }\n    \n    \/* Leaflet map specific overrides to ensure proper display within the component *\/\n    #property-listing-component .leaflet-container {\n      font-family: Arial, sans-serif !important;\n      z-index: 1 !important;\n    }\n    \n    #property-listing-component .leaflet-popup-content-wrapper {\n      border-radius: 8px !important;\n      padding: 0 !important;\n    }\n    \n    #property-listing-component .leaflet-popup-content {\n      margin: 10px 12px !important;\n      line-height: 1.5 !important;\n      font-size: 14px !important;\n    }\n    \n    #property-listing-component .leaflet-popup-content p {\n      margin: 0 0 5px 0 !important;\n      padding: 0 !important;\n      line-height: 1.4 !important;\n    }\n    \n    #property-listing-component .leaflet-popup-content b {\n      font-weight: bold !important;\n      display: inline-block !important;\n      margin-bottom: 2px !important;\n    }\n    \n    #property-listing-component .leaflet-control-zoom a {\n      color: #000 !important;\n      text-decoration: none !important;\n      text-align: center !important;\n    }\n    \n    #property-listing-component .leaflet-marker-icon {\n      z-index: 10 !important;\n    }\n    \n    #property-listing-component .marker-cluster {\n      background-clip: padding-box !important;\n      border-radius: 20px !important;\n    }\n    \n    #property-listing-component .marker-cluster div {\n      width: 30px !important;\n      height: 30px !important;\n      margin-left: 5px !important;\n      margin-top: 5px !important;\n      text-align: center !important;\n      border-radius: 15px !important;\n      font-size: 12px !important;\n      color: #fff !important;\n      line-height: 30px !important;\n    }\n    \n    \/* Button styles *\/\n    #property-listing-component .dropdown-toggle, \n    #property-listing-component .action-button {\n      background-color: #f0f0f0 !important;\n      border: 1px solid #ddd !important;\n      padding: 8px 16px !important;\n      border-radius: 4px !important;\n      cursor: pointer !important;\n      margin-top: 10px !important;\n      margin-right: 5px !important;\n      display: inline-block !important;\n      text-decoration: none !important;\n      font-size: 14px !important;\n    }\n    \n    #property-listing-component .action-button {\n      background-color: #4CAF50 !important;\n      color: white !important;\n      border: none !important;\n    }\n    \n    #property-listing-component .action-button:hover {\n      background-color: #45a049 !important;\n    }\n    \n    #property-listing-component h1 { \n      color: #2c3e50 !important; \n      font-size: 24px !important;\n      margin-bottom: 15px !important;\n    }\n    \n    \/* Filter bar *\/\n    #property-listing-component .filter-bar { \n      background: #eafffa !important; \n      padding: 1em 1em 0.5em 1em !important; \n      border-radius: 12px !important; \n      margin-bottom: 1.5em !important; \n      box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; \n      max-width: 600px !important; \n      margin-left: auto !important; \n      margin-right: auto !important; \n    }\n    \n    #property-listing-component .filter-group { \n      display: flex !important; \n      flex-wrap: wrap !important; \n      gap: 1em !important; \n      margin-bottom: 1em !important; \n    }\n    \n    #property-listing-component .slider-container { \n      margin-bottom: 10px !important; \n      flex: 1 1 0px !important; \n      min-width: 140px !important; \n      max-width: 100% !important; \n      height: auto !important; \n      min-height: 0 !important; \n    }\n    \n    #property-listing-component .dropdown-toggle { \n      background: #3ecf8e !important; \n      color: #fff !important; \n      border: none !important; \n      border-radius: 22px !important; \n      padding: 0.5em 1.5em !important; \n      font-size: 1em !important; \n      font-weight: bold !important; \n      cursor: pointer !important; \n      margin-left: 1em !important; \n    }\n    \n    #property-listing-component .dropdown-toggle:active, \n    #property-listing-component .dropdown-toggle:focus { \n      background: #29b673 !important; \n      outline: none !important; \n    }\n    \n    #property-listing-component .dropdown-filters { \n      width: 100% !important; \n      margin-top: 2px !important; \n      animation: dropdownFade 0.2s !important; \n    }\n    \n    @keyframes dropdownFade { \n      from { opacity: 0; } \n      to { opacity: 1; } \n    }\n    \n    #property-listing-component .slider-label { \n      display: block !important; \n      margin-bottom: 3px !important; \n      font-weight: bold !important; \n      font-size: 0.9em !important; \n    }\n    \n    #property-listing-component .slider-row { \n      display: block !important; \n      width: 100% !important; \n    }\n    \n    #property-listing-component .range-slider-container { \n      position: relative !important; \n      width: 100% !important; \n      height: 36px !important; \n      min-height: 0 !important; \n      margin-bottom: 6px !important; \n    }\n    #property-listing-component .range-slider { \n      width: calc(100% - 14px) !important; \n      height: 4px !important; \n      min-height: 0 !important; \n      background: #e0e0e0 !important; \n      position: absolute !important; \n      top: 50% !important; \n      left: 7px !important; \n      transform: translateY(-50%) !important; \n      border-radius: 2px !important; \n    }\n    \n    #property-listing-component .range-slider .range-selected { \n      height: 100% !important; \n      background-color: #3ecf8e !important; \n      position: absolute !important; \n    }\n    \n    #property-listing-component .range-slider .range-handle { \n      width: 14px !important; \n      height: 14px !important; \n      background: white !important; \n      border: 2px solid #3ecf8e !important; \n      border-radius: 50% !important; \n      position: absolute !important; \n      top: 50% !important; \n      cursor: pointer !important; \n      z-index: 2 !important; \n      box-shadow: 0 1px 3px rgba(0,0,0,0.2) !important; \n      transform: translateY(-50%) !important; \n    }\n    \n    #property-listing-component .range-slider .range-handle.left { \n      z-index: 3 !important;\n    }\n    \n    #property-listing-component .range-slider .range-handle.right { \n      z-index: 4 !important;\n    }\n    \n    #property-listing-component .range-slider .range-handle.left { \n      left: -7px !important; \n    }\n    \n    #property-listing-component .range-slider .range-handle.right { \n      right: -7px !important; \n    }\n    \n    #property-listing-component .range-values { \n      display: flex !important; \n      justify-content: space-between !important; \n      width: 100% !important; \n      margin-top: 0 !important; \n      margin-bottom: 8px !important; \n      font-size: 0.8em !important; \n      color: #666 !important; \n    }\n    \n    #property-listing-component .range-values .min-value { \n      display: block !important; \n      text-align: left !important; \n    }\n    \n    #property-listing-component .range-values .max-value { \n      display: block !important; \n      text-align: right !important; \n    }\n    \n    #property-listing-component #activeFilters { \n      margin-top: 1em !important; \n    }\n    \n    #property-listing-component .chip { \n      display: inline-block !important; \n      background: #f2f2f2 !important; \n      border-radius: 16px !important; \n      padding: 0.25em 0.75em !important; \n      margin: 0 0.5em 0.5em 0 !important; \n      font-size: 0.95em !important; \n    }\n    \n    #property-listing-component .chip button { \n      background: none !important; \n      border: none !important; \n      color: #888 !important; \n      cursor: pointer !important; \n      font-size: 1em !important; \n      margin-left: 0.5em !important; \n    }\n    \n    #property-listing-component .card-grid, #property-listing-component #cardGrid {\n      display: grid !important;\n      grid-template-columns: 1fr !important;\n      gap: 1.5em !important;\n    }\n    \n    #property-listing-component .card { \n      background: #fff !important; \n      border-radius: 8px !important; \n      border: 1px solid #e0e0e0 !important;\n      box-shadow: 0 1px 3px rgba(0,0,0,0.05) !important; \n      overflow: hidden !important; \n      min-height: 180px !important; \n      display: block !important;\n    }\n    \n    #property-listing-component .card-img { \n      width: 100% !important;\n      height: 160px !important;\n      background: #f5f5f5 !important; \n      display: flex !important; \n      align-items: center !important; \n      justify-content: center !important; \n    }\n    \n    #property-listing-component .card-img img { \n      width: 100% !important; \n      height: auto !important; \n      display: block !important; \n    }\n    \n    #property-listing-component .img-placeholder { \n      width: 80px !important; \n      height: 120px !important; \n      background: #d9e5ea !important; \n      border-radius: 8px !important; \n    }\n    \n    #property-listing-component .card-content { \n      padding: 1.2em !important; \n      display: flex !important; \n      flex-direction: column !important; \n      justify-content: space-between !important; \n    }\n    \n    #property-listing-component .card-status { \n      font-size: 0.9em !important; \n      margin-bottom: 0.5em !important; \n      display: flex !important; \n      align-items: center !important; \n      gap: 0.5em !important; \n      color: #333 !important;\n      font-weight: 500 !important;\n    }\n    \n    #property-listing-component .status-text {\n      font-size: 1.25em !important;\n      font-weight: bold !important;\n      margin-right: 0.5em;\n    }\n    \n    #property-listing-component .dot { \n      display: inline-block !important; \n      width: 10px !important; \n      height: 10px !important; \n      border-radius: 50% !important; \n      margin-right: 0.5em !important; \n    }\n    \n    #property-listing-component .dot-green { \n      background: #4caf50 !important; \n    }\n    \n    #property-listing-component .dot-yellow { \n      background: #ffb300 !important; \n    }\n    \n    #property-listing-component .dot-red { \n      background: #e53935 !important; \n    }\n    \n    #property-listing-component #property-listing-component .card-label,\n#property-listing-component .card-label {\n  font-weight: bold !important;\n  color: #222 !important;\n  margin-right: 0.2em !important;\n}\n    \n    #property-listing-component .card-title { \n      font-weight: bold !important; \n      font-size: 1.1em !important; \n      margin-bottom: 0.5em !important; \n      color: #333 !important;\n    }\n    \n    #property-listing-component .card-desc { \n      font-size: 0.97em !important; \n      color: #555 !important; \n      margin-bottom: 0.5em !important; \n    }\n    \n    #property-listing-component .card-info { \n      display: grid !important; \n      grid-template-columns: 1fr 1fr !important;\n      row-gap: 0.8em !important;\n      column-gap: 1em !important;\n      font-size: 0.9em !important; \n      margin-bottom: 1.2em !important; \n      color: #333 !important;\n    }\n    \n    #property-listing-component .card-info span { \n      white-space: nowrap !important; \n      display: block !important;\n    }\n    \n    #property-listing-component .card-info b {\n      display: block !important;\n      font-weight: 500 !important;\n      margin-top: 0.2em !important;\n    }\n    \n    #property-listing-component .show-btn { \n      background: #000 !important; \n      color: #fff !important; \n      border: none !important; \n      border-radius: 4px !important; \n      padding: 0.7em 1em !important; \n      font-size: 0.9em !important; \n      cursor: pointer !important; \n      text-align: center !important;\n      width: 100% !important;\n      transition: background 0.2s !important; \n      text-decoration: none !important;\n      display: block !important;\n    }\n    \n    #property-listing-component .show-btn:hover { \n      background: #333 !important; \n    }\n    \n    #property-listing-component .no-results { \n      padding: 2em !important; \n      text-align: center !important; \n      color: #888 !important; \n    }\n    \n    \/* Card buttons and interest button styles *\/\n    #property-listing-component .card-buttons { \n      display: flex !important; \n      gap: 0.5em !important; \n      margin-top: auto !important; \n    }\n    \n    #property-listing-component .interest-btn { \n      background: #fff !important; \n      color: #000 !important; \n      border: 1px solid #000 !important; \n      border-radius: 4px !important; \n      padding: 0.7em 1em !important; \n      font-size: 0.9em !important; \n      cursor: pointer !important; \n      text-decoration: none !important;\n      text-align: center !important;\n      width: 100% !important;\n      display: block !important;\n    }\n    \n    \/* Media queries - properly scoped to component *\/\n    @media (max-width: 600px) {\n      #property-listing-component .slider-label { \n        margin-bottom: 8px !important; \n      }\n      #property-listing-component .card-grid { \n        grid-template-columns: 1fr !important; \n      }\n      #property-listing-component .card { \n        flex-direction: column !important; \n        min-height: unset !important; \n      }\n      #property-listing-component .card-img, \n      #property-listing-component .img-placeholder { \n        min-width: 100% !important; \n        max-width: 100% !important; \n      }\n      #property-listing-component .card-content { \n        padding: 1em !important; \n      }\n      #property-listing-component .filter-bar { \n        padding: 0.7em 0.5em !important; \n        max-width: 100vw !important; \n        border-radius: 0 !important; \n        background: #f8fffd !important; \n      }\n      #property-listing-component .filter-group { \n        display: block !important; \n        gap: 32px !important; \n        margin-bottom: 8px !important; \n      }\n      #property-listing-component .slider-container { \n        display: block !important; \n        width: 100% !important; \n        min-width: 0 !important; \n        flex: unset !important; \n        margin-bottom: 0 !important; \n        background: #f4fcfa !important; \n        border-radius: 10px !important; \n        padding: 12px 10px 6px 10px !important; \n        box-shadow: 0 1px 6px rgba(0,0,0,0.1) !important; \n      }\n      #property-listing-component .dropdown-toggle { \n        margin-bottom: 4px !important; \n        margin-left: 0 !important; \n        width: 100% !important; \n      }\n    }\n    \/* Custom touch area for noUiSlider handles *\/\n    .slider-row-group {\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  gap: 18px 24px;\n  margin-bottom: 12px;\n}\n@media (max-width: 700px) {\n  .slider-row-group {\n    grid-template-columns: 1fr;\n  }\n}\n.slider-row-group .slider-container {\n  min-width: 0;\n  max-width: 100%;\n}\n    .noUi-touch-area {\n      width: 24px !important;\n      height: 24px !important;\n    }\n    .noUi-handle {\n      width: 24px !important;\n      height: 24px !important;\n      box-sizing: border-box !important;\n    }\n  <\/style>\n<\/head>\n<body>\n  <div id=\"property-listing-component\">\n    <div id=\"map\"><\/div> <!-- Map container -->\n    <div class=\"filter-bar\">\n    <div class=\"filter-group\">\n        <div class=\"slider-container\">\n          <label class=\"slider-label\">Objekttyp<\/label>\n          <div class=\"slider-row\">\n            <select id=\"typeFilter\"><option value=\"\">Alle<\/option><\/select>\n          <\/div>\n        <\/div>\n      <button id=\"toggleFiltersBtn\" class=\"dropdown-toggle\">Weitere Filter anzeigen<\/button>\n      <button id=\"showOnMapBtn\" class=\"action-button\">Auf der Karte anzeigen<\/button>\n    <\/div>\n    <div id=\"dropdownFilters\" class=\"dropdown-filters\" style=\"display:none;\">\n      <div class=\"filter-group\">\n        <div class=\"slider-row-group\">\n          <div class=\"slider-container\">\n            <label class=\"slider-label\">Gr\u00f6\u00dfe (Quadratmeter)<\/label>\n            <div class=\"slider-row\">\n              <div id=\"sizeSlider\"><\/div>\n              <span id=\"sizeMinValue\" class=\"min-value\">0 Quadratmeter<\/span>\n              <span id=\"sizeMaxValue\" class=\"max-value\">200 Quadratmeter<\/span>\n            <\/div>\n          <\/div>\n          <div class=\"slider-container\">\n            <label class=\"slider-label\">Preis (kr)<\/label>\n            <div class=\"slider-row\">\n              <div id=\"priceSlider\"><\/div>\n              <span id=\"priceMinValue\" class=\"min-value\">0 kr<\/span>\n              <span id=\"priceMaxValue\" class=\"max-value\">15 000 000 SEK<\/span>\n            <\/div>\n          <\/div>\n          <div class=\"slider-container\">\n            <label class=\"slider-label\">Geb\u00fchr (SEK)<\/label>\n            <div class=\"slider-row\">\n              <div id=\"feeSlider\"><\/div>\n              <span id=\"feeMinValue\" class=\"min-value\">0 kr<\/span>\n              <span id=\"feeMaxValue\" class=\"max-value\">10 000 SEK<\/span>\n            <\/div>\n          <\/div>\n          <div class=\"slider-container\">\n            <label class=\"slider-label\">Boden<\/label>\n            <div class=\"slider-row\">\n              <div id=\"floorSlider\"><\/div>\n              <span id=\"floorMinValue\" class=\"min-value\">0<\/span>\n              <span id=\"floorMaxValue\" class=\"max-value\">10<\/span>\n            <\/div>\n          <\/div>\n        <\/div>\n\n        <div class=\"slider-container\">\n          <label class=\"slider-label\">Status<\/label>\n          <div class=\"slider-row\">\n            <select id=\"statusFilter\"><option value=\"\">Alle<\/option><\/select>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n  <div id=\"activeFilters\"><\/div>\n  <div id=\"cardGrid\" class=\"card-grid\"><\/div>\n  <!-- Leaflet.js -->\n  <script src=\"https:\/\/unpkg.com\/leaflet@1.7.1\/dist\/leaflet.js\"><\/script>\n  <!-- MarkerCluster JS -->\n  <script src=\"https:\/\/unpkg.com\/leaflet.markercluster@1.4.1\/dist\/leaflet.markercluster.js\"><\/script>\n<!-- noUiSlider JS -->\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/nouislider@15.7.1\/dist\/nouislider.min.js\"><\/script>\n  <script>\n    \/\/ Global variable to store all property units\n    let allUnits = [];\n    \n    \/\/ Debug function to log data structure\n    function debugLogData(data, label) {\n      console.log(`DEBUG ${label}:`, data);\n      if (Array.isArray(data) && data.length > 0) {\n        console.log('Sample item keys:', Object.keys(data[0]));\n      }\n    }\n    \n    \/\/ Function to fetch property data from secure API proxy\n    function fetchPropertyData() {\n      const status = document.getElementById('skickaStatus');\n      if (status) status.textContent = 'Fetching property data...';\n      \n      \/\/ Check if we're running locally (which would cause CORS issues)\n      const isLocalEnvironment = window.location.protocol === 'file:' || \n                               window.location.hostname === 'localhost' || \n                               window.location.hostname === '127.0.0.1';\n      \n      if (isLocalEnvironment) {\n        console.log('Running in local environment - using hardcoded data to avoid CORS issues');\n        if (status) status.textContent = 'Using local data for development';\n        loadHardcodedData();\n        setTimeout(() => { if (status) status.textContent = ''; }, 3000);\n        return Promise.resolve(allUnits);\n      }\n      \n      \/\/ Use our secure API proxy instead of directly accessing the external API\n      return fetch('https:\/\/husetexklusiv.se\/digitalvisning\/ledigafastigheter\/api\/properties.php?action=getProperties', {\n        method: 'GET',\n        headers: { \n          'Content-Type': 'application\/json'\n        }\n      })\n      .then(response => {\n        if (!response.ok) {\n          throw new Error(`HTTP error! Status: ${response.status}`);\n        }\n        return response.json();\n      })\n      .then(data => {\n        console.log('Received property data:', data);\n        if (status) status.textContent = 'Property data updated!';\n        \n        \/\/ Map the received data to our format\n        if (Array.isArray(data)) {\n          allUnits = data.map(u => ({\n            id: u.objekt_nr || u.id || '',\n            title: u.objekt_nr || '',\n            status: u.Availability || '',\n            size: u.storlek || '',\n            floor: u.plan || '',\n            rooms: u.rum || '',\n            fee: u.avgift || '',\n            price: u.pris || '',\n            type: u.objekttyp || '',\n            description: '', \n            image: '',\n            map_url: u.map_url || '',\n            latitude: u.latitude || null,\n            longitude: u.longitude || null,\n            visa_objekt: u.visa_objekt || ''\n          }));\n          \n          \/\/ Update the UI with new data\n          renderFilters(allUnits);\n          renderCards();\n          renderMap(allUnits);\n          setTimeout(() => { if (status) status.textContent = ''; }, 3000);\n          return allUnits;\n        } else {\n          throw new Error('Received data is not an array');\n        }\n      })\n      .catch(error => {\n        \/\/ Check if this is a CORS error\n        const isCorsError = error.message.includes('CORS') || \n                          error.message.includes('Failed to fetch') || \n                          error.message.includes('NetworkError');\n        \n        if (isCorsError) {\n          console.warn('CORS error detected - this is expected when running locally');\n          console.warn('Using hardcoded data instead');\n          if (status) status.textContent = 'Using local data (CORS restriction)';\n        } else {\n          console.error('Error fetching property data:', error);\n          if (status) status.textContent = 'Error fetching data: ' + error.message;\n        }\n        \n        \/\/ Fall back to hardcoded data if fetch fails\n        loadHardcodedData();\n        return allUnits;\n      });\n    }\n    \n    \/\/ Initialize the page\n    window.addEventListener('DOMContentLoaded', function() {\n      \/\/ Make sure the map container is visible and has dimensions\n      const mapDiv = document.getElementById('map');\n      if (mapDiv) {\n        mapDiv.style.display = 'block';\n        mapDiv.style.height = '400px';\n        mapDiv.style.width = '100%';\n        mapDiv.style.maxWidth = '600px';\n        mapDiv.style.margin = '2em auto';\n      }\n      \n      \/\/ Only load data from NocoDB\n      fetchNocoDBData();\n\n      \/\/ Dropdown toggle logic\n      const toggleBtn = document.getElementById('toggleFiltersBtn');\n      const dropdown = document.getElementById('dropdownFilters');\n      if (toggleBtn && dropdown) {\n        toggleBtn.addEventListener('click', function() {\n          if (dropdown.style.display === 'none' || dropdown.style.display === '') {\n            dropdown.style.display = 'block';\n            toggleBtn.textContent = 'D\u00f6lj filter';\n          } else {\n            dropdown.style.display = 'none';\n            toggleBtn.textContent = 'Visa fler filter';\n          }\n        });\n      }\n    });\n    \n    \/\/ Filter configuration\n    let filters = {\n      type: '',\n      size: { min: 0, max: 200 },\n      price: { min: 0, max: 15000000 },\n      fee: { min: 0, max: 10000 },\n      floor: { min: 0, max: 10 },\n      status: ''\n    };\n    function renderFilters(units) {\n      console.log('Setting up filters with units:', units);\n      \n      \/\/ Extract numeric values from strings for comparison\n      const extractNumber = (str) => {\n        if (typeof str === 'string') {\n          \/\/ Remove all non-numeric characters except for the first decimal point\n          const numStr = str.replace(\/[^0-9.]\/g, '');\n          return parseFloat(numStr) || 0;\n        }\n        return str || 0;\n      };\n      \n      \/\/ Extract floor number from strings like \"2 av 10\"\n      const extractFloor = (str) => {\n        if (typeof str === 'string') {\n          const floorMatch = str.match(\/^(\\d+)\/);\n          if (floorMatch) {\n            return parseInt(floorMatch[1]);\n          }\n        }\n        return 0;\n      };\n      \n      \/\/ Get min and max values from the data\n      const sizeValues = units.map(u => extractNumber(u.size)).filter(v => v > 0);\n      const priceValues = units.map(u => extractNumber(u.price)).filter(v => v > 0);\n      const feeValues = units.map(u => extractNumber(u.fee)).filter(v => v > 0);\n      const floorValues = units.map(u => extractFloor(u.floor)).filter(v => v > 0);\n      \n      console.log('Extracted values:', {\n        size: sizeValues,\n        price: priceValues,\n        fee: feeValues,\n        floor: floorValues\n      });\n      \n      \/\/ Helper to show\/hide slider rows based on valid range, returns true if visible\n    function showOrHideSlider(sliderId, min, max) {\n      const slider = document.getElementById(sliderId);\n      if (!slider) return false;\n      const sliderRow = slider.closest('.slider-row');\n      if (!sliderRow) return false;\n      if (min === max || max === 0) {\n        sliderRow.style.display = 'none';\n        return false;\n      } else {\n        sliderRow.style.display = '';\n        return true;\n      }\n    }\n\n    \/\/ Update filters with actual min\/max values from data\n      \/\/ Storlek (kvm)\n      filters.size.min = 0;\n      filters.size.max = sizeValues.length > 0 ? Math.max(...sizeValues) : 0;\n      \n      document.getElementById('sizeMaxValue').textContent = filters.size.max ? filters.size.max + ' kvm' : '\u2013';\n      if (showOrHideSlider('sizeSlider', filters.size.min, filters.size.max)) {\n        initRangeSlider('sizeSlider', 'size');\n      }\n\n      \/\/ Pris (kr)\n      filters.price.min = 0;\n      filters.price.max = priceValues.length > 0 ? Math.max(...priceValues) : 0;\n      \n      document.getElementById('priceMaxValue').textContent = filters.price.max\n        ? filters.price.max.toLocaleString('sv-SE') + ' kr'\n        : '\u2013';\n      if (showOrHideSlider('priceSlider', filters.price.min, filters.price.max)) {\n        initRangeSlider('priceSlider', 'price');\n      }\n\n      \/\/ Avgift (kr)\n      filters.fee.min = 0;\n      filters.fee.max = feeValues.length > 0 ? Math.max(...feeValues) : 0;\n      \n      document.getElementById('feeMaxValue').textContent = filters.fee.max\n        ? filters.fee.max.toLocaleString('sv-SE') + ' kr'\n        : '\u2013';\n      if (showOrHideSlider('feeSlider', filters.fee.min, filters.fee.max)) {\n        initRangeSlider('feeSlider', 'fee');\n      }\n\n      \/\/ V\u00e5ning\n      filters.floor.min = 0;\n      filters.floor.max = floorValues.length > 0 ? Math.max(...floorValues) : 0;\n      \n      document.getElementById('floorMaxValue').textContent = filters.floor.max\n        ? filters.floor.max\n        : '\u2013';\n      if (showOrHideSlider('floorSlider', filters.floor.min, filters.floor.max)) {\n        initRangeSlider('floorSlider', 'floor');\n      }\n      \n      \/\/ Populate type dropdown\n      const typeSelect = document.getElementById('typeFilter');\n      const typeValues = [...new Set(units.map(u => u.type).filter(Boolean))];\n      typeSelect.innerHTML = `<option value=\"\">Alla<\/option>` + \n        typeValues.map(v => `<option value=\"${v}\">${v}<\/option>`).join('');\n\n      \/\/ Populate status dropdown\n      const statusSelect = document.getElementById('statusFilter');\n      const statusValues = [...new Set(units.map(u => u.status).filter(Boolean))];\n      statusSelect.innerHTML = `<option value=\"\">Alla<\/option>` + \n        statusValues.map(v => `<option value=\"${v}\">${v}<\/option>`).join('');\n      \n      console.log('Updated filters:', filters);\n    }\n    function renderActiveFilters() {\n      const filterNames = {\n        type: 'objekttyp', size: 'storlek', price: 'pris', fee: 'avgift', floor: 'plan', status: 'Status'\n      };\n      \n      \/\/ Format values for display in filter chips\n      function formatChipValue(key, value) {\n        if (typeof value !== 'object') {\n          if (!value) return null;\n          return value;\n        }\n        \n        \/\/ Check if min and max are at their default values\n        const defaultValues = {\n          rooms: { min: 1, max: 6 },\n          size: { min: 0, max: 200 },\n          price: { min: 0, max: 15000000 },\n          fee: { min: 0, max: 10000 },\n          floor: { min: 0, max: 10 }\n        };\n        \n        if (value.min === defaultValues[key].min && value.max === defaultValues[key].max) {\n          return null; \/\/ Don't show chip if using default range\n        }\n        \n        \/\/ Format min-max values based on filter type\n        let minFormatted, maxFormatted;\n        switch(key) {\n          case 'price':\n            minFormatted = new Intl.NumberFormat('sv-SE').format(value.min);\n            maxFormatted = new Intl.NumberFormat('sv-SE').format(value.max);\n            return `${minFormatted} - ${maxFormatted} kr`;\n          case 'fee':\n            minFormatted = new Intl.NumberFormat('sv-SE').format(value.min);\n            maxFormatted = new Intl.NumberFormat('sv-SE').format(value.max);\n            return `${minFormatted} - ${maxFormatted} kr`;\n          case 'size':\n            return `${value.min} - ${value.max} kvm`;\n          case 'rooms':\n          case 'floor':\n            return `${value.min} - ${value.max}`;\n          default:\n            return value;\n        }\n      }\n      \n      const chips = Object.entries(filters)\n        .map(([k, v]) => {\n          const formattedValue = formatChipValue(k, v);\n          if (!formattedValue) return '';\n          return `<span class=\"chip\">${filterNames[k]}: ${formattedValue} <button onclick=\"removeFilter('${k}')\">&times;<\/button><\/span>`;\n        })\n        .filter(chip => chip !== '');\n        \n      document.getElementById('activeFilters').innerHTML = chips.join(' ');\n    }\n    function removeFilter(key) {\n      \/\/ Reset filter to default values\n      if (key === 'status') {\n        filters[key] = '';\n        document.getElementById(key + 'Filter').value = '';\n      } else {\n        \/\/ Reset to default min\/max values\n        const defaultValues = {\n          rooms: { min: 1, max: 6 },\n          size: { min: 0, max: 200 },\n          price: { min: 0, max: 15000000 },\n          fee: { min: 0, max: 10000 },\n          floor: { min: 0, max: 10 }\n        };\n        \n        filters[key] = { ...defaultValues[key] };\n        \n        \/\/ Reset slider positions\n        const slider = document.getElementById(key + 'Slider');\n        if (slider) {\n          const leftHandle = slider.querySelector('.range-handle.left');\n          const rightHandle = slider.querySelector('.range-handle.right');\n          const rangeSelected = slider.querySelector('.range-selected');\n          \n          if (leftHandle && rightHandle && rangeSelected) {\n            leftHandle.style.left = '0%';\n            rightHandle.style.left = '100%';\n            rangeSelected.style.left = '0%';\n            rangeSelected.style.width = '100%';\n            \n            leftHandle.setAttribute('data-value', defaultValues[key].min);\n            rightHandle.setAttribute('data-value', defaultValues[key].max);\n            \n            \/\/ Update min\/max value displays\n            document.getElementById(key + 'MinValue').textContent = formatSliderValue(key, defaultValues[key].min, 'min');\n            document.getElementById(key + 'MaxValue').textContent = formatSliderValue(key, defaultValues[key].max, 'max');\n          }\n        }\n      }\n      renderActiveFilters();\n      renderCards();\n    }\n    \/\/ Track if we're in a debounced operation to control logging\n    let isDebouncing = false;\n    \n    \/\/ Helper function to ensure URLs have proper protocol\n    function ensureAbsoluteUrl(url) {\n      if (!url) return '';\n      \n      \/\/ Extract just the www.example.com part if the URL contains it\n      if (url.includes('www.') && !url.startsWith('www.') && !url.startsWith('http')) {\n        url = url.replace(\/.*?(www\\.[^\\s\/]+)\/, '$1');\n      }\n      \n      \/\/ Add https:\/\/ to URLs starting with www.\n      if (url.startsWith('www.')) {\n        return 'https:\/\/' + url;\n      }\n      \n      \/\/ If URL already has http:\/\/ or https:\/\/, return as is\n      if (url.startsWith('http:\/\/') || url.startsWith('https:\/\/')) {\n        return url;\n      }\n      \n      \/\/ Otherwise, add https:\/\/ as default protocol\n      return 'https:\/\/' + url;\n    }\n    \n    function filterUnits(silent = false) {\n      \/\/ Only log if not in silent mode\n      if (!silent) {\n        console.log('Filtering with criteria:', {\n          type: filters.type || 'Alla',\n          size: `${filters.size.min}-${filters.size.max}`,\n          price: `${filters.price.min}-${filters.price.max}`,\n          fee: `${filters.fee.min}-${filters.fee.max}`,\n          floor: `${filters.floor.min}-${filters.floor.max}`,\n          status: filters.status || 'Alla'\n        });\n      }\n      \n      const filteredUnits = allUnits.filter(u => {\n        \/\/ Extract numeric values from strings for comparison\n        const extractNumber = (str) => {\n          if (typeof str === 'string') {\n            \/\/ Remove all non-numeric characters except for the first decimal point\n            const numStr = str.replace(\/[^0-9.]\/g, '');\n            return parseFloat(numStr) || 0;\n          }\n          return str || 0;\n        };\n        \n        \/\/ Get numeric values for comparison\n        const sizeValue = extractNumber(u.size);\n        const priceValue = extractNumber(u.price);\n        const feeValue = extractNumber(u.fee);\n        \n        \/\/ Extract floor number from strings like \"2 av 10\"\n        let floorValue = 0;\n        if (typeof u.floor === 'string') {\n          const floorMatch = u.floor.match(\/^(\\d+)\/);\n          if (floorMatch) {\n            floorValue = parseInt(floorMatch[1]);\n          }\n        }\n        \n        \/\/ Check if values are within the min-max ranges\n        const typeMatch = !filters.type || u.type === filters.type;\n        \/\/ Allow empty or 0 values to pass if filter is at its default range\n        const sizeMatch = (u.size === '' || sizeValue === 0) ? filters.size.min === 0 : (sizeValue >= filters.size.min && sizeValue <= filters.size.max);\n        const priceMatch = (u.price === '' || priceValue === 0) ? filters.price.min === 0 : (priceValue >= filters.price.min && priceValue <= filters.price.max);\n        const feeMatch = (u.fee === '' || feeValue === 0) ? filters.fee.min === 0 : (feeValue >= filters.fee.min && feeValue <= filters.fee.max);\n        const floorMatch = (u.floor === '' || floorValue === 0) ? filters.floor.min === 0 : (floorValue >= filters.floor.min && floorValue <= filters.floor.max);\n        const statusMatch = !filters.status || u.status === filters.status;\n        \n        return typeMatch && sizeMatch && priceMatch && feeMatch && floorMatch && statusMatch;\n      });\n      \n      return filteredUnits;\n    }\n    function renderCards(silent = false) {\n      const filteredUnits = filterUnits(silent);\n      const grid = document.getElementById('cardGrid');\n      if (filteredUnits.length === 0) {\n        grid.innerHTML = '<div class=\"no-results\">Inga bost\u00e4der matchar filtren.<\/div>';\n        return;\n      }\n      grid.innerHTML = filteredUnits.map(unit => {\n        return `\n        <div class=\"card\">\n          <div class=\"card-content\">\n            <div class=\"card-status\">\n  <span class=\"dot ${unit.status && unit.status.toLowerCase() === 's\u00e5ld' ? 'dot-red' : unit.status && unit.status.toLowerCase() === 'reserverad' ? 'dot-yellow' : 'dot-green'}\"><\/span>\n  <span class=\"status-text\">${unit.status || 'Ledig'}<\/span>\n  <span style=\"margin-left: 1.5em;\">Objekt nr: <b>${unit.id || unit.title || ''}<\/b><\/span>\n<\/div>\n            <div class=\"card-info\">\n              <span><span class=\"card-label\">Storlek<\/span> ${unit.size || ''} m\u00b2<\/span>\n              <span><span class=\"card-label\">Plan<\/span> ${unit.floor || ''}<\/span>\n              <span><span class=\"card-label\">Rum<\/span> ${unit.rooms || ''}<\/span>\n              <span><span class=\"card-label\">Avgift<\/span> ${unit.fee ? unit.fee.toString().replace(\/\\s*kr\\s*$\/i, '').trim() + ' kr' : ''}<\/span>\n              <span><span class=\"card-label\">Pris<\/span> ${unit.price ? unit.price.toString().replace(\/\\s*kr\\s*$\/i, '').trim() + ' kr' : ''}<\/span>\n              <span><span class=\"card-label\">Bostadstyp<\/span> ${unit.type || 'L\u00e4genhet'}<\/span>\n            <\/div>\n            <div class=\"card-buttons\">\n              <button class=\"interest-btn\">Anm\u00e4l intresse<\/button>\n              ${unit.viewUrl ? `<a href=\"${ensureAbsoluteUrl(unit.viewUrl)}\" class=\"show-btn\">Visa bostad<\/a>` : '<button class=\"show-btn\">Visa bostad<\/button>'}\n            <\/div>\n          <\/div>\n        <\/div>\n        `;\n      }).join('');\n    }\n    \/\/ Format slider values based on filter type\n    function formatSliderValue(key, value, position) {\n      if (value === 0 && position === 'min') return 'Min';\n      \n      switch(key) {\n        case 'price':\n          return new Intl.NumberFormat('sv-SE').format(value) + (position === 'max' ? ' kr' : '');\n        case 'fee':\n          return new Intl.NumberFormat('sv-SE').format(value) + (position === 'max' ? ' kr' : '');\n        case 'size':\n          return value + (position === 'max' ? ' kvm' : '');\n        default:\n          return value;\n      }\n    }\n    \n    \/\/ Debounce function to limit how often a function is called\n    function debounce(func, wait) {\n      let timeout;\n      return function(...args) {\n        const context = this;\n        clearTimeout(timeout);\n        timeout = setTimeout(() => func.apply(context, args), wait);\n      };\n    }\n    \n    \/\/ Initialize range sliders\n    function initRangeSlider(sliderId, key) {\n      if (filters[key].min === filters[key].max || filters[key].max === 0) {\n        \/\/ Don't initialize slider if no valid range\n        return;\n      }\n      const slider = document.getElementById(sliderId);\n      if (!slider) return;\n\n      const leftHandle = slider.querySelector('.range-handle.left');\n      const rightHandle = slider.querySelector('.range-handle.right');\n      const rangeSelected = slider.querySelector('.range-selected');\n      const minValueDisplay = document.getElementById(key + 'MinValue');\n      const maxValueDisplay = document.getElementById(key + 'MaxValue');\n\n      if (!leftHandle || !rightHandle || !rangeSelected) return;\n\n      const minValue = filters[key].min;\n      const maxValue = filters[key].max;\n      const valueRange = maxValue - minValue;\n\n      \/\/ Initial positions (as fractions 0-1)\n      let minPos = (filters[key].min - minValue) \/ valueRange;\n      let maxPos = (filters[key].max - minValue) \/ valueRange;\n\n      function updateHandles() {\n        leftHandle.style.left = (minPos * 100) + '%';\n        rightHandle.style.left = (maxPos * 100) + '%';\n        rangeSelected.style.left = (minPos * 100) + '%';\n        rangeSelected.style.width = ((maxPos - minPos) * 100) + '%';\n        const minVal = Math.round(minValue + minPos * valueRange);\n        const maxVal = Math.round(minValue + maxPos * valueRange);\n        if (minValueDisplay) minValueDisplay.textContent = formatSliderValue(key, minVal, 'min');\n        if (maxValueDisplay) maxValueDisplay.textContent = formatSliderValue(key, maxVal, 'max');\n        filters[key].min = minVal;\n        filters[key].max = maxVal;\n      }\n\n      let activeHandle = null;\n      let isDragging = false;\n      function startDrag(e, handle) {\n        e.preventDefault();\n        activeHandle = handle;\n        isDragging = true;\n        document.addEventListener('mousemove', drag);\n        document.addEventListener('mouseup', stopDrag);\n        document.addEventListener('touchmove', drag);\n        document.addEventListener('touchend', stopDrag);\n      }\n      function drag(e) {\n        if (!activeHandle) return;\n        const clientX = e.touches ? e.touches[0].clientX : e.clientX;\n        const sliderRect = slider.getBoundingClientRect();\n        let position = (clientX - sliderRect.left) \/ sliderRect.width;\n        position = Math.max(0, Math.min(1, position));\n        if (activeHandle === leftHandle) {\n          minPos = Math.min(position, maxPos - 0.01); \/\/ Prevent overlap\n          filters[key].min = Math.round(minValue + minPos * valueRange);\n        } else if (activeHandle === rightHandle) {\n          maxPos = Math.max(position, minPos + 0.01);\n          filters[key].max = Math.round(minValue + maxPos * valueRange);\n        }\n        \/\/ Recalculate positions from updated values to ensure accurate handle placement\n        minPos = (filters[key].min - minValue) \/ valueRange;\n        maxPos = (filters[key].max - minValue) \/ valueRange;\n        updateHandles();\n        renderActiveFilters();\n        renderCards(true);\n      }\n      function stopDrag() {\n        if (isDragging) {\n          renderActiveFilters();\n          renderCards(false);\n          isDragging = false;\n        }\n        \n        activeHandle = null;\n        document.removeEventListener('mousemove', drag);\n        document.removeEventListener('mouseup', stopDrag);\n        document.removeEventListener('touchmove', drag);\n        document.removeEventListener('touchend', stopDrag);\n      }\n      \n      \/\/ Add event listeners\n      leftHandle.addEventListener('mousedown', e => startDrag(e, leftHandle));\n      leftHandle.addEventListener('touchstart', e => startDrag(e, leftHandle));\n      rightHandle.addEventListener('mousedown', e => startDrag(e, rightHandle));\n      rightHandle.addEventListener('touchstart', e => startDrag(e, rightHandle));\n    }\n    \n    \/\/ Initialize noUiSlider for all filters\n    function initNoUiSlider(sliderId, key, unit, step) {\n      const slider = document.getElementById(sliderId);\n      if (!slider) return;\n      \/\/ Remove previous slider instance if any\n      if (slider.noUiSlider) slider.noUiSlider.destroy();\n      noUiSlider.create(slider, {\n        start: [filters[key].min, filters[key].max],\n        connect: true,\n        range: {\n          min: filters[key].min,\n          max: filters[key].max\n        },\n        step: step,\n        tooltips: false,\n        format: {\n          to: value => Math.round(value),\n          from: value => Number(value)\n        }\n      });\n      slider.noUiSlider.on('update', function(values, handle) {\n        document.getElementById(key + 'MinValue').textContent = values[0] + ' ' + unit;\n        document.getElementById(key + 'MaxValue').textContent = values[1] + ' ' + unit;\n        filters[key].min = Number(values[0]);\n        filters[key].max = Number(values[1]);\n        renderActiveFilters();\n        renderCards(true);\n      });\n    }\n    \/\/ Call for each slider\n    initNoUiSlider('sizeSlider', 'size', 'kvm', 1);\n    initNoUiSlider('priceSlider', 'price', 'kr', 1000);\n    initNoUiSlider('feeSlider', 'fee', 'kr', 100);\n    initNoUiSlider('floorSlider', 'floor', '', 1);\n\n    \n    \/\/ Function to show a temporary notification\n    function showNotification(message, duration = 3000) {\n      \/\/ Create notification element if it doesn't exist\n      let notification = document.getElementById('notification');\n      if (!notification) {\n        notification = document.createElement('div');\n        notification.id = 'notification';\n        notification.style.position = 'fixed';\n        notification.style.bottom = '20px';\n        notification.style.right = '20px';\n        notification.style.backgroundColor = '#4CAF50';\n        notification.style.color = 'white';\n        notification.style.padding = '10px 20px';\n        notification.style.borderRadius = '5px';\n        notification.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';\n        notification.style.zIndex = '1000';\n        notification.style.transition = 'opacity 0.3s';\n        document.body.appendChild(notification);\n      }\n      \n      \/\/ Set message and show notification\n      notification.textContent = message;\n      notification.style.opacity = '1';\n      \n      \/\/ Hide after duration\n      setTimeout(() => {\n        notification.style.opacity = '0';\n      }, duration);\n    }\n    \n    \/\/ Function to focus the map on filtered properties\n    function focusMapOnFilteredProperties() {\n      \/\/ Get the filtered units based on current filters\n      const filteredUnits = filterUnits();\n      \n      \/\/ Show a message if no properties match the filters\n      if (filteredUnits.length === 0) {\n        alert('Inga bost\u00e4der matchar de valda filtren.');\n        return;\n      }\n      \n      \/\/ Update button text to show loading state\n      const mapButton = document.getElementById('showOnMapBtn');\n      const originalText = mapButton.textContent;\n      mapButton.textContent = 'Uppdaterar karta...';\n      mapButton.disabled = true;\n      \n      \/\/ Scroll to the map section\n      document.getElementById('map').scrollIntoView({ behavior: 'smooth' });\n      \n      \/\/ Log all filtered units to debug\n      console.log('Filtered units before map validation:', filteredUnits);\n      \n      \/\/ Debug log each unit's map_url\n      filteredUnits.forEach(unit => {\n        console.log(`Unit ${unit.id || unit.objekt_nr || unit.title} map_url: ${unit.map_url || 'none'}`);\n      });\n      \n      \/\/ Only use units that have map_url or valid coordinates\n      const validUnits = filteredUnits.filter(unit => {\n        \/\/ Check if unit has map_url\n        if (unit.map_url && unit.map_url.trim() !== '') {\n          console.log(`Unit ${unit.id} has valid map_url: ${unit.map_url}`);\n          return true;\n        }\n        \/\/ Check if unit has valid direct coordinates\n        if (unit.latitude && unit.longitude && \n            !isNaN(parseFloat(unit.latitude)) && !isNaN(parseFloat(unit.longitude))) {\n          console.log(`Unit ${unit.id} has valid direct coordinates: ${unit.latitude}, ${unit.longitude}`);\n          return true;\n        }\n        console.log(`Unit ${unit.id} has no valid location data`);\n        return false;\n      });\n      \n      \/\/ Show a message if no properties have valid locations\n      if (validUnits.length === 0) {\n        alert('Inga bost\u00e4der med giltiga platskoordinater hittades.');\n        mapButton.textContent = originalText;\n        mapButton.disabled = false;\n        return;\n      }\n      \n      \/\/ Render the map with only units that have valid locations\n      renderMap(validUnits);\n      \n      \/\/ Show a message with the number of properties shown on the map\n      console.log(`Visar ${validUnits.length} bost\u00e4der p\u00e5 kartan`);\n      showNotification(`Visar ${validUnits.length} bost\u00e4der p\u00e5 kartan`);\n      \n      \/\/ Reset button after a short delay\n      setTimeout(() => {\n        mapButton.textContent = originalText;\n        mapButton.disabled = false;\n      }, 1000);\n    }\n    \n    \/\/ Add event listener for the 'Visa p\u00e5 kartan' button\n    document.getElementById('showOnMapBtn').addEventListener('click', focusMapOnFilteredProperties);\n    \n    \/\/ Global variable to store the map instance\n    let mapInstance = null;\n    \n    \/\/ Function to render map with property data\n    function renderMap(units) {\n      \/\/ Show loading state for map\n      const mapDiv = document.getElementById('map');\n      if (!mapDiv) return;\n      \n      mapDiv.innerHTML = '<div style=\"text-align:center;padding:2em;\">Laddar karta...<\/div>';\n      \n      \/\/ Make sure the map div is visible and has dimensions before initializing Leaflet\n      mapDiv.style.display = 'block';\n      mapDiv.style.visibility = 'visible';\n      \n      \/\/ If we already have a map instance, remove it to prevent memory leaks\n      if (mapInstance) {\n        mapInstance.remove();\n        mapInstance = null;\n      }\n      \n      \/\/ Helper function to extract coordinates from Google\/OpenStreetMap URLs\n      function extractCoordsFromUrl(url) {\n        if (!url) return null;\n        \n        console.log('Extracting coordinates from URL:', url);\n        \n        try {\n          \/\/ Check for place URLs with explicit coordinates in the URL path\n          \/\/ Format: \/place\/Name\/@lat,lng,zoom\n          let match = url.match(\/\\\/place\\\/.*?@(-?\\d+\\.\\d+),(-?\\d+\\.\\d+)\/);\n          if (match) {\n            console.log(`Found place format coordinates: ${match[1]}, ${match[2]}`);\n            return { lat: parseFloat(match[1]), lng: parseFloat(match[2]) };\n          }\n          \n          \/\/ Look for coordinates in Google Maps URLs with format !8m2!3d[LAT]!4d[LNG]\n          \/\/ This format is commonly used in Google Maps share URLs\n          match = url.match(\/!3d(-?\\d+\\.\\d+)!4d(-?\\d+\\.\\d+)\/);\n          if (match) {\n            console.log(`Found Google Maps format coordinates: ${match[1]}, ${match[2]}`);\n            return { lat: parseFloat(match[1]), lng: parseFloat(match[2]) };\n          }\n          \n          \/\/ Try to match coordinates in the format @lat,lng,zoom\n          match = url.match(\/\\\/@(-?\\d+\\.\\d+),(-?\\d+\\.\\d+)\/);\n          if (match) {\n            console.log(`Found @ format coordinates: ${match[1]}, ${match[2]}`);\n            return { lat: parseFloat(match[1]), lng: parseFloat(match[2]) };\n          }\n          \n          \/\/ Try to match coordinates in the format ?q=lat,lng\n          match = url.match(\/\\?q=(-?\\d+\\.\\d+),(-?\\d+\\.\\d+)\/);\n          if (match) {\n            console.log(`Found ?q= format coordinates: ${match[1]}, ${match[2]}`);\n            return { lat: parseFloat(match[1]), lng: parseFloat(match[2]) };\n          }\n          \n          \/\/ Try to match coordinates in the format lat=X&lon=Y\n          match = url.match(\/lat=(-?\\d+\\.\\d+).*?lon=(-?\\d+\\.\\d+)\/);\n          if (match) {\n            console.log(`Found lat\/lon format coordinates: ${match[1]}, ${match[2]}`);\n            return { lat: parseFloat(match[1]), lng: parseFloat(match[2]) };\n          }\n          \n          \/\/ Try to match any pair of coordinates in the URL\n          match = url.match(\/(-?\\d+\\.\\d+),\\s*(-?\\d+\\.\\d+)\/);\n          if (match) {\n            console.log(`Found generic coordinates: ${match[1]}, ${match[2]}`);\n            return { lat: parseFloat(match[1]), lng: parseFloat(match[2]) };\n          }\n          \n          console.log('No coordinate pattern matched in URL');\n          return null;\n        } catch (error) {\n          console.error('Error extracting coordinates from URL:', error);\n          return null;\n        }\n      }\n      \n      \/\/ Helper for geocoding addresses with retry and caching\n      const geocodeCache = {}; \/\/ Cache geocoding results\n      \n      function geocodeAddress(address) {\n        \/\/ Return from cache if available\n        if (geocodeCache[address]) {\n          console.log(`Using cached coordinates for address: ${address}`);\n          return Promise.resolve(geocodeCache[address]);\n        }\n        \n        \/\/ Use our secure API proxy instead of directly accessing the external API\n        return fetch(`api\/properties.php?action=geocode&address=${encodeURIComponent(address)}`)\n          .then(response => response.json())\n          .then(data => {\n            if (data && data.lat && data.lon) {\n              const result = {\n                lat: parseFloat(data.lat),\n                lon: parseFloat(data.lon)\n              };\n              \/\/ Cache the result\n              geocodeCache[address] = result;\n              return result;\n            }\n            return null;\n          })\n          .catch(error => {\n            console.error(`Geocoding error for address ${address}:`, error);\n            return null;\n          });\n      }\n      \n      \/\/ Process units to get valid coordinates\n      const validUnits = [];\n      const geocodePromises = [];\n      \n      console.log('Processing units for map:', units);\n      \n      units.forEach(unit => {\n        \/\/ Try to parse latitude and longitude\n        let lat = unit.latitude || null;\n        let lng = unit.longitude || null;\n        let coordsSource = 'direct';\n        \n        \/\/ Log each unit's coordinates and map_url for debugging\n        console.log(`Processing unit ${unit.id || unit.objekt_nr || unit.title}: lat=${lat}, lng=${lng}, map_url=${unit.map_url || 'none'}`);\n        \n        \/\/ If map_url exists, prioritize extracting coordinates from it\n        if (unit.map_url) {\n          console.log(`Extracting coordinates from map_url for ${unit.objekt_nr || unit.id || 'unknown'}`);\n          const coords = extractCoordsFromUrl(unit.map_url);\n          if (coords) {\n            console.log(`Successfully extracted coordinates from map_url: lat=${coords.lat}, lng=${coords.lng}`);\n            lat = coords.lat;\n            lng = coords.lng;\n            coordsSource = 'map_url';\n          } else {\n            console.log(`Failed to extract coordinates from map_url for ${unit.objekt_nr || unit.id || 'unknown'}`);\n          }\n        } else {\n          console.log(`No map_url found for unit ${unit.objekt_nr || unit.id || 'unknown'}`);\n        }\n        \n        \/\/ If we still don't have valid coordinates but have direct lat\/lng, use those\n        if ((!lat || !lng || isNaN(parseFloat(lat)) || isNaN(parseFloat(lng))) && \n            (unit.latitude && unit.longitude)) {\n          lat = parseFloat(unit.latitude);\n          lng = parseFloat(unit.longitude);\n          coordsSource = 'direct';\n          console.log(`Using direct coordinates: lat=${lat}, lng=${lng}`);\n        }\n        \n        \/\/ If we have valid coordinates, add to valid units\n        if (lat && lng && !isNaN(parseFloat(lat)) && !isNaN(parseFloat(lng))) {\n          console.log(`Adding unit ${unit.objekt_nr || unit.id || 'unknown'} with coordinates from ${coordsSource}`);\n          validUnits.push({...unit, latitude: parseFloat(lat), longitude: parseFloat(lng)});\n        }\n        \/\/ If we have an address but no coordinates, try geocoding\n        else if (unit.address) {\n          console.log(`Geocoding address for unit ${unit.objekt_nr || unit.id || 'unknown'}: ${unit.address}`);\n          geocodePromises.push(\n            geocodeAddress(unit.address).then(coords => {\n              if (coords) {\n                console.log(`Geocoded coordinates for ${unit.objekt_nr || unit.id || 'unknown'}: lat=${coords.lat}, lng=${coords.lon}`);\n                validUnits.push({...unit, latitude: coords.lat, longitude: coords.lon});\n              } else {\n                console.log(`Failed to geocode address for ${unit.objekt_nr || unit.id || 'unknown'}`);\n              }\n            })\n          );\n        } else {\n          console.log(`No valid coordinates or address for unit ${unit.objekt_nr || unit.id || 'unknown'}`);\n        }\n      });\n      \n      \/\/ Wait for all geocoding to finish\n      Promise.all(geocodePromises).then(() => {\n        \/\/ If no valid units with coordinates, show a message\n        if (validUnits.length === 0) {\n          console.log('No valid coordinates found for any units');\n          mapDiv.innerHTML = '<div style=\"text-align:center;padding:2em;\">Inga bost\u00e4der med giltiga platskoordinater hittades!<\/div>';\n          return;\n        }\n        \n        if (validUnits.length > 0) {\n          \/\/ Clear the loading message\n          mapDiv.innerHTML = '';\n          \n          \/\/ Add a small delay to ensure the DOM is ready\n          setTimeout(() => {\n            try {\n              \/\/ Make sure any existing map is properly removed first\n              if (mapInstance) {\n                console.log('Removing existing map instance');\n                try {\n                  mapInstance.remove();\n                } catch (e) {\n                  console.error('Error removing existing map:', e);\n                }\n                mapInstance = null;\n              }\n              \n              \/\/ Initialize the map with default view\n              console.log('Creating new map instance');\n              mapInstance = L.map('map', {\n                \/\/ Add these options to help with initialization\n                fadeAnimation: false,\n                zoomAnimation: false,\n                preferCanvas: true, \/\/ Use canvas for better performance\n                attributionControl: false \/\/ Remove attribution for cleaner look\n              });\n              \n              \/\/ If we have multiple units, fit the map to show all markers\n              if (validUnits.length > 1) {\n                console.log(`Fitting map to show all ${validUnits.length} properties`);\n                \/\/ Create bounds object to fit all markers\n                const bounds = L.latLngBounds(validUnits.map(unit => [unit.latitude, unit.longitude]));\n                \/\/ Fit the map to these bounds with some padding\n                mapInstance.fitBounds(bounds, {\n                  padding: [50, 50], \/\/ Add padding around the bounds\n                  maxZoom: 15 \/\/ Limit maximum zoom level\n                });\n              } else {\n                \/\/ If only one unit, center on it\n                console.log('Only one property, centering map on it');\n                mapInstance.setView([validUnits[0].latitude, validUnits[0].longitude], 13);\n              }\n          \n              \/\/ Add the tile layer (OpenStreetMap)\n              \/\/ Use a faster CDN for tiles\n              L.tileLayer('https:\/\/tile.openstreetmap.org\/{z}\/{x}\/{y}.png', {\n                maxZoom: 19,\n                attribution: '\u00a9 OpenStreetMap contributors',\n                crossOrigin: true\n              }).addTo(mapInstance);\n          \n              \/\/ Create a marker cluster group for better performance with many markers\n              const markers = L.markerClusterGroup ? L.markerClusterGroup() : L.layerGroup();\n              \n              \/\/ Add markers for each unit\n              validUnits.forEach(unit => {\n                const marker = L.marker([unit.latitude, unit.longitude]);\n                \n                \/\/ Create popup content\n                let popupContent = `<b>${unit.title || unit.objekt_nr || ''}<\/b><br>`;\n                if (unit.address) popupContent += `Adress: ${unit.address}<br>`;\n                if (unit.status) popupContent += `Status: ${unit.status}<br>`;\n                if (unit.rooms) popupContent += `Rum: ${unit.rooms}<br>`;\n                if (unit.size) popupContent += `Storlek: ${unit.size} kvm<br>`;\n                if (unit.fee) popupContent += `Avgift: ${unit.fee} kr<br>`;\n                if (unit.price) {\n                  \/\/ Handle the 'kr' suffix properly, similar to the card display fix\n                  let priceText = unit.price.toString();\n                  \/\/ Remove any existing 'kr' suffix before adding it again\n                  priceText = priceText.replace(\/\\s*kr\\s*$\/i, '').trim();\n                  popupContent += `Pris: ${priceText} kr<br>`;\n                }\n                if (unit.type) popupContent += `Bostadstyp: ${unit.type}<br>`;\n                \n                marker.bindPopup(popupContent);\n                markers.addLayer(marker);\n              });\n              \n              \/\/ Add all markers at once for better performance\n              mapInstance.addLayer(markers);\n              \n              \/\/ Force a map redraw after initialization\n              setTimeout(() => {\n                mapInstance.invalidateSize();\n              }, 200);\n            } catch (error) {\n              console.error('Error initializing map:', error);\n              mapDiv.innerHTML = '<div style=\"text-align:center;padding:2em;\">Fel vid initialisering av kartan. F\u00f6rs\u00f6k igen senare.<\/div>';\n            }\n          }, 100); \/\/ Small delay before map initialization\n        } else {\n          mapDiv.innerHTML = '<div style=\"text-align:center;padding:2em;\">Inga l\u00e4genheter med giltiga koordinater hittades!<\/div>';\n        }\n      });\n    }\n    \n    \/\/ Fetch data from NocoDB to supplement the existing data\n    function fetchNocoDBData() {\n      fetch('https:\/\/husetexklusiv.se\/digitalvisning\/ledigafastigheter\/api\/properties.php?action=getNocoDBData', {\n        method: 'GET',\n        headers: { 'Content-Type': 'application\/json' }\n      })\n      .then(response => response.json())\n      .then(data => {\n        \/\/ Debug log to see the structure of the data\n        debugLogData(data, 'NocoDB raw data');\n        \n        if (data.list && data.list.length > 0) {\n          \/\/ Debug log a sample item to see its structure\n          debugLogData(data.list[0], 'Sample NocoDB item');\n          \n          \/\/ Map NocoDB data to our format and merge with existing units\n          const nocoUnits = data.list.map(u => ({\n            id: u.objekt_nr || u.Id || '',\n            status: u.Availability || '',\n            rooms: u.rum || '',\n            size: u.storlek || '',\n            fee: u.avgift || '',\n            price: u.pris || '',\n            type: u.objekttyp || '',\n            map_url: u.map_url || '',\n            mapUrl: u.map_url || '',\n            viewUrl: u.visa_objekt || '',\n            floor: u.plan || '',\n            title: '',\n            description: '',\n            image: '',\n            latitude: u.latitude || '',\n            longitude: u.longitude || '',\n            address: u.address || ''\n          }));\n          \n          \/\/ Merge with existing units if any\n          \/\/ Always use only the NocoDB data\n          allUnits = nocoUnits;\n          \n          \/\/ Debug log the mapped units\n          debugLogData(nocoUnits, 'Mapped NocoDB units');\n          \n          \/\/ Only use properties with real coordinates\n          const hasCoordinates = nocoUnits.some(unit => \n            (unit.latitude && unit.longitude) || unit.map_url\n          );\n          \n          if (!hasCoordinates) {\n            console.warn('No real coordinates found in any property.');\n          } else {\n            console.log('Using real coordinates from database');\n          }\n          renderFilters(allUnits);\n          renderCards();\n          renderMap(allUnits);\n        }\n      })\n      .catch(error => {\n        console.error('Error fetching data from NocoDB:', error);\n      });\n    }\n    \n    \/\/ Setup type filter\n    const typeFilter = document.getElementById('typeFilter');\n    if (typeFilter) {\n      typeFilter.addEventListener('change', function() {\n        filters.type = this.value;\n        renderActiveFilters();\n        renderCards();\n      });\n    } else {\n      console.warn('Type filter not found');\n    }\n    \/\/ Setup status filter\n    const statusFilter = document.getElementById('statusFilter');\n    if (statusFilter) {\n      statusFilter.addEventListener('change', function() {\n        filters.status = this.value;\n        renderActiveFilters();\n        renderCards();\n      });\n    } else {\n      console.warn('Status filter not found');\n    }\n    renderActiveFilters();\n    \n    \/\/ JavaScript style enforcer for CSS isolation\n    document.addEventListener('DOMContentLoaded', function() {\n      const component = document.getElementById('property-listing-component');\n      if (!component) return;\n      \n      const isolateStyles = function() {\n        const allElements = component.querySelectorAll('*');\n        allElements.forEach(function(el) {\n          if (el.tagName === 'BUTTON') {\n            el.style.setProperty('display', 'inline-block', 'important');\n            el.style.setProperty('cursor', 'pointer', 'important');\n          }\n          el.style.setProperty('font-family', 'Arial, sans-serif', 'important');\n        });\n      };\n      \n      \/\/ Apply styles on load\n      isolateStyles();\n      \n      \/\/ Watch for DOM changes and reapply styles\n      const observer = new MutationObserver(isolateStyles);\n      observer.observe(component, { childList: true, subtree: true });\n    });\n  <\/script>\n  <\/div> <!-- Close property-listing-component -->\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-dfd05d6 elementor-reverse-tablet elementor-reverse-mobile elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"dfd05d6\" data-element_type=\"section\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b916744\" data-id=\"b916744\" data-element_type=\"column\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-590e047 elementor-widget elementor-widget-spacer\" data-id=\"590e047\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-84fa2ac elementor-widget elementor-widget-heading\" data-id=\"84fa2ac\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Implementierte Funktionen<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-961bea9 elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"961bea9\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-48ce3b0 elementor-widget elementor-widget-text-editor\" data-id=\"48ce3b0\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<ul>\n<li>Virtuelle Vertriebsassistentin<\/li><li>Die Videowiedergabe ist jetzt f\u00fcr Smartphones, Tablets, VR-Headsets und Computer sowohl im 2D- als auch im 360\u00b0-Format verf\u00fcgbar.&nbsp;<br>- Personalisierte(s) Video(s). Mit personalisierten Playbacks kann der Kunde personalisierte Begr\u00fc\u00dfungen und Informationen von z.B. dem Makler erhalten.&nbsp;<br>- Objektanzeige im 2D- und 360\u00b0-Videoformat.<\/li>\n<li>Die folgenden Formate werden unterst\u00fctzt <br>.Wort<br>.PDF <br>.PP(Microsoft PowerPoint)<br>.XL(Microsoft Excel)<\/li>\n<li>.<\/li>\n<li>3D-Objekte<\/li>\n<li>YouTube<\/li>\n<li>Facebook<\/li>\n<li>Linkedin<\/li>\n<li>Twitter<\/li>\n<\/ul>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-187a3ac elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"187a3ac\" data-element_type=\"section\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f74d0da\" data-id=\"f74d0da\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-5992af6 elementor-widget elementor-widget-spacer\" data-id=\"5992af6\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0044f35 elementor-widget elementor-widget-heading\" data-id=\"0044f35\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<span class=\"elementor-heading-title elementor-size-default\">Lesen Sie mehr \u00fcber unseren Konfigurator f\u00fcr Neubauten<\/span>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d9e3ba3 elementor-align-center elementor-widget elementor-widget-button\" data-id=\"d9e3ba3\" data-element_type=\"widget\" data-widget_type=\"button.default\">\n\t\t\t\t\t\t\t\t\t\t<a class=\"elementor-button elementor-button-link elementor-size-sm\" href=\"https:\/\/huset.se\/konfigurator\/\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Mehr lesen<\/span>\n\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c869b12 elementor-widget elementor-widget-spacer\" data-id=\"c869b12\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Interaktive Tools Verf\u00fcgbare Immobilien Ein nahtloses Erlebnis - direkt auf Ihrer Website F\u00fcr Immobilieneigent\u00fcmer und -makler mit mehreren Immobilien bieten wir jetzt eine ma\u00dfgeschneiderte L\u00f6sung, um die vorgestellten Immobilien mit einem Ma\u00df an Eleganz und Zug\u00e4nglichkeit zu pr\u00e4sentieren, das bisher fehlte. Mit unserer neuen Funktion k\u00f6nnen Sie ganz einfach ein komplettes Modul f\u00fcr die Immobiliensuche in Ihre eigene Website integrieren [...]<\/p>","protected":false},"author":25,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template\/template-homepage.php","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"class_list":["post-28037","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/huset.se\/de\/wp-json\/wp\/v2\/pages\/28037","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/huset.se\/de\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/huset.se\/de\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/huset.se\/de\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/huset.se\/de\/wp-json\/wp\/v2\/comments?post=28037"}],"version-history":[{"count":232,"href":"https:\/\/huset.se\/de\/wp-json\/wp\/v2\/pages\/28037\/revisions"}],"predecessor-version":[{"id":28275,"href":"https:\/\/huset.se\/de\/wp-json\/wp\/v2\/pages\/28037\/revisions\/28275"}],"wp:attachment":[{"href":"https:\/\/huset.se\/de\/wp-json\/wp\/v2\/media?parent=28037"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}