/* Banyan Pharmacy — Kolkata map: detailed vector basemap, pan (no zoom),
   floating HUD, uniform pins, in-pan tooltip (no jitter). */
const { useState: useStateM, useRef: useRefM, useEffect: useEffectM, useLayoutEffect } = React;

/* zoom-control styles (injected once; pharma.css is the canonical home) */
if (typeof document !== "undefined" && !document.getElementById("map-zoom-css")) {
  const _mzs = document.createElement("style");
  _mzs.id = "map-zoom-css";
  _mzs.textContent = `
.map-zoom { position: absolute; right: 18px; bottom: 76px; z-index: 20; display: flex; flex-direction: column; background: rgba(251,248,242,0.92); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); border: 1px solid var(--rule); border-radius: 10px; overflow: hidden; box-shadow: var(--shadow-1); }
.map-zoom .mz-btn { width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 0; color: var(--body); cursor: pointer; transition: background 140ms, color 140ms; }
.map-zoom .mz-btn + .mz-btn { border-top: 1px solid var(--rule); }
.map-zoom .mz-btn:hover:not(:disabled) { background: var(--stone-deep); color: var(--clay-deep); }
.map-zoom .mz-btn:active:not(:disabled) { transform: translateY(0.5px); }
.map-zoom .mz-btn:disabled { color: var(--fade); cursor: default; }`;
  document.head.appendChild(_mzs);
}

/* ---- projection: lat/lng -> fixed-px map space -------------------------- */
const MAPW = 1280, MAPH = 1800;
const LNG0 = 88.285, LNG1 = 88.445;   // west .. east
const LATT = 22.660, LATB = 22.450;   // top(north) .. bottom(south)
function proj(lat, lng) {
  return { x: ((lng - LNG0) / (LNG1 - LNG0)) * MAPW, y: ((LATT - lat) / (LATT - LATB)) * MAPH };
}
const STATUS_COLOR = { healthy: "var(--green)", watch: "var(--amber)", atrisk: "var(--red)", critical: "var(--clay)" };

/* small per-store map nudges (cartographic legibility only) */
const NUDGE = { str_behala01: { dx: 50, dy: 0 } };
function pinXY(store) {
  const p = proj(store.lat, store.lng); const n = NUDGE[store.id];
  return n ? { x: p.x + n.dx, y: p.y + n.dy } : p;
}
/* label offset so locality text doesn't sit on the dot */
const LABELPOS = {
  str_parkst01: { dx: 16, dy: 5, a: "start" }, str_gariah01: { dx: 16, dy: 5, a: "start" },
  str_dhakur01: { dx: -16, dy: 16, a: "end" }, str_mukund01: { dx: 16, dy: 16, a: "start" },
  str_ananda01: { dx: 16, dy: -8, a: "start" }, str_behala01: { dx: -16, dy: 5, a: "end" },
  str_saltlk01: { dx: -16, dy: 6, a: "end" }, str_shyamb01: { dx: -16, dy: -8, a: "end" },
  str_howrah01: { dx: -16, dy: 5, a: "end" },
};

