/* ── MAP PEEK ──────────────────────────────────────────────────────────
   The map is a layer over Browse Rentals, never a second browsing mode.
   The grid stays the page; the map slides in beside it (laptop) or over it
   (phone), shows the homes that are already on screen, and goes away again
   leaving the results exactly as they were.

   Everything here is built from the same tokens as the rest of KULI — the
   2px corner, the hairline, the foam/gold-black grounds — so the panel
   reads as part of the site and not as an embedded map product. The only
   thing Leaflet is allowed to bring with it is the tiles.               */

:root {
  /* How much room the drawer takes on a laptop. The grid keeps the rest. */
  --mp-w: clamp(360px, 42vw, 560px);
}

/* ── The trigger ───────────────────────────────────────────────────────
   One action, sitting with the results count in the filter bar — so it
   travels into the navbar with the rest of the controls when the bar docks
   and stays reachable the whole way down the page. Deliberately NOT a
   Grid/Map segmented control: there is one way to browse, and this offers
   to show you where those homes are. */
.mp-trigger {
  display: inline-flex; align-items: center; gap: 8px;
  height: 42px; padding: 0 14px;
  border: 1px solid var(--hairline); border-radius: 2px;
  background: transparent; color: var(--ink);
  font-family: inherit; font-size: 13.5px; font-weight: 500;
  white-space: nowrap; cursor: pointer;
  transition: border-color var(--trans-fast), color var(--trans-fast), background var(--trans-fast);
}
.mp-trigger:hover { border-color: var(--bronze); }
.mp-trigger[hidden] { display: none; }
.mp-trigger svg { width: 15px; height: 15px; flex-shrink: 0; stroke: var(--bronze); fill: none; stroke-width: 1.7; }
.mp-trigger:hover svg { stroke: var(--ink); }
.mp-trigger .mp-t-count {
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
  color: var(--bronze);
}
.mp-trigger.on { border-color: var(--bronze); background: rgba(126,123,120,0.14); }
.mp-trigger.on svg { stroke: var(--ink); }

/* The full sentence when there is room for it, the short form when there
   isn't — same button, so the phrasing never becomes a second control.
   Docked in the navbar the row is tight, so it always reads short there. */
.mp-t-short { display: none; }
/* The filter row is now the same width on the page as it is in the navbar
   (css/pages.css), so the handover moves nothing sideways — which also means
   the page has the navbar's room, not the page's. The long phrasing no longer
   fits either seat, so it gives way earlier. */
@media (max-width: 1420px) { .mp-t-long { display: none; } .mp-t-short { display: inline; } }
.nav-dock .mp-t-long { display: none; }
.nav-dock .mp-t-short { display: inline; }

/* ── The floating trigger on a phone ──────────────────────────────────
   The filter bar on a phone is a sideways-scrolling row and a button at the
   end of it would be a button nobody finds, so the phone gets this instead. */
.mp-fab {
  position: fixed; z-index: 470;
  left: 50%; transform: translateX(-50%);
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  display: none; align-items: center; gap: 8px;
  height: 44px; padding: 0 18px;
  border-radius: 2px; border: 1px solid var(--hairline);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: 13.5px; font-weight: 600;
  box-shadow: var(--shadow-md);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  transition: opacity var(--trans-med), transform var(--trans-med);
}
.mp-fab svg { width: 15px; height: 15px; stroke: var(--ink); fill: none; stroke-width: 1.7; }
.mp-fab .mp-t-count { font-family: var(--font-data); font-variant-numeric: tabular-nums; color: var(--bronze); }
@media (max-width: 900px) {
  /* One trigger per screen. On a phone the filter bar is a sideways-scrolling
     row, so the action moves out of it and becomes the floating button. */
  .mp-trigger { display: none !important; }
  .mp-fab.live { display: inline-flex; }
  .mp-fab.away { opacity: 0; pointer-events: none; transform: translateX(-50%) translateY(12px); }
}

