{"slug":"map-3d","headLinks":["https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.css","https://fonts.googleapis.com/css2?family=Playfair+Display:wght@600;700&family=Inter:wght@400;500;600;700&display=swap"],"styles":"\n  :root{\n    --ink:#1b2430; --ink-soft:#4a5568; --paper:#f6f4ef; --panel:#ffffff;\n    --gold:#b8925a; --gold-deep:#8f6f42; --line:#e4ddd0;\n    --available:#3f8f6b; --sold:#b5484c; --construction:#c98a2c; --upcoming:#3b6ea5;\n    --shadow:0 10px 30px rgba(27,36,48,0.14);\n  }\n  *{box-sizing:border-box;}\n  body{ -webkit-user-select:none; user-select:none; }\n  input, textarea{ -webkit-user-select:text; user-select:text; }\n  img{ -webkit-user-drag:none; user-drag:none; }\n  body,html{margin:0;padding:0;height:100%;width:100%;font-family:'Inter',sans-serif;background:var(--paper);color:var(--ink);}\n  #map{position:absolute;inset:0;z-index:0;}\n\n  #topbar{\n    position:fixed;top:0;left:0;right:0;z-index:1200;\n    display:flex;align-items:center;justify-content:space-between;\n    padding:12px 26px;\n    background:transparent;\n  }\n  #topbar .brand{\n    display:flex;align-items:center;gap:10px;color:var(--ink);\n    background:rgba(255,255,255,0.8);backdrop-filter:blur(6px);\n    padding:7px 16px;border-radius:12px;\n    box-shadow:0 2px 10px rgba(27,36,48,0.12);\n  }\n  #topbar .brand img.logo{height:38px;width:auto;max-width:130px;object-fit:contain;display:block;}\n  #topbar .brand .brand-text{display:flex;flex-direction:column;}\n  #topbar .brand h1{font-family:'Playfair Display',serif;font-size:19px;margin:0;letter-spacing:.3px;color:var(--ink);}\n  #topbar .brand span{font-size:10.5px;color:var(--ink-soft);letter-spacing:1px;text-transform:uppercase;margin-top:1px;}\n  #toolbar{display:flex;gap:8px;align-items:center;}\n  #search-input{\n    width:200px;padding:10px 16px;border-radius:999px;\n    border:1px solid #e6dfd0;background:#ffffff;\n    font-size:13px;color:var(--ink);font-family:'Inter',sans-serif;\n    box-shadow:0 1px 4px rgba(27,36,48,0.1);\n  }\n  #search-input::placeholder{color:#8a8577;}\n  #search-input:focus{outline:2px solid var(--gold);}\n  .btn{\n    border:1px solid #e6dfd0;background:#ffffff;color:#1b2430;\n    padding:10px 16px;border-radius:999px;font-size:13px;font-weight:600;cursor:pointer;\n    display:flex;align-items:center;gap:6px;transition:.2s ease;white-space:nowrap;\n    box-shadow:0 1px 4px rgba(27,36,48,0.1);\n    text-decoration:none;\n  }\n  .btn:hover{background:var(--gold);color:#241a0d;border-color:var(--gold);transform:translateY(-1px);box-shadow:0 5px 12px rgba(184,146,90,0.4);}\n\n  #tilt-hint{\n    position:absolute;bottom:20px;right:20px;z-index:1200;background:rgba(27,36,48,0.75);color:#fff;\n    padding:8px 13px;border-radius:20px;font-size:11.5px;backdrop-filter:blur(4px);\n    display:flex;align-items:center;gap:6px;\n  }\n\n  #legend{\n    position:absolute;bottom:20px;left:20px;z-index:1200;background:var(--panel);\n    border-radius:10px;box-shadow:var(--shadow);padding:12px 16px;font-size:12px;max-width:200px;\n  }\n  #legend h4{margin:0 0 8px;font-family:'Playfair Display',serif;font-size:13px;color:var(--ink);}\n  #legend .row{display:flex;align-items:center;gap:8px;margin-bottom:5px;color:var(--ink-soft);}\n  #legend .swatch{width:11px;height:11px;border-radius:50%;flex:none;}\n\n  .pin-wrap{width:32px;height:44px;position:relative;cursor:pointer;transform-origin:50% 100%;}\n  .pin-circle{\n    position:absolute;top:0;left:2px;width:28px;height:28px;border-radius:50%;\n    box-shadow:0 3px 7px rgba(0,0,0,0.35);\n    display:flex;align-items:center;justify-content:center;overflow:hidden;\n    border:2px solid rgba(255,255,255,0.9);\n  }\n  .pin-circle img{width:100%;height:100%;object-fit:cover;}\n  .pin-circle .glyph{color:#fff;font-size:13px;}\n  .pin-tail{\n    position:absolute;top:22px;left:50%;transform:translateX(-50%);\n    width:0;height:0;border-left:7px solid transparent;border-right:7px solid transparent;\n    border-top:15px solid currentColor;filter:drop-shadow(0 2px 1px rgba(0,0,0,0.25));\n  }\n  .pin-ground{\n    position:absolute;bottom:1px;left:50%;transform:translateX(-50%);\n    width:10px;height:4px;border-radius:50%;background:rgba(0,0,0,0.28);filter:blur(1px);\n  }\n  .pin-radar{\n    position:absolute;top:0;left:2px;width:28px;height:28px;border-radius:50%;\n    border:3px solid currentColor;animation:radar-pulse 1.6s ease-out infinite;pointer-events:none;\n  }\n  @keyframes radar-pulse{\n    0%{transform:scale(0.6);opacity:0.9;}\n    100%{transform:scale(2.6);opacity:0;}\n  }\n  .infra-pin{\n    border-radius:10px;border:2.5px solid rgba(255,255,255,0.95);\n    display:flex;align-items:center;justify-content:center;cursor:pointer;\n    box-shadow:0 6px 14px rgba(0,0,0,0.45), inset 0 2px 3px rgba(255,255,255,0.5), inset 0 -3px 5px rgba(0,0,0,0.25);\n    background-image:linear-gradient(145deg, rgba(255,255,255,0.35), rgba(0,0,0,0.15));\n    background-blend-mode:overlay;\n    transition:transform .15s ease, box-shadow .15s ease;\n  }\n  .infra-pin:hover{ transform:scale(1.15) translateY(-2px); }\n  .infra-pin img{width:70%;height:70%;object-fit:contain;filter:drop-shadow(0 1px 1px rgba(0,0,0,0.4));}\n\n  .teaser-popup .maplibregl-popup-content{border-radius:12px;padding:0;box-shadow:0 12px 30px rgba(27,36,48,0.3);overflow:hidden;}\n  .teaser-card{font-family:'Inter',sans-serif;width:220px;}\n  .teaser-card img{width:100%;height:120px;object-fit:cover;display:block;}\n  .teaser-card .tc-body{padding:11px 13px 13px;}\n  .teaser-card .tc-title{font-family:'Playfair Display',serif;font-size:14px;color:var(--ink);margin:0 0 4px;}\n  .teaser-card .tc-meta{font-size:12px;color:var(--ink-soft);margin-bottom:8px;line-height:1.4;}\n  .teaser-card .tc-status{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:700;color:#fff;margin-bottom:8px;}\n  .teaser-card .tc-type{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:700;color:var(--ink-soft);background:#f0ebe0;margin-bottom:8px;margin-left:5px;}\n  .teaser-card .tc-actions{display:flex;gap:6px;}\n  .teaser-card button{\n    flex:1;background:var(--ink);color:#fff;border:none;border-radius:7px;\n    padding:9px 0;font-size:12.5px;font-weight:700;cursor:pointer;font-family:'Inter',sans-serif;\n  }\n  .teaser-card button:hover{background:#000;}\n  .teaser-card button.tc-share{\n    flex:none;background:#fff;color:var(--ink);border:1px solid #e6dfd0;padding:9px 12px;\n    display:flex;align-items:center;gap:5px;\n  }\n  .teaser-card button.tc-share:hover{background:var(--gold);color:#241a0d;border-color:var(--gold);}\n\n  #overlay-bg{\n    position:absolute;inset:0;z-index:1700;background:rgba(27,36,48,0.5);\n    display:none;align-items:center;justify-content:center;\n  }\n  #overlay-bg.open{display:flex;}\n  #lead-box{\n    width:360px;max-width:92vw;background:var(--panel);border-radius:14px;box-shadow:var(--shadow);\n    padding:24px 24px 20px;\n  }\n  #lead-box h3{margin:0 0 4px;font-family:'Playfair Display',serif;font-size:19px;color:var(--ink);}\n  #lead-box p{margin:0 0 16px;font-size:12.5px;color:var(--ink-soft);}\n  .field{margin-bottom:13px;}\n  .field label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--ink-soft);margin-bottom:5px;}\n  .field input, .field select{\n    width:100%;padding:10px 11px;border:1px solid var(--line);border-radius:7px;font-size:13.5px;\n    font-family:'Inter',sans-serif;color:var(--ink);background:#fdfcfa;\n  }\n  .field input:focus, .field select:focus{outline:2px solid var(--gold);border-color:var(--gold);}\n  #lead-error{font-size:11.5px;color:var(--sold);min-height:14px;margin-bottom:6px;}\n  #lead-consent-row{display:flex;align-items:flex-start;gap:9px;margin-bottom:14px;}\n  #lead-consent-row input[type=checkbox]{width:17px;height:17px;flex:none;margin-top:2px;cursor:pointer;}\n  #lead-consent-row label{font-size:10.5px;line-height:1.5;color:var(--ink-soft);font-weight:400;text-transform:none;letter-spacing:0;cursor:pointer;}\n  .lead-actions{display:flex;gap:10px;margin-top:6px;}\n  .lead-actions button{flex:1;padding:11px 0;border-radius:8px;font-size:13px;font-weight:700;cursor:pointer;border:1px solid var(--line);}\n  #lead-submit{background:var(--gold);color:#241a0d;border-color:var(--gold);}\n  #lead-submit:hover{background:var(--gold-deep);color:#fff;}\n  #lead-cancel{background:#fff;color:var(--ink-soft);}\n\n  #detail-panel{\n    position:absolute;top:0;right:0;height:100%;width:400px;max-width:92vw;\n    background:var(--panel);box-shadow:-8px 0 30px rgba(27,36,48,0.2);\n    z-index:1500;transform:translateX(100%);transition:transform .28s ease;\n    display:flex;flex-direction:column;\n  }\n  #detail-panel.open{transform:translateX(0);}\n  #detail-head{position:relative;}\n  #detail-head img{width:100%;height:200px;object-fit:cover;display:block;}\n  #detail-close{\n    position:absolute;top:14px;right:14px;background:rgba(27,36,48,0.6);color:#fff;border:none;\n    width:32px;height:32px;border-radius:50%;font-size:16px;cursor:pointer;\n  }\n  #detail-body{padding:22px 24px;overflow-y:auto;flex:1;}\n  #detail-body h2{font-family:'Playfair Display',serif;font-size:22px;margin:0 0 6px;}\n  #detail-body .status-badge{display:inline-block;padding:3px 10px;border-radius:12px;font-size:11px;font-weight:700;color:#fff;margin-bottom:14px;}\n  .detail-row{margin-bottom:16px;}\n  .detail-row label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--ink-soft);margin-bottom:4px;}\n  .detail-row .value{font-size:14.5px;color:var(--ink);line-height:1.5;}\n  .detail-row .value.price{font-family:'Playfair Display',serif;font-size:19px;color:var(--gold-deep);}\n  .detail-share{\n    width:100%;margin-top:6px;background:#fff;color:var(--ink);border:1px solid #e6dfd0;\n    border-radius:8px;padding:11px 0;font-size:13px;font-weight:700;cursor:pointer;\n    font-family:'Inter',sans-serif;display:flex;align-items:center;justify-content:center;gap:7px;\n  }\n  .detail-share:hover{background:var(--gold);color:#241a0d;border-color:var(--gold);}\n\n  #loading{\n    position:absolute;inset:0;z-index:2000;background:var(--paper);\n    display:flex;align-items:center;justify-content:center;flex-direction:column;gap:10px;\n    font-family:'Playfair Display',serif;color:var(--ink-soft);\n  }\n  #loading .spin{width:26px;height:26px;border:3px solid var(--line);border-top-color:var(--gold);border-radius:50%;animation:spin 0.9s linear infinite;}\n  @keyframes spin{to{transform:rotate(360deg);}}\n\n  @media (max-width:640px){\n    #topbar{ flex-wrap:wrap; gap:8px; padding:10px 12px; }\n    #topbar .brand{ padding:6px 12px; }\n    #topbar .brand img.logo{ height:30px; }\n    #topbar .brand h1{font-size:15px;}\n    #topbar .brand span{font-size:9px;}\n    #toolbar{ width:100%; }\n    #search-input{ flex:1; width:auto; min-width:0; }\n    .btn{ padding:10px 14px; font-size:12.5px; }\n    #legend{\n      left:12px; right:12px; bottom:12px; max-width:none;\n      max-height:130px; overflow-y:auto; font-size:11px; padding:10px 12px;\n    }\n    #legend .row{ margin-bottom:4px; }\n    #tilt-hint{\n      top:72px; bottom:auto; left:50%; right:auto; transform:translateX(-50%);\n      font-size:10.5px; padding:7px 12px; text-align:center; max-width:88vw;\n    }\n    #lead-box{ padding:18px 18px 16px; }\n    #detail-panel{width:100%;}\n    #detail-body{ padding:18px 16px; }\n    .teaser-card{ width:190px; }\n  }\n  @media (max-width:380px){\n    #topbar .brand span{ display:none; }\n    #search-input{ font-size:12px; }\n    #tilt-hint{ display:none; }\n  }\n","scripts":[{"type":"inline","code":"\n(function(){\n  var SUPABASE_URL = '';\n  var SUPABASE_ANON_KEY = 'local';\n  fetch(SUPABASE_URL + '/rest/v1/map_settings?id=eq.1&select=gtm_container_id,search_console_verification', {\n    headers: { 'apikey': SUPABASE_ANON_KEY, 'Authorization': 'Bearer ' + SUPABASE_ANON_KEY }\n  }).then(function(r){ return r.json(); }).then(function(rows){\n    var row = rows && rows[0];\n    if(!row) return;\n    if(row.search_console_verification){\n      var meta = document.createElement('meta');\n      meta.name = 'google-site-verification';\n      meta.content = row.search_console_verification;\n      document.head.appendChild(meta);\n    }\n    if(row.gtm_container_id){\n      window.dataLayer = window.dataLayer || [];\n      window.dataLayer.push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });\n      var j = document.createElement('script');\n      j.async = true;\n      j.src = 'https://www.googletagmanager.com/gtm.js?id=' + row.gtm_container_id;\n      document.head.appendChild(j);\n      document.addEventListener('DOMContentLoaded', function(){\n        var ifr = document.createElement('iframe');\n        ifr.src = 'https://www.googletagmanager.com/ns.html?id=' + row.gtm_container_id;\n        ifr.height = 0; ifr.width = 0; ifr.style.display = 'none'; ifr.style.visibility = 'hidden';\n        var ns = document.createElement('noscript');\n        ns.appendChild(ifr);\n        document.body.insertBefore(ns, document.body.firstChild);\n      });\n    }\n  }).catch(function(){});\n})();\n"},{"type":"inline","code":"\n(function(){\n  var ALLOWED_HOSTS = []; // e.g. ['associatte.com','www.associatte.com']\n  if(ALLOWED_HOSTS.length && ALLOWED_HOSTS.indexOf(location.hostname) === -1){\n    document.write('<div style=\"display:flex;align-items:center;justify-content:center;height:100vh;font-family:sans-serif;text-align:center;padding:20px;color:#4a5568;\">This map is licensed for use on its original website only.</div>');\n    window.stop ? window.stop() : (document.execCommand && document.execCommand('Stop'));\n  }\n})();\n"},{"type":"ext","src":"https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.js","async":false},{"type":"ext","src":"/db-shim.js","async":false},{"type":"inline","code":"\n(async function(){\n\n  const SUPABASE_URL = '';\n  const SUPABASE_ANON_KEY = 'local';\n  const sb = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);\n\n  const statusColor = {available:'#3f8f6b', sold:'#b5484c', construction:'#c98a2c', upcoming:'#3b6ea5'};\n  const statusLabel = {available:'Available', sold:'Sold', construction:'Under Construction', upcoming:'Upcoming'};\n\n  const infraTypes = {\n    bridge:          {emoji:'🌉', label:'Bridge',              color:'#3b6ea5'},\n    highway_bridge:  {emoji:'🛣️', label:'Highway Bridge',       color:'#8f6f42'},\n    flyover:         {emoji:'🎢', label:'Flyover',              color:'#7a5c9e'},\n    bullet_train:    {emoji:'🚄', label:'Bullet Train Station', color:'#b5484c'},\n    metro:           {emoji:'🚇', label:'Metro Station',        color:'#3f8f6b'},\n    railway_station: {emoji:'🚉', label:'Railway Station',      color:'#5b7c99'},\n    hotel:           {emoji:'🏨', label:'Hotel',                color:'#a0527a'},\n    hospital:        {emoji:'🏥', label:'Hospital',             color:'#c0392b'},\n    underpass:       {emoji:'🔽', label:'Underpass',            color:'#5c6670'},\n    proposed_road:   {emoji:'🚧', label:'Proposed Road',        color:'#c98a2c'},\n    school:          {emoji:'🏫', label:'School',                color:'#5c8a3f'}\n  };\n  const infraSizes = {small:{px:26, font:13}, medium:{px:36, font:18}, large:{px:48, font:24}};\n  function isBridgeLike(type){ return type === 'bridge' || type === 'highway_bridge' || type === 'flyover'; }\n\n  function pinShareUrl(pin){\n    const url = new URL(window.location.href);\n    url.search = '';\n    url.searchParams.set('pin', pin.id);\n    return url.toString();\n  }\n  async function sharePin(pin){\n    const url = pinShareUrl(pin);\n    const shareData = {\n      title: pin.title || 'Land parcel — Associatte',\n      text: 'Check out this land parcel on the Associatte Interactive Map: ' + (pin.title || ''),\n      url\n    };\n    if(navigator.share){\n      try{ await navigator.share(shareData); return; }\n      catch(_e){ /* user cancelled or share failed — fall through to copy */ }\n    }\n    try{\n      await navigator.clipboard.writeText(url);\n      alert('Link copied — you can now paste and share it.');\n    }catch(_e){\n      window.prompt('Copy this link to share:', url);\n    }\n  }\n  window.sharePin = sharePin;\n\n  function teaserLine(p){\n    if(p.status === 'construction'){\n      const bits = [p.configuration, p.sqft].filter(Boolean).join(' · ');\n      const poss = p.possession_timeline ? ('Possession: ' + p.possession_timeline) : '';\n      return [bits, poss].filter(Boolean).join('<br>') || 'Details on request';\n    }\n    if(p.status === 'upcoming'){\n      const bits = [p.configuration, p.sqft].filter(Boolean).join(' · ');\n      const launch = p.launch_date ? ('Launching: ' + p.launch_date) : '';\n      return [bits, launch].filter(Boolean).join('<br>') || 'Launching soon';\n    }\n    if(p.status === 'available'){\n      return p.whats_available || (p.price || 'Enquire for availability');\n    }\n    return 'This project has been sold out.';\n  }\n\n  /* ---------------------------------------------------------\n     LOAD DATA\n  --------------------------------------------------------- */\n  const [pinsRes, infraRes, roadsRes, settingsRes] = await Promise.all([\n    sb.from('pins').select('*'),\n    sb.from('infra_markers').select('*'),\n    sb.from('roads').select('*'),\n    sb.from('map_settings').select('*').eq('id', 1).single()\n  ]);\n  const pins = pinsRes.data || [];\n  const bridges = infraRes.data || [];\n  const roads = roadsRes.data || [];\n  const boundary = (settingsRes.data && settingsRes.data.boundary) || [];\n\n  /* ---------------------------------------------------------\n     MAP INIT — MapLibre GL + OpenFreeMap (free, no API key)\n  --------------------------------------------------------- */\n  // Figure out the real extent of the plan so the camera frames it correctly —\n  // a steep tilt over a guessed center was pushing far pins toward the horizon.\n  const allCoords = [];\n  pins.forEach(p=> allCoords.push([p.lng, p.lat]));\n  bridges.forEach(b=> allCoords.push([b.lng, b.lat]));\n  boundary.forEach(c=> allCoords.push([c[1], c[0]]));\n  let initialCenter = [73.9280, 18.5260];\n  if(allCoords.length){\n    const lngs = allCoords.map(c=>c[0]), lats = allCoords.map(c=>c[1]);\n    initialCenter = [(Math.min(...lngs)+Math.max(...lngs))/2, (Math.min(...lats)+Math.max(...lats))/2];\n  }\n\n  const map = new maplibregl.Map({\n    container: 'map',\n    style: 'https://tiles.openfreemap.org/styles/liberty',\n    center: initialCenter,\n    zoom: 14.5,\n    pitch: 0,\n    bearing: 0,\n    antialias: true\n  });\n  map.addControl(new maplibregl.NavigationControl({visualizePitch:true}), 'bottom-right');\n\n  map.on('load', ()=>{\n    document.getElementById('loading').style.display = 'none';\n\n    // Frame every pin + the boundary while completely flat first — fitBounds\n    // miscalculates the required zoom once pitch is already applied, which is\n    // what was pushing pins outside the visible plan area. Only after the\n    // correct flat fit do we tilt, then zoom out a touch more to compensate\n    // for the extra ground the perspective view reveals.\n    if(allCoords.length){\n      const bounds = allCoords.reduce((b,c)=> b.extend(c), new maplibregl.LngLatBounds(allCoords[0], allCoords[0]));\n      map.fitBounds(bounds, {padding:90, duration:0, maxZoom:16});\n      const flatZoom = map.getZoom();\n      map.jumpTo({ pitch:38, bearing:-17, zoom: Math.max(flatZoom - 0.6, 10) });\n    }\n\n    // Find the vector source OpenFreeMap ships (so this keeps working even if they rename it)\n    const styleSources = map.getStyle().sources;\n    const vectorSourceId = Object.keys(styleSources).find(id => styleSources[id].type === 'vector');\n\n    // 3D building extrusions — the core \"flying into a city\" effect\n    if(vectorSourceId){\n      const firstSymbolLayer = map.getStyle().layers.find(l => l.type === 'symbol');\n      map.addLayer({\n        id: 'mundhwa-3d-buildings',\n        source: vectorSourceId,\n        'source-layer': 'building',\n        type: 'fill-extrusion',\n        minzoom: 14,\n        paint: {\n          'fill-extrusion-color': '#d8cfc0',\n          'fill-extrusion-height': ['coalesce', ['get', 'render_height'], 8],\n          'fill-extrusion-base': ['coalesce', ['get', 'render_min_height'], 0],\n          'fill-extrusion-opacity': 0.85\n        }\n      }, firstSymbolLayer ? firstSymbolLayer.id : undefined);\n    }\n\n    // Boundary outline\n    if(boundary.length > 1){\n      const ring = boundary.map(c => [c[1], c[0]]);\n      ring.push(ring[0]);\n      map.addSource('boundary', { type:'geojson', data:{ type:'Feature', geometry:{ type:'Polygon', coordinates:[ring] } } });\n      map.addLayer({ id:'boundary-fill', type:'fill', source:'boundary', paint:{ 'fill-color':'#e74c3c', 'fill-opacity':0.04 } });\n      map.addLayer({ id:'boundary-line', type:'line', source:'boundary', paint:{ 'line-color':'#e74c3c', 'line-width':2, 'line-dasharray':[3,3] } });\n    }\n\n    // Roads / lines, with bridge casing where relevant\n    const roadFeatures = roads.filter(r => r.points && r.points.length > 1).map(r=>{\n      const meta = infraTypes[r.type] || infraTypes.proposed_road;\n      return {\n        type:'Feature',\n        properties:{ id:r.id, color: r.color || meta.color, weight: r.weight || 5, bridge: isBridgeLike(r.type) ? 1 : 0, dashed: r.type === 'proposed_road' ? 1 : 0, title: r.title || meta.label, notes: r.notes || '' },\n        geometry:{ type:'LineString', coordinates: r.points.map(p=>[p[1], p[0]]) }\n      };\n    });\n    map.addSource('roads', { type:'geojson', data:{ type:'FeatureCollection', features: roadFeatures } });\n    map.addLayer({\n      id:'roads-casing', type:'line', source:'roads',\n      filter:['==', ['get','bridge'], 1],\n      paint:{ 'line-color':'#ffffff', 'line-width':['+', ['get','weight'], 6], 'line-opacity':0.9 },\n      layout:{ 'line-join':'round', 'line-cap':'round' }\n    });\n    map.addLayer({\n      id:'roads-line', type:'line', source:'roads',\n      paint:{ 'line-color':['get','color'], 'line-width':['get','weight'], 'line-opacity':0.95,\n        'line-dasharray':['case', ['==', ['get','dashed'], 1], ['literal',[2,1.6]], ['literal',[1,0]]] },\n      layout:{ 'line-join':'round', 'line-cap':'round' }\n    });\n    map.on('click', 'roads-line', (e)=>{\n      const p = e.features[0].properties;\n      new maplibregl.Popup({offset:8}).setLngLat(e.lngLat).setHTML(`<b>${p.title}</b>${p.notes ? '<br>'+p.notes : ''}`).addTo(map);\n    });\n    map.on('mouseenter', 'roads-line', ()=> map.getCanvas().style.cursor = 'pointer');\n    map.on('mouseleave', 'roads-line', ()=> map.getCanvas().style.cursor = '');\n\n    // Infra markers\n    bridges.forEach(b=>{\n      const meta = infraTypes[b.type] || infraTypes.bridge;\n      const sz = infraSizes[b.size] || infraSizes.medium;\n      const color = b.color || meta.color;\n      const inner = b.icon_image ? `<img src=\"${b.icon_image}\" alt=\"\">` : meta.emoji;\n      const el = document.createElement('div');\n      el.className = 'infra-pin';\n      el.style.width = sz.px+'px'; el.style.height = sz.px+'px'; el.style.background = color; el.style.fontSize = sz.font+'px';\n      el.innerHTML = inner;\n      const popup = new maplibregl.Popup({offset:sz.px/2+4, closeButton:false, closeOnClick:false}).setHTML(`<b>${meta.emoji} ${b.title || meta.label}</b><br>${meta.label}`);\n      const marker = new maplibregl.Marker({element:el, anchor:'bottom'}).setLngLat([b.lng, b.lat]).setPopup(popup).addTo(map);\n      // Hover still works for desktop convenience; a tap/click (mobile's\n      // equivalent, since there's no hover on touch) toggles it too.\n      el.addEventListener('mouseenter', ()=>{ if(!popup.isOpen()) marker.togglePopup(); });\n      el.addEventListener('mouseleave', ()=>{ if(popup.isOpen()) marker.togglePopup(); });\n      el.addEventListener('click', (evt)=>{ evt.stopPropagation(); marker.togglePopup(); });\n    });\n\n    // Project pins\n    const pinScale = {small:0.78, medium:1, large:1.35};\n    pins.forEach(pin=>{\n      const color = statusColor[pin.status] || statusColor.available;\n      const head = pin.image ? `<img src=\"${pin.image}\" alt=\"\">` : `<span class=\"glyph\">●</span>`;\n      const radar = pin.highlighted ? '<div class=\"pin-radar\"></div>' : '';\n      const el = document.createElement('div');\n      el.className = 'pin-wrap';\n      el.style.color = color;\n      el.style.transform = 'scale(' + (pinScale[pin.size] || 1) + ')';\n      el.innerHTML = `${radar}<div class=\"pin-circle\" style=\"background:${color};\">${head}</div><div class=\"pin-tail\"></div><div class=\"pin-ground\"></div>`;\n\n      const imgTag = pin.image ? `<img src=\"${pin.image}\" alt=\"\">` : '';\n      const shareBtn = `<button class=\"tc-share\" data-share-pin=\"${pin.id}\" type=\"button\">🔗 Share</button>`;\n      const html = `<div class=\"teaser-card\">${imgTag}<div class=\"tc-body\">\n          <p class=\"tc-title\">${pin.title || 'Untitled project'}</p>\n          <span class=\"tc-status\" style=\"background:${color};\">${statusLabel[pin.status] || 'Available'}</span>\n          ${pin.type ? `<span class=\"tc-type\">${pin.type}</span>` : ''}\n          <div class=\"tc-meta\">${teaserLine(pin)}</div>\n          <div class=\"tc-actions\">\n            <button data-pin=\"${pin.id}\">View Full Details</button>\n            ${shareBtn}\n          </div>\n        </div></div>`;\n      // closeOnClick is off deliberately — we manage open/close ourselves\n      // below so behaviour is identical on desktop click and mobile tap\n      // (hover doesn't exist on touch, which used to leave the card stuck).\n      const popup = new maplibregl.Popup({offset:34, className:'teaser-popup', closeButton:true, closeOnClick:false}).setHTML(html);\n      popup.on('open', ()=>{\n        const btn = popup._content.querySelector('button[data-pin]');\n        if(btn) btn.addEventListener('click', ()=> requestDetails(pin));\n        const shareBtnEl = popup._content.querySelector('button[data-share-pin]');\n        if(shareBtnEl) shareBtnEl.addEventListener('click', (evt)=>{ evt.stopPropagation(); sharePin(pin); });\n      });\n      popup.on('close', ()=>{ if(openPopupMarker === marker) openPopupMarker = null; });\n      const marker = new maplibregl.Marker({element:el, anchor:'bottom'}).setLngLat([pin.lng, pin.lat]).setPopup(popup).addTo(map);\n      // One tap/click opens this card (closing any other open card first);\n      // tapping the same pin again, or anywhere else on the map, closes it.\n      el.addEventListener('click', (evt)=>{\n        evt.stopPropagation();\n        if(popup.isOpen()){ closeOpenPopup(); return; }\n        openMarkerPopup(marker);\n      });\n      pinMarkerMap.set(pin.id, {marker, pin});\n    });\n\n    // Tapping/clicking anywhere on the map that isn't a pin closes whatever\n    // card is currently open — this is the piece that was missing for mobile,\n    // where there's no hover event to fall back on.\n    map.on('click', ()=> closeOpenPopup());\n\n    // Focus the map on load: a shared pin link (?pin=<id>) takes priority,\n    // otherwise the company's own pin (number 1 / Associatte) is focused and highlighted.\n    (function focusOnLoad(){\n      const urlPinId = new URLSearchParams(window.location.search).get('pin');\n      const sharedPin = urlPinId ? pins.find(p => p.id === urlPinId) : null;\n      const companyPin = pins.find(p => p.number === 1) ||\n        pins.find(p => (p.title || '').toLowerCase().includes('associatte'));\n      const targetPin = sharedPin || companyPin;\n      if(!targetPin) return;\n      const entry = pinMarkerMap.get(targetPin.id);\n      if(!entry) return;\n      map.flyTo({ center:[targetPin.lng, targetPin.lat], zoom:17, pitch:38, bearing:-17, duration:1200 });\n      setTimeout(()=> openMarkerPopup(entry.marker), 1300);\n    })();\n  });\n\n  const pinMarkerMap = new Map();\n\n  // Tracks which project card is currently open, so only one is ever shown\n  // at a time (important when pins sit close together) and a click anywhere\n  // else — the map, or another pin — reliably closes it, on desktop or mobile.\n  let openPopupMarker = null;\n  function closeOpenPopup(){\n    if(openPopupMarker && openPopupMarker.getPopup() && openPopupMarker.getPopup().isOpen()){\n      openPopupMarker.togglePopup();\n    }\n    openPopupMarker = null;\n  }\n  function openMarkerPopup(marker){\n    if(openPopupMarker && openPopupMarker !== marker) closeOpenPopup();\n    if(!marker.getPopup().isOpen()) marker.togglePopup();\n    openPopupMarker = marker;\n  }\n\n  /* ---------------------------------------------------------\n     LEAD CAPTURE + DETAIL REVEAL (same flow as the 2D map)\n  --------------------------------------------------------- */\n  const overlayBg = document.getElementById('overlay-bg');\n  const leadBox = document.getElementById('lead-box');\n  const detailPanel = document.getElementById('detail-panel');\n  const leadRole = document.getElementById('lead-role');\n  const leadName = document.getElementById('lead-name');\n  const leadWhatsapp = document.getElementById('lead-whatsapp');\n  const leadWhatsappCode = document.getElementById('lead-whatsapp-code');\n  leadWhatsapp.addEventListener('input', ()=>{\n    leadWhatsapp.value = leadWhatsapp.value.replace(/\\D/g, '').slice(0, 10);\n  });\n  const leadEmail = document.getElementById('lead-email');\n  const leadConsent = document.getElementById('lead-consent');\n  const leadError = document.getElementById('lead-error');\n  const leadSubmit = document.getElementById('lead-submit');\n  const leadCancel = document.getElementById('lead-cancel');\n  const leadTitle = document.getElementById('lead-title');\n\n  let pendingPin = null;\n  function unlockKey(pinId){ return 'lead_unlocked_' + pinId; }\n\n  function requestDetails(pin){\n    if(localStorage.getItem(unlockKey(pin.id))){ showDetails(pin); return; }\n    pendingPin = pin;\n    leadTitle.textContent = 'See full details — ' + (pin.title || 'this project');\n    leadError.textContent = '';\n    leadName.value=''; leadWhatsapp.value=''; leadEmail.value=''; leadRole.value='buyer';\n    leadWhatsappCode.value = '+91';\n    leadConsent.checked = true;\n    leadBox.style.display = 'block';\n    detailPanel.classList.remove('open');\n    overlayBg.classList.add('open');\n  }\n  leadCancel.addEventListener('click', ()=>{ overlayBg.classList.remove('open'); leadBox.style.display='none'; pendingPin=null; });\n  overlayBg.addEventListener('click', (e)=>{ if(e.target === overlayBg){ overlayBg.classList.remove('open'); leadBox.style.display='none'; pendingPin=null; } });\n\n  leadSubmit.addEventListener('click', async ()=>{\n    const name = leadName.value.trim(), whatsappDigits = leadWhatsapp.value.trim(), email = leadEmail.value.trim(), role = leadRole.value;\n    if(!name || !whatsappDigits || !email){ leadError.textContent = 'Please fill in all fields.'; return; }\n    if(!/^\\d{10}$/.test(whatsappDigits)){ leadError.textContent = 'WhatsApp number must be exactly 10 digits.'; return; }\n    const whatsapp = leadWhatsappCode.value + ' ' + whatsappDigits;\n    if(!/^\\S+@\\S+\\.\\S+$/.test(email)){ leadError.textContent = 'Please enter a valid email.'; return; }\n    if(!leadConsent.checked){ leadError.textContent = 'Please provide consent to continue.'; return; }\n    leadSubmit.disabled = true; leadSubmit.textContent = 'Submitting…';\n    const { error } = await sb.from('leads').insert({ pin_id: pendingPin.id, role, name, whatsapp, email, consent: leadConsent.checked });\n    leadSubmit.disabled = false; leadSubmit.textContent = 'View Details';\n    if(error){ leadError.textContent = 'Something went wrong — please try again.'; return; }\n    localStorage.setItem(unlockKey(pendingPin.id), '1');\n    leadBox.style.display = 'none';\n    showDetails(pendingPin);\n  });\n\n  function showDetails(pin){\n    const color = statusColor[pin.status] || statusColor.available;\n    const img = document.getElementById('detail-img');\n    if(pin.image){ img.src = pin.image; img.style.display = 'block'; } else { img.style.display = 'none'; }\n    let rows = '';\n    if(pin.status === 'sold'){\n      rows = `<div class=\"detail-row\"><label>Status</label><div class=\"value\">This project has been sold out.</div></div>`;\n    } else {\n      if(pin.price) rows += `<div class=\"detail-row\"><label>Price</label><div class=\"value price\">${pin.price}</div></div>`;\n      if(pin.status === 'construction' || pin.status === 'upcoming'){\n        if(pin.configuration) rows += `<div class=\"detail-row\"><label>Configuration</label><div class=\"value\">${pin.configuration}</div></div>`;\n        if(pin.sqft) rows += `<div class=\"detail-row\"><label>Sq Ft</label><div class=\"value\">${pin.sqft}</div></div>`;\n      }\n      if(pin.status === 'construction' && pin.possession_timeline) rows += `<div class=\"detail-row\"><label>Possession Timeline</label><div class=\"value\">${pin.possession_timeline}</div></div>`;\n      if(pin.status === 'upcoming' && pin.launch_date) rows += `<div class=\"detail-row\"><label>Approximate Launch Date</label><div class=\"value\">${pin.launch_date}</div></div>`;\n      if(pin.status === 'available' && pin.whats_available) rows += `<div class=\"detail-row\"><label>What's Available</label><div class=\"value\">${pin.whats_available}</div></div>`;\n    }\n    if(pin.description) rows += `<div class=\"detail-row\"><label>Description</label><div class=\"value\">${pin.description}</div></div>`;\n    const detailShareBtn = `<button class=\"detail-share\" type=\"button\" id=\"detail-share-btn\">🔗 Share this project</button>`;\n    document.getElementById('detail-body').innerHTML = `\n      <h2>${pin.title || 'Untitled project'}</h2>\n      <span class=\"status-badge\" style=\"background:${color};\">${statusLabel[pin.status] || 'Available'}</span>\n      ${pin.type ? `<div class=\"detail-row\"><label>Type</label><div class=\"value\">${pin.type}</div></div>` : ''}\n      ${rows}\n      ${detailShareBtn}\n    `;\n    const shareEl = document.getElementById('detail-share-btn');\n    if(shareEl) shareEl.addEventListener('click', ()=> sharePin(pin));\n    overlayBg.classList.add('open');\n    detailPanel.classList.add('open');\n  }\n  document.getElementById('detail-close').addEventListener('click', ()=>{\n    detailPanel.classList.remove('open'); overlayBg.classList.remove('open');\n  });\n\n  /* ---------------------------------------------------------\n     SEARCH — flies the camera to the matching project\n  --------------------------------------------------------- */\n  document.getElementById('search-input').addEventListener('input', (e)=>{\n    const q = e.target.value.trim().toLowerCase();\n    if(!q) return;\n    const match = pins.find(p => (p.title||'').toLowerCase().includes(q));\n    if(match){\n      map.flyTo({ center:[match.lng, match.lat], zoom:16.5, pitch:42, essential:true });\n      const entry = pinMarkerMap.get(match.id);\n      if(entry) openMarkerPopup(entry.marker);\n    }\n  });\n\n  // ---------- View-source deterrent: TEMPORARILY DISABLED ----------\n  // Right-click / DevTools blocking is off while debugging the search\n  // feature. Say the word and I'll switch it back on.\n\n})();\n"}],"bodyHtml":"\n\n\n\n\n\n<div id=\"loading\"><div class=\"spin\"></div><div>Loading the 3D map…</div></div>\n<div id=\"map\"></div>\n\n<div id=\"topbar\">\n  <div class=\"brand\">\n    <img src=\"/img/Mappingg.com PNG logo(1).png\" alt=\"Associatte\" class=\"logo\" onerror=\"this.style.display='none'\">\n    <div class=\"brand-text\">\n      <h1>Associatte Interactive Map — 3D</h1>\n      <span>Live projects &amp; infrastructure</span>\n    </div>\n  </div>\n  <div id=\"toolbar\">\n    <input type=\"text\" id=\"search-input\" placeholder=\"🔍 Search a project name\">\n    <a class=\"btn\" href=\"index.html\">🗺️ 2D Map</a>\n  </div>\n</div>\n\n<div id=\"tilt-hint\">🖱️ Drag with right-click (or two fingers) to tilt &amp; rotate</div>\n\n<div id=\"legend\">\n  <h4>Legend</h4>\n  <div class=\"row\"><span class=\"swatch\" style=\"background:var(--available)\"></span> Available</div>\n  <div class=\"row\"><span class=\"swatch\" style=\"background:var(--sold)\"></span> Sold</div>\n  <div class=\"row\"><span class=\"swatch\" style=\"background:var(--construction)\"></span> Under Construction</div>\n  <div class=\"row\"><span class=\"swatch\" style=\"background:var(--upcoming)\"></span> Upcoming</div>\n</div>\n\n<div id=\"overlay-bg\">\n  <div id=\"lead-box\" style=\"display:none;\">\n    <h3 id=\"lead-title\">See full project details</h3>\n    <p>Quick details so we can follow up on this project for you.</p>\n    <div class=\"field\">\n      <label>I'm a</label>\n      <select id=\"lead-role\">\n        <option value=\"developer\">Developer / Builder</option>\n        <option value=\"agent\">Sales Agent / Broker / Channel Partner</option>\n        <option value=\"buyer\" selected>Buyer / Investor</option>\n      </select>\n    </div>\n    <div class=\"field\">\n      <label>Name</label>\n      <input type=\"text\" id=\"lead-name\" placeholder=\"Your full name\">\n    </div>\n    <div class=\"field\">\n      <label>WhatsApp Number</label>\n      <div style=\"display:flex;gap:8px;\">\n        <select id=\"lead-whatsapp-code\" style=\"flex:0 0 90px;\">\n        <option value=\"+93\" title=\"Afghanistan\">🇦🇫 +93</option>\n        <option value=\"+355\" title=\"Albania\">🇦🇱 +355</option>\n        <option value=\"+213\" title=\"Algeria\">🇩🇿 +213</option>\n        <option value=\"+1684\" title=\"American Samoa\">🇦🇸 +1684</option>\n        <option value=\"+376\" title=\"Andorra\">🇦🇩 +376</option>\n        <option value=\"+244\" title=\"Angola\">🇦🇴 +244</option>\n        <option value=\"+1264\" title=\"Anguilla\">🇦🇮 +1264</option>\n        <option value=\"+1268\" title=\"Antigua and Barbuda\">🇦🇬 +1268</option>\n        <option value=\"+54\" title=\"Argentina\">🇦🇷 +54</option>\n        <option value=\"+374\" title=\"Armenia\">🇦🇲 +374</option>\n        <option value=\"+297\" title=\"Aruba\">🇦🇼 +297</option>\n        <option value=\"+61\" title=\"Australia\">🇦🇺 +61</option>\n        <option value=\"+43\" title=\"Austria\">🇦🇹 +43</option>\n        <option value=\"+994\" title=\"Azerbaijan\">🇦🇿 +994</option>\n        <option value=\"+1242\" title=\"Bahamas\">🇧🇸 +1242</option>\n        <option value=\"+973\" title=\"Bahrain\">🇧🇭 +973</option>\n        <option value=\"+880\" title=\"Bangladesh\">🇧🇩 +880</option>\n        <option value=\"+1246\" title=\"Barbados\">🇧🇧 +1246</option>\n        <option value=\"+375\" title=\"Belarus\">🇧🇾 +375</option>\n        <option value=\"+32\" title=\"Belgium\">🇧🇪 +32</option>\n        <option value=\"+501\" title=\"Belize\">🇧🇿 +501</option>\n        <option value=\"+229\" title=\"Benin\">🇧🇯 +229</option>\n        <option value=\"+1441\" title=\"Bermuda\">🇧🇲 +1441</option>\n        <option value=\"+975\" title=\"Bhutan\">🇧🇹 +975</option>\n        <option value=\"+591\" title=\"Bolivia\">🇧🇴 +591</option>\n        <option value=\"+387\" title=\"Bosnia and Herzegovina\">🇧🇦 +387</option>\n        <option value=\"+267\" title=\"Botswana\">🇧🇼 +267</option>\n        <option value=\"+55\" title=\"Brazil\">🇧🇷 +55</option>\n        <option value=\"+673\" title=\"Brunei\">🇧🇳 +673</option>\n        <option value=\"+359\" title=\"Bulgaria\">🇧🇬 +359</option>\n        <option value=\"+226\" title=\"Burkina Faso\">🇧🇫 +226</option>\n        <option value=\"+257\" title=\"Burundi\">🇧🇮 +257</option>\n        <option value=\"+855\" title=\"Cambodia\">🇰🇭 +855</option>\n        <option value=\"+237\" title=\"Cameroon\">🇨🇲 +237</option>\n        <option value=\"+1\" title=\"Canada\">🇨🇦 +1</option>\n        <option value=\"+238\" title=\"Cape Verde\">🇨🇻 +238</option>\n        <option value=\"+1345\" title=\"Cayman Islands\">🇰🇾 +1345</option>\n        <option value=\"+236\" title=\"Central African Republic\">🇨🇫 +236</option>\n        <option value=\"+235\" title=\"Chad\">🇹🇩 +235</option>\n        <option value=\"+56\" title=\"Chile\">🇨🇱 +56</option>\n        <option value=\"+86\" title=\"China\">🇨🇳 +86</option>\n        <option value=\"+57\" title=\"Colombia\">🇨🇴 +57</option>\n        <option value=\"+269\" title=\"Comoros\">🇰🇲 +269</option>\n        <option value=\"+242\" title=\"Congo\">🇨🇬 +242</option>\n        <option value=\"+243\" title=\"Congo (DRC)\">🇨🇩 +243</option>\n        <option value=\"+682\" title=\"Cook Islands\">🇨🇰 +682</option>\n        <option value=\"+506\" title=\"Costa Rica\">🇨🇷 +506</option>\n        <option value=\"+385\" title=\"Croatia\">🇭🇷 +385</option>\n        <option value=\"+53\" title=\"Cuba\">🇨🇺 +53</option>\n        <option value=\"+357\" title=\"Cyprus\">🇨🇾 +357</option>\n        <option value=\"+420\" title=\"Czech Republic\">🇨🇿 +420</option>\n        <option value=\"+45\" title=\"Denmark\">🇩🇰 +45</option>\n        <option value=\"+253\" title=\"Djibouti\">🇩🇯 +253</option>\n        <option value=\"+1767\" title=\"Dominica\">🇩🇲 +1767</option>\n        <option value=\"+1809\" title=\"Dominican Republic\">🇩🇴 +1809</option>\n        <option value=\"+593\" title=\"Ecuador\">🇪🇨 +593</option>\n        <option value=\"+20\" title=\"Egypt\">🇪🇬 +20</option>\n        <option value=\"+503\" title=\"El Salvador\">🇸🇻 +503</option>\n        <option value=\"+240\" title=\"Equatorial Guinea\">🇬🇶 +240</option>\n        <option value=\"+291\" title=\"Eritrea\">🇪🇷 +291</option>\n        <option value=\"+372\" title=\"Estonia\">🇪🇪 +372</option>\n        <option value=\"+268\" title=\"Eswatini\">🇸🇿 +268</option>\n        <option value=\"+251\" title=\"Ethiopia\">🇪🇹 +251</option>\n        <option value=\"+679\" title=\"Fiji\">🇫🇯 +679</option>\n        <option value=\"+358\" title=\"Finland\">🇫🇮 +358</option>\n        <option value=\"+33\" title=\"France\">🇫🇷 +33</option>\n        <option value=\"+594\" title=\"French Guiana\">🇬🇫 +594</option>\n        <option value=\"+689\" title=\"French Polynesia\">🇵🇫 +689</option>\n        <option value=\"+241\" title=\"Gabon\">🇬🇦 +241</option>\n        <option value=\"+220\" title=\"Gambia\">🇬🇲 +220</option>\n        <option value=\"+995\" title=\"Georgia\">🇬🇪 +995</option>\n        <option value=\"+49\" title=\"Germany\">🇩🇪 +49</option>\n        <option value=\"+233\" title=\"Ghana\">🇬🇭 +233</option>\n        <option value=\"+350\" title=\"Gibraltar\">🇬🇮 +350</option>\n        <option value=\"+30\" title=\"Greece\">🇬🇷 +30</option>\n        <option value=\"+299\" title=\"Greenland\">🇬🇱 +299</option>\n        <option value=\"+1473\" title=\"Grenada\">🇬🇩 +1473</option>\n        <option value=\"+590\" title=\"Guadeloupe\">🇬🇵 +590</option>\n        <option value=\"+1671\" title=\"Guam\">🇬🇺 +1671</option>\n        <option value=\"+502\" title=\"Guatemala\">🇬🇹 +502</option>\n        <option value=\"+224\" title=\"Guinea\">🇬🇳 +224</option>\n        <option value=\"+245\" title=\"Guinea-Bissau\">🇬🇼 +245</option>\n        <option value=\"+592\" title=\"Guyana\">🇬🇾 +592</option>\n        <option value=\"+509\" title=\"Haiti\">🇭🇹 +509</option>\n        <option value=\"+504\" title=\"Honduras\">🇭🇳 +504</option>\n        <option value=\"+852\" title=\"Hong Kong\">🇭🇰 +852</option>\n        <option value=\"+36\" title=\"Hungary\">🇭🇺 +36</option>\n        <option value=\"+354\" title=\"Iceland\">🇮🇸 +354</option>\n        <option value=\"+91\" selected title=\"India\">🇮🇳 +91</option>\n        <option value=\"+62\" title=\"Indonesia\">🇮🇩 +62</option>\n        <option value=\"+98\" title=\"Iran\">🇮🇷 +98</option>\n        <option value=\"+964\" title=\"Iraq\">🇮🇶 +964</option>\n        <option value=\"+353\" title=\"Ireland\">🇮🇪 +353</option>\n        <option value=\"+972\" title=\"Israel\">🇮🇱 +972</option>\n        <option value=\"+39\" title=\"Italy\">🇮🇹 +39</option>\n        <option value=\"+1876\" title=\"Jamaica\">🇯🇲 +1876</option>\n        <option value=\"+81\" title=\"Japan\">🇯🇵 +81</option>\n        <option value=\"+962\" title=\"Jordan\">🇯🇴 +962</option>\n        <option value=\"+7\" title=\"Kazakhstan\">🇰🇿 +7</option>\n        <option value=\"+254\" title=\"Kenya\">🇰🇪 +254</option>\n        <option value=\"+686\" title=\"Kiribati\">🇰🇮 +686</option>\n        <option value=\"+965\" title=\"Kuwait\">🇰🇼 +965</option>\n        <option value=\"+996\" title=\"Kyrgyzstan\">🇰🇬 +996</option>\n        <option value=\"+856\" title=\"Laos\">🇱🇦 +856</option>\n        <option value=\"+371\" title=\"Latvia\">🇱🇻 +371</option>\n        <option value=\"+961\" title=\"Lebanon\">🇱🇧 +961</option>\n        <option value=\"+266\" title=\"Lesotho\">🇱🇸 +266</option>\n        <option value=\"+231\" title=\"Liberia\">🇱🇷 +231</option>\n        <option value=\"+218\" title=\"Libya\">🇱🇾 +218</option>\n        <option value=\"+423\" title=\"Liechtenstein\">🇱🇮 +423</option>\n        <option value=\"+370\" title=\"Lithuania\">🇱🇹 +370</option>\n        <option value=\"+352\" title=\"Luxembourg\">🇱🇺 +352</option>\n        <option value=\"+853\" title=\"Macau\">🇲🇴 +853</option>\n        <option value=\"+261\" title=\"Madagascar\">🇲🇬 +261</option>\n        <option value=\"+265\" title=\"Malawi\">🇲🇼 +265</option>\n        <option value=\"+60\" title=\"Malaysia\">🇲🇾 +60</option>\n        <option value=\"+960\" title=\"Maldives\">🇲🇻 +960</option>\n        <option value=\"+223\" title=\"Mali\">🇲🇱 +223</option>\n        <option value=\"+356\" title=\"Malta\">🇲🇹 +356</option>\n        <option value=\"+692\" title=\"Marshall Islands\">🇲🇭 +692</option>\n        <option value=\"+596\" title=\"Martinique\">🇲🇶 +596</option>\n        <option value=\"+222\" title=\"Mauritania\">🇲🇷 +222</option>\n        <option value=\"+230\" title=\"Mauritius\">🇲🇺 +230</option>\n        <option value=\"+52\" title=\"Mexico\">🇲🇽 +52</option>\n        <option value=\"+691\" title=\"Micronesia\">🇫🇲 +691</option>\n        <option value=\"+373\" title=\"Moldova\">🇲🇩 +373</option>\n        <option value=\"+377\" title=\"Monaco\">🇲🇨 +377</option>\n        <option value=\"+976\" title=\"Mongolia\">🇲🇳 +976</option>\n        <option value=\"+382\" title=\"Montenegro\">🇲🇪 +382</option>\n        <option value=\"+1664\" title=\"Montserrat\">🇲🇸 +1664</option>\n        <option value=\"+212\" title=\"Morocco\">🇲🇦 +212</option>\n        <option value=\"+258\" title=\"Mozambique\">🇲🇿 +258</option>\n        <option value=\"+95\" title=\"Myanmar\">🇲🇲 +95</option>\n        <option value=\"+264\" title=\"Namibia\">🇳🇦 +264</option>\n        <option value=\"+674\" title=\"Nauru\">🇳🇷 +674</option>\n        <option value=\"+977\" title=\"Nepal\">🇳🇵 +977</option>\n        <option value=\"+31\" title=\"Netherlands\">🇳🇱 +31</option>\n        <option value=\"+687\" title=\"New Caledonia\">🇳🇨 +687</option>\n        <option value=\"+64\" title=\"New Zealand\">🇳🇿 +64</option>\n        <option value=\"+505\" title=\"Nicaragua\">🇳🇮 +505</option>\n        <option value=\"+227\" title=\"Niger\">🇳🇪 +227</option>\n        <option value=\"+234\" title=\"Nigeria\">🇳🇬 +234</option>\n        <option value=\"+683\" title=\"Niue\">🇳🇺 +683</option>\n        <option value=\"+850\" title=\"North Korea\">🇰🇵 +850</option>\n        <option value=\"+389\" title=\"North Macedonia\">🇲🇰 +389</option>\n        <option value=\"+47\" title=\"Norway\">🇳🇴 +47</option>\n        <option value=\"+968\" title=\"Oman\">🇴🇲 +968</option>\n        <option value=\"+92\" title=\"Pakistan\">🇵🇰 +92</option>\n        <option value=\"+680\" title=\"Palau\">🇵🇼 +680</option>\n        <option value=\"+970\" title=\"Palestine\">🇵🇸 +970</option>\n        <option value=\"+507\" title=\"Panama\">🇵🇦 +507</option>\n        <option value=\"+675\" title=\"Papua New Guinea\">🇵🇬 +675</option>\n        <option value=\"+595\" title=\"Paraguay\">🇵🇾 +595</option>\n        <option value=\"+51\" title=\"Peru\">🇵🇪 +51</option>\n        <option value=\"+63\" title=\"Philippines\">🇵🇭 +63</option>\n        <option value=\"+48\" title=\"Poland\">🇵🇱 +48</option>\n        <option value=\"+351\" title=\"Portugal\">🇵🇹 +351</option>\n        <option value=\"+1787\" title=\"Puerto Rico\">🇵🇷 +1787</option>\n        <option value=\"+974\" title=\"Qatar\">🇶🇦 +974</option>\n        <option value=\"+262\" title=\"Reunion\">🇷🇪 +262</option>\n        <option value=\"+40\" title=\"Romania\">🇷🇴 +40</option>\n        <option value=\"+7\" title=\"Russia\">🇷🇺 +7</option>\n        <option value=\"+250\" title=\"Rwanda\">🇷🇼 +250</option>\n        <option value=\"+685\" title=\"Samoa\">🇼🇸 +685</option>\n        <option value=\"+378\" title=\"San Marino\">🇸🇲 +378</option>\n        <option value=\"+239\" title=\"Sao Tome and Principe\">🇸🇹 +239</option>\n        <option value=\"+966\" title=\"Saudi Arabia\">🇸🇦 +966</option>\n        <option value=\"+221\" title=\"Senegal\">🇸🇳 +221</option>\n        <option value=\"+381\" title=\"Serbia\">🇷🇸 +381</option>\n        <option value=\"+248\" title=\"Seychelles\">🇸🇨 +248</option>\n        <option value=\"+232\" title=\"Sierra Leone\">🇸🇱 +232</option>\n        <option value=\"+65\" title=\"Singapore\">🇸🇬 +65</option>\n        <option value=\"+421\" title=\"Slovakia\">🇸🇰 +421</option>\n        <option value=\"+386\" title=\"Slovenia\">🇸🇮 +386</option>\n        <option value=\"+677\" title=\"Solomon Islands\">🇸🇧 +677</option>\n        <option value=\"+252\" title=\"Somalia\">🇸🇴 +252</option>\n        <option value=\"+27\" title=\"South Africa\">🇿🇦 +27</option>\n        <option value=\"+82\" title=\"South Korea\">🇰🇷 +82</option>\n        <option value=\"+211\" title=\"South Sudan\">🇸🇸 +211</option>\n        <option value=\"+34\" title=\"Spain\">🇪🇸 +34</option>\n        <option value=\"+94\" title=\"Sri Lanka\">🇱🇰 +94</option>\n        <option value=\"+1869\" title=\"St Kitts and Nevis\">🇰🇳 +1869</option>\n        <option value=\"+1758\" title=\"St Lucia\">🇱🇨 +1758</option>\n        <option value=\"+1784\" title=\"St Vincent\">🇻🇨 +1784</option>\n        <option value=\"+249\" title=\"Sudan\">🇸🇩 +249</option>\n        <option value=\"+597\" title=\"Suriname\">🇸🇷 +597</option>\n        <option value=\"+46\" title=\"Sweden\">🇸🇪 +46</option>\n        <option value=\"+41\" title=\"Switzerland\">🇨🇭 +41</option>\n        <option value=\"+963\" title=\"Syria\">🇸🇾 +963</option>\n        <option value=\"+886\" title=\"Taiwan\">🇹🇼 +886</option>\n        <option value=\"+992\" title=\"Tajikistan\">🇹🇯 +992</option>\n        <option value=\"+255\" title=\"Tanzania\">🇹🇿 +255</option>\n        <option value=\"+66\" title=\"Thailand\">🇹🇭 +66</option>\n        <option value=\"+670\" title=\"Timor-Leste\">🇹🇱 +670</option>\n        <option value=\"+228\" title=\"Togo\">🇹🇬 +228</option>\n        <option value=\"+676\" title=\"Tonga\">🇹🇴 +676</option>\n        <option value=\"+1868\" title=\"Trinidad and Tobago\">🇹🇹 +1868</option>\n        <option value=\"+216\" title=\"Tunisia\">🇹🇳 +216</option>\n        <option value=\"+90\" title=\"Turkey\">🇹🇷 +90</option>\n        <option value=\"+993\" title=\"Turkmenistan\">🇹🇲 +993</option>\n        <option value=\"+1649\" title=\"Turks and Caicos\">🇹🇨 +1649</option>\n        <option value=\"+688\" title=\"Tuvalu\">🇹🇻 +688</option>\n        <option value=\"+256\" title=\"Uganda\">🇺🇬 +256</option>\n        <option value=\"+380\" title=\"Ukraine\">🇺🇦 +380</option>\n        <option value=\"+971\" title=\"United Arab Emirates\">🇦🇪 +971</option>\n        <option value=\"+44\" title=\"United Kingdom\">🇬🇧 +44</option>\n        <option value=\"+1\" title=\"United States\">🇺🇸 +1</option>\n        <option value=\"+598\" title=\"Uruguay\">🇺🇾 +598</option>\n        <option value=\"+998\" title=\"Uzbekistan\">🇺🇿 +998</option>\n        <option value=\"+678\" title=\"Vanuatu\">🇻🇺 +678</option>\n        <option value=\"+379\" title=\"Vatican City\">🇻🇦 +379</option>\n        <option value=\"+58\" title=\"Venezuela\">🇻🇪 +58</option>\n        <option value=\"+84\" title=\"Vietnam\">🇻🇳 +84</option>\n        <option value=\"+1284\" title=\"British Virgin Islands\">🇻🇬 +1284</option>\n        <option value=\"+1340\" title=\"US Virgin Islands\">🇻🇮 +1340</option>\n        <option value=\"+967\" title=\"Yemen\">🇾🇪 +967</option>\n        <option value=\"+260\" title=\"Zambia\">🇿🇲 +260</option>\n        <option value=\"+263\" title=\"Zimbabwe\">🇿🇼 +263</option>\n        </select>\n        <input type=\"tel\" id=\"lead-whatsapp\" placeholder=\"10-digit number\" maxlength=\"10\" inputmode=\"numeric\" style=\"flex:1;\">\n      </div>\n    </div>\n    <div class=\"field\">\n      <label>Email</label>\n      <input type=\"email\" id=\"lead-email\" placeholder=\"you@example.com\">\n    </div>\n    <div id=\"lead-consent-row\">\n      <input type=\"checkbox\" id=\"lead-consent\" checked>\n      <label for=\"lead-consent\">I Consent to The Processing of Provided Data According To Privacy Policy | Terms &amp; Conditions, I Authorize Associatte and its representatives to Call, SMS, Email or WhatsApp Me About Its Products and Offers. This Consent Overrides Any Registration For DNC/NDNC.</label>\n    </div>\n    <div id=\"lead-error\"></div>\n    <div class=\"lead-actions\">\n      <button id=\"lead-cancel\">Cancel</button>\n      <button id=\"lead-submit\">View Details</button>\n    </div>\n  </div>\n\n  <div id=\"detail-panel\">\n    <div id=\"detail-head\">\n      <button id=\"detail-close\">✕</button>\n      <img id=\"detail-img\" style=\"display:none;\">\n    </div>\n    <div id=\"detail-body\"></div>\n  </div>\n</div>\n\n\n\n\n"}