/* ===================== the basemap art ================================== */
function Basemap() {
  return (
    <g>
      {/* land ground */}
      <rect x="-40" y="-40" width={MAPW + 80} height={MAPH + 80} fill="#F1EBDF" />

      {/* ---- water bodies ---- */}
      {/* East Kolkata Wetlands (east/southeast) */}
      <path d="M1040 1060 C 1120 1050 1240 1070 1300 1110 L1320 1760 L1000 1780
               C 980 1700 1000 1600 1010 1500 C 1018 1400 1000 1300 1020 1200 C 1030 1140 1030 1100 1040 1060 Z"
        fill="#BCCBCB" opacity="0.9" />
      <path d="M1060 1140 C 1120 1150 1180 1180 1210 1230" fill="none" stroke="#A9BBBB" strokeWidth="2" opacity="0.6" />
      <path d="M1050 1320 C 1130 1330 1200 1360 1250 1410" fill="none" stroke="#A9BBBB" strokeWidth="2" opacity="0.6" />
      {/* Hooghly river — wide ribbon, N->S bending SW */}
      <path d="M360 -30 C 350 200, 336 400, 318 620 C 296 840, 268 1040, 232 1240 C 196 1440, 172 1620, 160 1840"
        fill="none" stroke="#B7C7C9" strokeWidth="84" strokeLinecap="round" />
      <path d="M360 -30 C 350 200, 336 400, 318 620 C 296 840, 268 1040, 232 1240 C 196 1440, 172 1620, 160 1840"
        fill="none" stroke="#CAD7D8" strokeWidth="2" strokeLinecap="round" opacity="0.8" />
      {/* lakes */}
      <ellipse cx="592" cy="1432" rx="46" ry="84" fill="#BCCBCB" />{/* Rabindra Sarobar */}
      <ellipse cx="952" cy="566" rx="42" ry="30" fill="#BCCBCB" />{/* Subhash Sarobar */}

      {/* ---- parks (muted sage) ---- */}
      <path d="M392 770 C 470 760 472 900 458 1010 C 450 1070 420 1085 392 1080 C 372 1010 372 880 392 770 Z" fill="#C2CCA8" />{/* Maidan */}
      <rect x="1086" y="556" width="132" height="150" rx="6" fill="#C9D2B2" />{/* Salt Lake Central Park area */}
      <path d="M520 1520 C 600 1510 640 1560 628 1620 C 618 1665 560 1672 520 1660 C 506 1610 506 1560 520 1520 Z" fill="#C2CCA8" />{/* Tollygunge green */}
      <ellipse cx="452" cy="1248" rx="40" ry="34" fill="#C9D2B2" />{/* Alipore */}

      {/* ---- secondary street mesh (texture) ---- */}
      <g stroke="#E2D9C7" strokeWidth="1.6" fill="none" opacity="0.85">
        <path d="M560 700 L700 720 M560 800 L760 815 M520 900 L720 910 M520 980 L760 980 M540 1080 L780 1075" />
        <path d="M600 760 L590 1180 M660 720 L650 1240 M740 780 L735 1240 M820 940 L815 1300" />
        <path d="M860 700 L1000 690 M880 800 L1010 800 M880 900 L1000 905 M860 1000 L1000 1010 M840 1120 L990 1130" />
        <path d="M460 1140 L700 1150 M440 1260 L680 1270 M460 1360 L700 1370 M520 1460 L740 1470" />
        <path d="M300 1320 L520 1360 M280 1420 L500 1450 M300 1520 L540 1540" />
        <path d="M700 480 L840 470 M720 560 L880 560 M740 360 L900 360" />
        <path d="M1040 760 L1180 780 M1050 900 L1200 920 M1040 1000 L1180 1020" />
      </g>

      {/* ---- arterial roads (ochre with casing) ---- */}
      {[
        ["M940 460 C 950 640 965 820 950 1000 C 935 1180 905 1340 890 1480 C 878 1580 872 1640 868 1700", 11],
        ["M700 510 C 665 640 600 740 560 860 C 535 950 545 1050 558 1150 C 572 1250 575 1340 562 1450 C 552 1540 548 1610 548 1700", 10],
        ["M770 545 C 870 460 1000 350 1140 250", 9],
        ["M545 1015 C 460 1085 360 1185 285 1290 C 235 1355 205 1420 180 1490", 9],
        ["M690 1050 C 780 1035 860 1010 940 985", 8],
        ["M700 640 C 760 720 800 820 820 920", 7],
        ["M700 510 C 720 410 742 310 762 200", 8],
        ["M150 560 C 230 585 290 605 322 622", 7],
        ["M150 720 C 230 700 285 665 300 645", 7],
        ["M430 985 C 560 1000 700 1010 700 1050", 6],
      ].map(([d, w], i) => (
        <g key={i}>
          <path d={d} fill="none" stroke="#D8C49A" strokeWidth={w + 3} strokeLinecap="round" strokeLinejoin="round" />
          <path d={d} fill="none" stroke="#EBD7AE" strokeWidth={w} strokeLinecap="round" strokeLinejoin="round" />
        </g>
      ))}

      {/* bridges over the Hooghly */}
      <g stroke="#9A9384" strokeWidth="5" strokeLinecap="round">
        <path d="M322 430 L432 430" />{/* Howrah Bridge */}
        <path d="M300 770 L470 748" />{/* Vidyasagar Setu */}
      </g>

      {/* ---- railway (dashed dark) ---- */}
      <g fill="none" stroke="#5A554C" strokeWidth="3.4" strokeDasharray="11 8" opacity="0.7">
        <path d="M360 360 C 350 600 320 840 280 1080 C 252 1270 224 1410 206 1520" />
        <path d="M722 940 C 822 922 922 902 1006 872" />
        <path d="M722 940 C 704 840 694 740 704 624" />
        <path d="M704 1230 C 800 1276 900 1340 982 1422" />
      </g>
      {/* Howrah Station marks */}
      <g stroke="#8A8276" strokeWidth="2.4">
        <path d="M150 470 L210 478 M150 492 L210 500 M150 514 L210 522" />
      </g>

      {/* ---- metro line 1 (dashed muted green) ---- */}
      <path d="M690 300 C 660 500 600 720 560 900 C 535 1010 548 1140 560 1280 C 568 1380 565 1470 558 1560"
        fill="none" stroke="#7FA589" strokeWidth="5" strokeLinecap="round" strokeDasharray="3 11" />

      {/* ===== map labels ===== */}
      <text x="262" y="980" transform="rotate(-79 262 980)" style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontSize: 26, fill: "#7E9499" }}>Hooghly River</text>
      <Lbl x={1186} y={1420} s={13} caps c="#7E9499">EAST KOLKATA</Lbl>
      <Lbl x={1186} y={1442} s={13} caps c="#7E9499">WETLANDS</Lbl>
      <text x="592" y="1436" textAnchor="middle" style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontSize: 14, fill: "#7E9499" }}>Rabindra</text>
      <text x="592" y="1454" textAnchor="middle" style={{ fontFamily: "var(--font-serif)", fontStyle: "italic", fontSize: 14, fill: "#7E9499" }}>Sarobar</text>
      <text x="425" y="930" transform="rotate(-90 425 930)" textAnchor="middle" style={{ fontFamily: "var(--font-sans)", fontSize: 19, fontWeight: 600, letterSpacing: "0.04em", fill: "#7C8758" }}>THE MAIDAN</text>
      <text x="905" y="900" transform="rotate(86 905 900)" textAnchor="middle" style={{ fontFamily: "var(--font-sans)", fontSize: 13, fontWeight: 600, letterSpacing: "0.16em", fill: "#B6A985" }}>EM BYPASS</text>
      <text x="980" y="360" transform="rotate(-44 980 360)" textAnchor="middle" style={{ fontFamily: "var(--font-sans)", fontSize: 12.5, fontWeight: 600, letterSpacing: "0.15em", fill: "#B6A985" }}>VIP ROAD</text>
      {[
        ["Bagbazar", 700, 612], ["Ultadanga", 806, 612], ["Maniktala", 762, 740], ["Sealdah", 724, 956],
        ["BBD Bagh", 452, 856], ["Esplanade", 506, 992], ["Park Circus", 726, 1064], ["Bhowanipore", 556, 1148],
        ["Kalighat", 584, 1276], ["Alipore", 452, 1212], ["Ballygunge", 706, 1162], ["Jadavpur", 706, 1492],
        ["Tollygunge", 556, 1604], ["Garia", 648, 1716], ["New Alipore", 416, 1392], ["Garden Reach", 236, 1648],
        ["Shibpur", 150, 742], ["Beleghata", 884, 856], ["Tangra", 846, 1086], ["Topsia", 826, 1186],
        ["Dum Dum", 724, 296], ["Lake Town", 902, 452], ["New Town", 1190, 552], ["Bidhannagar", 1100, 720],
        ["Santoshpur", 768, 1556], ["Baranagar", 540, 220], ["Cossipore", 470, 360],
      ].map(([t, x, y]) => <Lbl key={t} x={x} y={y} s={17} c="#6E6657">{t}</Lbl>)}
    </g>
  );
}