/* ── The panel ─────────────────────────────────────────────────────────
   One element, two shapes. On a laptop it is a drawer pinned under the
   navbar; on a phone it is a sheet that comes up over the listings. */
.mp-panel {
  position: fixed;
  background: var(--bg);
  display: flex; flex-direction: column;
  visibility: hidden;
  z-index: 480;
}
.mp-panel.shown { visibility: visible; }

/* Laptop — a drawer beside the grid, under the header, never over it.

   It slides on a transform, which the compositor can carry on its own, and
   the page below makes room on the physical padding with the Dhivehi side
   spelled out separately. Both are deliberate: an animated `inset-inline-end`
   would move the drawer by re-laying-out the page on every frame, and the
   logical padding longhands are the shakier half of the two engines'
   transition support. The written direction is still honoured — it is just
   stated rather than inferred. */
.mp-panel.mp-desk {
  top: var(--nav-h); bottom: 0;
  inset-inline-end: 0;
  width: var(--mp-w);
  border-inline-start: 1px solid var(--hairline);
  transform: translateX(100%);
  transition: transform var(--trans-med), top var(--trans-med), visibility 0s linear var(--trans-med);
}
body.dv .mp-panel.mp-desk { transform: translateX(-100%); }
.mp-panel.mp-desk.shown,
body.dv .mp-panel.mp-desk.shown { transform: translateX(0); transition-delay: 0s; }

/* The page makes room rather than being covered — the listings stay
   readable, which is the whole point of peeking instead of switching. */
#main-content, .site-footer { transition: padding-right var(--trans-med), padding-left var(--trans-med); }
body.mp-open #main-content,
body.mp-open .site-footer { padding-right: var(--mp-w); }
body.dv.mp-open #main-content,
body.dv.mp-open .site-footer { padding-right: 0; padding-left: var(--mp-w); }
/* Fewer, narrower columns instead of squeezed ones. */
body.mp-open .listings-grid { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }

/* Phone — a sheet with three resting heights, dragged by its handle. */
.mp-panel.mp-sheet {
  left: 0; right: 0; bottom: 0;
  height: 92vh; height: 92dvh;
  border-top: 1px solid var(--hairline);
  border-radius: 2px 2px 0 0;
  box-shadow: 0 -18px 44px rgba(0,0,0,0.30);
  transform: translateY(100%);
  z-index: 520;   /* over the navbar: at full height it owns the screen */
  transition: transform var(--trans-med);
}
.mp-panel.mp-sheet.dragging { transition: none; }

/* ── Head ── */
.mp-head {
  flex: 0 0 auto; position: relative;
  padding: 14px 18px 12px;
  border-bottom: 1px solid var(--hairline);
  display: flex; align-items: baseline; gap: 10px;
}
.mp-title { font-family: 'Newsreader', serif; font-size: 19px; color: var(--ink); line-height: 1.2; }
/* "Showing 8 of 12 homes on the map." — said here, quietly, rather than
   left for the renter to notice by counting pins. */
.mp-note {
  font-size: 12.5px; color: var(--muted);
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
}
.mp-close {
  margin-inline-start: auto; flex-shrink: 0;
  width: 32px; height: 32px; border-radius: 2px;
  display: flex; align-items: center; justify-content: center;
  color: var(--bronze); border: 1px solid transparent;
  transition: color var(--trans-fast), border-color var(--trans-fast);
}
.mp-close:hover { color: var(--ink); border-color: var(--hairline); }
.mp-close svg { width: 14px; height: 14px; stroke: currentColor; stroke-width: 1.8; fill: none; }

/* The grab handle only exists on the sheet. */
.mp-grip { display: none; }
.mp-sheet .mp-head { padding-top: 20px; cursor: grab; touch-action: none; -webkit-user-select: none; user-select: none; }
.mp-sheet .mp-head:active { cursor: grabbing; }
.mp-sheet .mp-grip {
  display: block; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
  width: 38px; height: 4px; border-radius: 100px; background: var(--hairline);
}

/* ── Body ── */
.mp-body { flex: 1 1 auto; position: relative; min-height: 0; display: flex; flex-direction: column; }
/* On the sheet the body is sized to the band the renter can actually see
   (js sets --mp-vis on every snap), so the card rail is at the bottom of
   the map rather than at the bottom of a sheet that runs off screen. */
.mp-sheet .mp-body { flex: 0 0 auto; height: var(--mp-vis, 55vh); overflow: hidden; }
.mp-map { flex: 1 1 auto; min-height: 0; background: var(--surface); }
/* Own stacking context so Leaflet's internal z-indexes stay inside the map */
.mp-map { position: relative; z-index: 0; }

/* The basemap is CARTO's Positron in the light theme and Dark Matter in the
   dark one — two purpose-drawn pale maps rather than one map with a CSS
   invert over it. The invert trick (still used on the listing-detail map)
   turns land the colour of a bruise and makes the sea glow; these two were
   drawn to sit under markers and stay quiet, which is exactly the job here.
   js/map-peek.js swaps the layer when the theme changes. */
.mp-map .leaflet-tile-pane { filter: none; }

/* Leaflet's own chrome, brought down to KULI's volume. */
.mp-map .leaflet-container { font-family: 'Instrument Sans', sans-serif; background: var(--surface); }
.mp-map .leaflet-control-attribution {
  background: rgba(0,0,0,0.35); color: var(--muted);
  font-size: 10px; padding: 2px 6px; border-radius: 2px;
}
[data-theme="light"] .mp-map .leaflet-control-attribution { background: rgba(255,255,255,0.72); }
.mp-map .leaflet-control-attribution a { color: var(--bronze); }
.mp-map .leaflet-bar {
  border: 1px solid var(--hairline); border-radius: 2px; box-shadow: var(--shadow-sm); overflow: hidden;
}
.mp-map .leaflet-bar a {
  background: var(--surface); color: var(--ink);
  width: 30px; height: 30px; line-height: 30px;
  border-bottom-color: var(--hairline);
}
.mp-map .leaflet-bar a:hover { background: var(--bg); color: var(--ink); }

/* ── Markers ───────────────────────────────────────────────────────────
   A pin drop in KULI's oxblood carrying the KULI mark, on a pale basemap.
   The mark is the real logo file, not a copy of it — swap the SVG in
   /img and every pin on the map changes with it.

   Everything is sized off --mp-pin, so the pin, the mark inside it and the
   count on a cluster stay in proportion to each other at any size. The pin
   is oxblood in both themes, which is why it always takes the white mark.

   Three states, and none of them changes the pin's size: the difference is
   depth and a lift. Markers that grow under the pointer make the whole map
   twitch as you cross it. */
.mp-pin { width: 0 !important; height: 0 !important; }
.mp-marker {
  --mp-pin: 30px;
  position: absolute;
  /* The point of a pin is its tip, so the tip sits on the coordinate and
     the body stands above it. */
  transform: translate(-50%, -100%);
  width: var(--mp-pin);
  height: calc(var(--mp-pin) * 1.286);
  display: block;
  transition: transform var(--trans-fast), filter var(--trans-fast);
  filter: drop-shadow(0 2px 3px rgba(13,11,11,0.34));
  will-change: transform;
}
.mp-drop { display: block; width: 100%; height: 100%; }
.mp-drop path { fill: var(--accent); }
/* The logo, centred on the head of the pin rather than on the whole pin. */
.mp-pin-logo {
  position: absolute; left: 50%; top: calc(var(--mp-pin) * 0.465);
  transform: translate(-50%, -50%);
  height: calc(var(--mp-pin) * 0.50);
  width: auto; pointer-events: none;
}
/* A pin under the pointer answers for itself in CSS. The .hot class below is
   the other direction — the grid telling the map which card you are on —
   and redrawing every marker just to light the one already under the
   pointer would drop the hover the moment it was applied. */