function Lbl({ x, y, s = 17, c = "#6E6657", caps, children, anchor = "middle" }) {
  return (
    <text x={x} y={y} textAnchor={anchor}
      style={{ fontFamily: "var(--font-sans)", fontSize: s, fontWeight: caps ? 600 : 500,
        letterSpacing: caps ? "0.12em" : "-0.005em", fill: c }}>{children}</text>
  );
}

/* ---- uniform store pin (shape constant; type lives in the tooltip) ----- */
function Pin({ store, status, onEnter, onLeave, onClick, focused, dim, showLabel }) {
  const { x, y } = pinXY(store);
  const color = STATUS_COLOR[status];
  const lp = LABELPOS[store.id] || { dx: 16, dy: 5, a: "start" };
  return (
    <g className={cx("map-pin", focused && "flip-anim")} transform={`translate(${x} ${y})`} opacity={dim ? 0.3 : 1}
      onMouseEnter={() => onEnter && onEnter(store)} onMouseLeave={() => onLeave && onLeave()}
      onClick={(e) => { if (onClick) { e.stopPropagation(); onClick(store); } }}
      style={{ cursor: onClick ? "pointer" : "default" }}>
      {focused && <circle className="map-ring" r="13" fill="none" stroke={color} strokeWidth="2.5" />}
      <circle className="pin-hit" r="17" fill="transparent" />
      {/* format, quietly: cross = hospital · larger = flagship · dot = neighbourhood */}
      <circle className="pin-body" r={store.format === "flagship" ? 14.5 : 12.5} fill={color} stroke="var(--stone-soft)" strokeWidth="3.2" />
      {store.format === "hospital"
        ? <path d="M-4 0H4M0 -4V4" stroke="var(--stone-soft)" strokeWidth="2.8" strokeLinecap="round" />
        : <circle r={store.format === "flagship" ? 5 : 4} fill="var(--stone-soft)" />}
      {showLabel && (
        <text className="pin-label" x={lp.dx} y={lp.dy} textAnchor={lp.a}
          style={{ fontFamily: "var(--font-sans)", fontSize: 18, fontWeight: 600, letterSpacing: "-0.01em",
            fill: "var(--ink)", paintOrder: "stroke", stroke: "var(--stone)", strokeWidth: 4, strokeLinejoin: "round" }}>
          {store.locality}
        </text>
      )}
    </g>
  );
}