.mp-pin:hover { z-index: 620 !important; }
.mp-pin:hover .mp-marker,
.mp-marker.hot {
  transform: translate(-50%, -100%) translateY(-3px);
  filter: drop-shadow(0 5px 7px rgba(13,11,11,0.38));
}
.mp-marker.sel {
  transform: translate(-50%, -100%) translateY(-3px);
  filter: drop-shadow(0 6px 9px rgba(13,11,11,0.44));
}
.mp-marker.sel .mp-drop path { fill: var(--accent-deep); }
.mp-pin.is-sel { z-index: 640 !important; }

/* A cluster is the same pin carrying a number instead of the mark, so a
   group of homes still reads as homes. */
.mp-marker.mp-cluster { --mp-pin: 34px; }
.mp-pin-count {
  position: absolute; left: 50%; top: calc(var(--mp-pin) * 0.455);
  transform: translate(-50%, -50%);
  color: #F4F1EC; pointer-events: none;
  font-family: var(--font-data); font-variant-numeric: tabular-nums;
  font-size: calc(var(--mp-pin) * 0.42); font-weight: 700; line-height: 1;
  letter-spacing: -0.02em;
}

/* ── The hover tag ─────────────────────────────────────────────────────
   What a home is and what it costs, on the way past. Two lines, no
   chrome, no photo — the full card is one click further in and this is
   only here to save that click while you are scanning. */
.mp-tip {
  position: absolute; z-index: 630;
  transform: translate(-50%, 6px);
  padding: 9px 13px 10px; border-radius: 2px;
  background: var(--surface); border: 1px solid var(--hairline);
  box-shadow: var(--shadow-md);
  pointer-events: none; white-space: nowrap;
}
.mp-tip-title { font-size: 13px; font-weight: 600; color: var(--ink); line-height: 1.25; }
.mp-tip-price {
  font-family: var(--font-num); font-size: 15px; color: var(--ink);
  line-height: 1.25; margin-top: 1px;
}
.mp-tip-price span { font-family: 'Instrument Sans', sans-serif; font-size: 11.5px; color: var(--muted); }

/* ── Show all ──────────────────────────────────────────────────────────
   Only when the map is genuinely hiding some of the results, and it moves
   the map alone — the search is untouched. */
.mp-all {
  position: absolute; z-index: 610;
  left: 14px; bottom: 14px;
  display: inline-flex; align-items: center; gap: 7px;
  height: 30px; padding: 0 12px;
  border-radius: 2px; border: 1px solid var(--hairline);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: 12px; font-weight: 600;
  box-shadow: var(--shadow-sm);
  opacity: 0; pointer-events: none;
  transition: opacity var(--trans-med), border-color var(--trans-fast);
}
.mp-all.live { opacity: 1; pointer-events: auto; }
.mp-all:hover { border-color: var(--bronze); }
.mp-sheet .mp-all { bottom: 14px; }

/* ── Marker preview ────────────────────────────────────────────────────
   The whole card opens the listing, so there is no second "Open listing"
   button to look at. The link wraps everything and carries its own
   accessible name, which is what a keyboard or a screen reader needs. */
.mp-pop .leaflet-popup-content-wrapper {
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: 2px;
  box-shadow: var(--shadow-md); padding: 0;
}
.mp-pop .leaflet-popup-content { margin: 0; width: 244px !important; line-height: 1.5; }
.mp-pop .leaflet-popup-tip { background: var(--surface); border: 1px solid var(--hairline); box-shadow: none; }
.mp-pop .leaflet-popup-close-button { display: none; }

.mp-prev { display: block; color: inherit; }
.mp-prev-img { aspect-ratio: 16 / 10; overflow: hidden; background: var(--bg); }
.mp-prev-img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.mp-prev:hover .mp-prev-img img { transform: scale(1.04); }
.mp-prev-body { padding: 12px 14px 13px; }
.mp-prev-price { font-family: 'Newsreader', serif; font-size: 19px; color: var(--ink); line-height: 1.15; }
.mp-prev-price span { font-size: 12px; color: var(--muted); font-family: 'Instrument Sans', sans-serif; }
.mp-prev-title {
  font-size: 13.5px; font-weight: 600; color: var(--ink); margin-top: 4px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.mp-prev-where { font-size: 12.5px; color: var(--muted); margin-top: 3px; }
.mp-prev-meta {
  display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px;
}
.mp-prev-meta span {
  font-size: 11px; font-weight: 500; color: var(--muted);
  border: 1px solid var(--hairline); border-radius: 2px; padding: 3px 7px;
}
/* Smart location context — built only from what the listing already says.
   No walking times, no invented landmarks. */
.mp-prev-ctx {
  margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--hairline);
  font-size: 12px; color: var(--muted); line-height: 1.5;
}
.mp-prev-ctx strong { color: var(--ink); font-weight: 600; }
.mp-prev-ctx em { display: block; font-style: normal; color: var(--bronze); margin-top: 2px; }

/* ── Show homes in this area ──────────────────────────────────────────
   Moving the map changes nothing on its own. This appears once the view has
   genuinely moved on, and the results only follow when it is pressed. */
.mp-area {
  position: absolute; z-index: 610;
  top: 14px; left: 50%; transform: translateX(-50%) translateY(-8px);
  display: inline-flex; align-items: center; gap: 7px;
  height: 34px; padding: 0 15px;
  border-radius: 2px; border: 1px solid var(--hairline);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: 12.5px; font-weight: 600;
  box-shadow: var(--shadow-md);
  opacity: 0; pointer-events: none;
  transition: opacity var(--trans-med), transform var(--trans-med), border-color var(--trans-fast);
}
.mp-area.live { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
.mp-area:hover { border-color: var(--bronze); }
.mp-area svg { width: 13px; height: 13px; stroke: var(--bronze); fill: none; stroke-width: 1.8; }

/* ── Empty states ─────────────────────────────────────────────────────
   A map with nothing on it tells the renter nothing, so it is replaced by
   the sentence that does. */
.mp-empty {
  position: absolute; inset: 0; z-index: 605;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 40px 32px; text-align: center;
  background: var(--bg);
}
.mp-empty[hidden] { display: none; }
.mp-empty-title { font-family: 'Newsreader', serif; font-size: 20px; color: var(--ink); }
.mp-empty-desc { font-size: 13.5px; color: var(--muted); max-width: 300px; line-height: 1.6; }

/* ── The card rail (phone) ────────────────────────────────────────────
   The homes inside the map's current view, in the order the results are
   already in. Swipe it, and the markers follow; tap a marker, and it
   scrolls to the one you tapped — inside the rail, never the page. */
.mp-rail { display: none; }
.mp-sheet .mp-rail {
  display: flex; gap: 10px;
  flex: 0 0 auto;
  padding: 12px 14px calc(14px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--hairline);
  background: var(--bg);
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  scrollbar-width: none;
}
.mp-sheet .mp-rail::-webkit-scrollbar { display: none; }
.mp-rail:empty { display: none !important; }

.mp-rcard {
  flex: 0 0 auto; width: 232px; scroll-snap-align: start;
  display: flex; gap: 10px; padding: 8px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 2px;
  color: inherit;
  transition: border-color var(--trans-fast);
}
.mp-rcard.sel { border-color: var(--accent); }
.mp-rcard-img { flex: 0 0 62px; height: 62px; border-radius: 2px; overflow: hidden; background: var(--bg); }
.mp-rcard-img img { width: 100%; height: 100%; object-fit: cover; }
.mp-rcard-body { min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.mp-rcard-price { font-family: 'Newsreader', serif; font-size: 16px; color: var(--ink); line-height: 1.1; }
.mp-rcard-title {
  font-size: 12px; font-weight: 600; color: var(--ink); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mp-rcard-where { font-size: 11.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Grid ↔ map ───────────────────────────────────────────────────────
   Hovering a card marks its marker and vice versa. The card's own hover
   lift is left alone — this only adds the line that says "this one". */
.listing-card.mp-hi { border-color: var(--bronze); }
.listing-card.mp-sel { border-color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
  .mp-panel, #main-content, .site-footer, .mp-area, .mp-fab { transition: none !important; }
}