/* ===================== interactive map (Dashboard hero) ================= */
function KolkataMap() {
  const app = window.useApp();
  const vpRef = useRefM(null);
  const [pan, setPan] = useStateM({ x: 0, y: 0 });
  const [scale, setScale] = useStateM(1);
  const [hover, setHover] = useStateM(null);
  const [dragging, setDragging] = useStateM(false);
  const [hintGone, setHintGone] = useStateM(false);
  const drag = useRefM(null);
  const moved = useRefM(false);
  const focusId = app.loopFocus && app.loopFocus.kind === "pin" ? app.loopFocus.id : null;

  const MINS = 0.75, MAXS = 2.4;
  const clamp = (x, y, s = scale) => {
    const vp = vpRef.current; const cw = vp ? vp.clientWidth : 1100, ch = vp ? vp.clientHeight : 700;
    return { x: Math.min(0, Math.max(cw - MAPW * s, x)), y: Math.min(0, Math.max(ch - MAPH * s, y)) };
  };
  const centerOn = (px, py, s = scale) => {
    const vp = vpRef.current; const cw = vp ? vp.clientWidth : 1100, ch = vp ? vp.clientHeight : 700;
    return clamp(cw / 2 - px * s, ch / 2 - py * s, s);
  };
  /* zoom toward the viewport center, keeping that point fixed */
  const zoomTo = (next) => {
    const s = Math.min(MAXS, Math.max(MINS, +(+next).toFixed(3)));
    if (s === scale) return;
    const vp = vpRef.current; const cw = vp ? vp.clientWidth : 1100, ch = vp ? vp.clientHeight : 700;
    const cx = (cw / 2 - pan.x) / scale, cy = (ch / 2 - pan.y) / scale;
    setScale(s);
    setPan(clamp(cw / 2 - cx * s, ch / 2 - cy * s, s));
  };

  useLayoutEffect(() => { const p = pinXY(D.storeById.str_parkst01); setPan(centerOn(p.x, p.y + 120)); }, []);
  useEffectM(() => {
    if (focusId && D.storeById[focusId]) { const p = pinXY(D.storeById[focusId]); setPan(centerOn(p.x, p.y)); }
  }, [focusId]);

  const onDown = (e) => {
    drag.current = { sx: e.clientX, sy: e.clientY, px: pan.x, py: pan.y };
    moved.current = false; setDragging(true); setHover(null);
    e.currentTarget.setPointerCapture && e.currentTarget.setPointerCapture(e.pointerId);
  };
  const onMove = (e) => {
    if (!drag.current) return;
    const dx = e.clientX - drag.current.sx, dy = e.clientY - drag.current.sy;
    if (Math.abs(dx) > 4 || Math.abs(dy) > 4) { moved.current = true; if (!hintGone) setHintGone(true); }
    setPan(clamp(drag.current.px + dx, drag.current.py + dy));
  };
  const onUp = () => { drag.current = null; setDragging(false); };

  const kpis = (() => {
    const stage = app.stage;
    const atRisk = D.stores.filter((s) => { const st = window.storeStatusAt(s, stage); return st === "atrisk" || st === "critical"; }).length;
    return [
      { k: "Stores at risk", v: atRisk, m: atRisk ? "Need attention" : "Chain steady", accent: !!atRisk },
      { k: "Alerts open", v: window.alertsAt(stage).length, m: "Store-raised" },
      { k: "Expiry · 30d", v: window.inr(D.expiryAtRisk), m: "1 batch flagged", small: true },
      { k: "Pilots", v: 1, m: "Rehydra ORS" },
    ];
  })();

  return (
    <div className="map-viewport" ref={vpRef}
      onPointerDown={onDown} onPointerMove={onMove} onPointerUp={onUp} onPointerLeave={onUp}
      style={{ cursor: dragging ? "grabbing" : "grab" }}>
      <div className="map-pan" style={{ transform: `translate(${pan.x}px, ${pan.y}px) scale(${scale})`, transformOrigin: "0 0", transition: dragging ? "none" : "transform 460ms var(--ease)" }}>
        <svg width={MAPW} height={MAPH} viewBox={`0 0 ${MAPW} ${MAPH}`} style={{ display: "block" }}>
          <Basemap />
          {D.stores.filter((s) => s.id !== "str_barasa01").map((s) => {
            const status = window.storeStatusAt(s, app.stage);
            return <Pin key={s.id} store={s} status={status} showLabel focused={focusId === s.id}
              onEnter={setHover} onLeave={() => setHover(null)}
              onClick={(st) => { if (!moved.current) app.nav({ name: "store", id: st.id }); }} />;
          })}
        </svg>
        {hover && (() => {
          const p = pinXY(hover); const status = window.storeStatusAt(hover, app.stage);
          return (
            <div className="peek" style={{ left: p.x, top: p.y }}>
              <div className="pk-name">{hover.locality}</div>
              <div className="pk-meta">{D.FORMAT[hover.format].label} · {hover.region}</div>
              <div className="pk-row"><span className="dot" style={{ background: STATUS_COLOR[status] }} />{D.HEALTH[status].label}
                {hover.openAlerts > 0 && <span className="pk-al">· {hover.openAlerts} open alert{hover.openAlerts > 1 ? "s" : ""}</span>}</div>
              <div className="pk-mgr">Manager · {hover.manager}</div>
            </div>
          );
        })()}
      </div>

      {/* ---------- floating HUD (does not pan) ---------- */}
      <div className="map-hud-top">
        <div className="hud-meta">
          <div className="hud-date">{window.longDate(D.TODAY)}</div>
          <div className="hud-sub">Banyan Pharmacy · <span>10 stores across Kolkata</span></div>
        </div>
        <div className="hud-kpis">
          {kpis.map((c) => (
            <div className={cx("hud-kpi", c.accent && "accent")} key={c.k}>
              <div className="hk-k">{c.k}</div>
              <div className={cx("hk-v", c.small && "sm", c.accent && "clay")}>{c.v}</div>
              <div className="hk-m">{c.m}</div>
            </div>
          ))}
        </div>
      </div>

      <button className="map-chip-north" onClick={() => app.nav({ name: "store", id: "str_barasa01" })}>
        <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M12 19V5M5 12l7-7 7 7" /></svg>
        Barasat · satellite store
      </button>

      <div className="map-legend">
        <div className="lg-t">Shelf-health · estimate</div>
        <div className="lg-items">
          <span className="lg-item"><span className="lg-sw" style={{ background: "var(--green)" }} />Healthy</span>
          <span className="lg-item"><span className="lg-sw" style={{ background: "var(--amber)" }} />Watch</span>
          <span className="lg-item"><span className="lg-sw" style={{ background: "var(--red)" }} />At-risk</span>
          <span className="lg-item"><span className="lg-sw" style={{ background: "var(--clay)" }} />Critical</span>
        </div>
        <div className="lg-t" style={{ marginTop: 9 }}>Format</div>
        <div className="lg-items">
          <span className="lg-item">
            <svg width="13" height="13" viewBox="0 0 13 13"><circle cx="6.5" cy="6.5" r="5.6" fill="var(--mute)" /><path d="M4.3 6.5h4.4M6.5 4.3v4.4" stroke="var(--stone-soft)" strokeWidth="1.5" strokeLinecap="round" /></svg>
            Hospital</span>
          <span className="lg-item">
            <svg width="13" height="13" viewBox="0 0 13 13"><circle cx="6.5" cy="6.5" r="6" fill="var(--mute)" /><circle cx="6.5" cy="6.5" r="2.4" fill="var(--stone-soft)" /></svg>
            Flagship</span>
          <span className="lg-item">
            <svg width="13" height="13" viewBox="0 0 13 13"><circle cx="6.5" cy="6.5" r="4.8" fill="var(--mute)" /><circle cx="6.5" cy="6.5" r="1.9" fill="var(--stone-soft)" /></svg>
            Neighbourhood</span>
        </div>
      </div>

      <div className="map-zoom">
        <button className="mz-btn" aria-label="Zoom in" disabled={scale >= MAXS}
          onClick={() => zoomTo(scale * 1.35)}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M12 5v14M5 12h14" /></svg>
        </button>
        <button className="mz-btn" aria-label="Zoom out" disabled={scale <= MINS}
          onClick={() => zoomTo(scale / 1.35)}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M5 12h14" /></svg>
        </button>
      </div>

      <div className="map-compass">
        <svg width="44" height="44" viewBox="0 0 44 44">
          <circle cx="22" cy="22" r="20" fill="rgba(251,248,242,0.9)" stroke="var(--rule)" />
          <path d="M22 7 L27 22 L22 19 L17 22 Z" fill="var(--clay)" />
          <path d="M22 37 L17 22 L22 25 L27 22 Z" fill="var(--mute)" />
          <text x="22" y="15" textAnchor="middle" style={{ fontFamily: "var(--font-sans)", fontSize: 9, fontWeight: 700, fill: "var(--ink)" }}>N</text>
        </svg>
      </div>

      {!hintGone && <div className="map-hint">Drag to explore · tap a store</div>}
    </div>
  );
}

/* ---- mini locator (store detail; static, fit-to-view) ------------------ */
function MapLocator({ store }) {
  const app = window.useApp();
  const target = pinXY(store);
  const vw = 760, vh = 520;
  const vx = Math.max(0, Math.min(MAPW - vw, target.x - vw / 2));
  const vy = Math.max(0, Math.min(MAPH - vh, target.y - vh / 2));
  return (
    <div className="locator">
      <svg viewBox={`${vx} ${vy} ${vw} ${vh}`} role="img" aria-label={`Location of ${store.locality}`} style={{ display: "block", width: "100%", height: "auto" }}>
        <Basemap />
        {D.stores.filter((s) => s.id !== "str_barasa01").map((s) => {
          const status = window.storeStatusAt(s, app.stage);
          const sel = s.id === store.id;
          return <Pin key={s.id} store={s} status={status} dim={!sel} showLabel={sel} focused={sel} />;
        })}
      </svg>
    </div>
  );
}

window.KolkataMap = KolkataMap;
window.MapLocator = MapLocator;
window.mapProj = proj;
