/* The /s map: the container and its panel chrome, the pin and cluster
   layers, the mobile drawer and the place rows. Split out of
   custom-tailwind.css (2026-09-12): 17KB of render-blocking CSS on every page
   in the app for one surface that lives at one URL.

   Loaded by `pageStyles: ['mapCss.css']` from `_renderMap` in
   controllers/search.js, the only handler that renders it.

   The pin family and the scope toggle are deliberately NOT here: the
   composer's location picker builds a `.map-pin`, and the RESULTS page renders
   the scope toggle, both on pages with no map. They stayed in
   custom-tailwind.css. */

/* ── Map page ── */

.map-container {
  padding: 0.5rem;
  padding-left: 0;
  height: 100dvh;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

@media (max-width: 1023px) {
  .map-container {
    padding-left: 0.5rem;
    padding-top: 0;
  }
}

.map-page {
  display: flex;
  flex: 1;
  min-height: 0;
  border-radius: 1rem;
  overflow: hidden;
  border: 1px solid var(--color-gray-700, var(--color-gray-700));
}

.map-area {
  flex: 1;
  min-width: 0;
  position: relative;
}

/* The bar/map seam, drawn inside the map area (see .map-topbar). Full width
   normally; with the detail panel open it stops at the panel's left edge,
   whose border-left continues the line down — the map is outlined on its
   top + right, and the bar + panel merge into one chrome region. */
.map-area::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--color-gray-700, var(--color-gray-700));
  z-index: 2;
  pointer-events: none;
  transition: right 0.25s ease;
}
@media (min-width: 1300px) {
  /* Keep in step with .map-detail-panel's width. */
  .map-area:has(.map-detail-panel.is-open)::before {
    right: min(440px, 90%);
  }
}

.map-area-inner {
  width: 100%;
  height: 100%;
  background-color: var(--vb, #1a1a2e);
}

/* Panel bar — ONE bar above the map at every width (2026-07-31 redesign;
   the 650px list sidebar is gone). Visually the old mobile header,
   promoted to universal. */
.map-topbar {
  padding: 0.5rem 1rem;
  background: var(--vb, var(--color-gray-900));
  border: 1px solid var(--color-gray-700, var(--color-gray-700));
  /* No bottom border here: the bar/map seam is drawn INSIDE the map area
     (.map-area::before) so it can stop where the open detail panel begins
     — the bar and the panel then read as one continuous chrome region,
     with the border tracing just the map's top and right edges. */
  border-bottom: none;
  border-radius: 1rem 1rem 0 0;
}

.map-topbar + .map-page {
  /* Square the TOP corners only — they join with the bar above, which
   * provides the rounded top. The bottom corners keep the 1rem radius so
   * the map's bottom edge stays rounded against the page background. */
  border-radius: 0 0 1rem 1rem;
  border-top: none;
}

.map-panel-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* The scope control is NOT here: partials/search/header.ejs renders it on the
   RESULTS page too, which is not a map. It lives in custom-tailwind.css
   (.srch-scope*). */

/* Type filter icons */
.map-type-filters {
  display: flex;
  gap: 0.25rem;
  flex-shrink: 0;
}

.map-type-btn {
  width: 1.75rem;
  height: 1.75rem;
  color: var(--vc-53, var(--color-gray-500));
  background: transparent;
  border: 1px solid transparent;
  border-radius: 0.375rem;
  cursor: pointer;
  /* No transition: snap the active highlight (avoids the theme-swap flicker on
   * a scope change, which also clears the type filter). */
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.map-type-icon {
  display: block;
  width: 1.125rem;
  height: 1.125rem;
  background: currentColor;
  mask-image: var(--icon);
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-image: var(--icon);
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
}

.map-type-btn:hover {
  color: var(--vtext, var(--color-gray-300));
  background: var(--vc-15, var(--color-gray-700));
}

.map-type-btn.active {
  background: var(--vc, var(--color-teal-500));
  color: var(--vc-text, #fff);
  border-color: var(--vc, var(--color-teal-500));
}

.map-panel-right {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  margin-left: auto;
  flex-shrink: 0;
}

.map-refresh-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: none;
  border: none;
  border-radius: 0.375rem;
  color: rgb(103, 116, 130);
  cursor: pointer;
  transition: color 0.15s, background 0.15s, transform 0.1s;
}

.map-refresh-btn:hover {
  color: rgb(207, 214, 220);
  background: rgb(51, 66, 83);
}

.map-refresh-btn:active {
  transform: scale(0.85);
  background: rgb(72, 86, 101);
}

.map-refresh-btn.loading,
.map-refresh-btn.cooldown {
  pointer-events: none;
}

.map-refresh-btn.loading .map-refresh-icon,
.map-refresh-btn.cooldown .map-refresh-icon {
  opacity: 0.35;
}

.map-refresh-icon {
  display: block;
  width: 1.25rem;
  height: 1.25rem;
  background: currentColor;
  mask-image: var(--icon);
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-image: var(--icon);
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
}

/* The selected post's card (buildCardNode stamps .map-post-card on the
   detail node mounted in the panel/drawer). */
.map-post-card {
  /* `position: relative` + isolation: a stacking context so inner poll /
   * photoset chrome layers behave, and the :has() lift below can raise the
   * card when a picker popover is open. */
  position: relative;
  isolation: isolate;
}
.map-post-card:has(.v-picker-menu:not(.hidden)) {
  z-index: 1;
}
.map-post-card .post-content {
  font-size: 0.875rem;
  line-height: 1.5;
}

/* Selected-post detail chrome, shared by the desktop panel and the mobile
   drawer: count + prev/next steppers + close. */
.map-detail-head {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 10px;
  border-bottom: 1px solid var(--vc-15, rgba(255, 255, 255, 0.12));
}
.map-detail-count {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--vc-53, var(--color-gray-500));
  padding-left: 4px;
}
.map-detail-navs { display: flex; gap: 2px; }
.map-detail-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 0.5rem;
  background: transparent;
  color: var(--vt-muted, var(--color-gray-400));
  cursor: pointer;
}
.map-detail-nav svg { width: 17px; height: 17px; }
.map-detail-nav:hover { background: var(--vc-10, rgba(255, 255, 255, 0.08)); color: var(--vtext, #fff); }
.map-detail-nav[disabled] { opacity: 0.35; pointer-events: none; }
.map-detail-close { margin-left: 2px; }

/* Panel-bar variant of the selection controls: right-aligned in the row,
   ABOVE the open panel. Space is reserved permanently (opacity, never
   display) so toggling can't reflow the filter icons; visibility fades and
   slides in step with the panel's own 0.25s transition. The drawer keeps
   its in-sheet head under 1300px. */
.map-topbar .map-detail-head {
  margin-left: auto;
  border-bottom: none;
  padding: 0;
  opacity: 0;
  transform: translateX(8px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.map-topbar .map-detail-count { flex: none; padding-left: 0; }
.map-container:has(.map-detail-panel.is-open) .map-topbar .map-detail-head {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}
@media (max-width: 1299px) {
  .map-topbar .map-detail-head { display: none; }
}

/* Desktop selected-post panel: overlays the right edge of the map area
   (the map stays full-bleed beneath; no canvas resize on open). Mobile
   (<=1299px) uses the drawer instead. */
.map-detail-panel { display: none; }
@media (min-width: 1300px) {
  .map-detail-panel {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 5;
    width: min(440px, 90%);
    background: var(--vb, var(--color-gray-900));
    border-left: 1px solid var(--color-gray-700, var(--color-gray-700));
    transform: translateX(102%);
    visibility: hidden;
    transition: transform 0.25s ease, visibility 0.25s;
  }
  .map-detail-panel.is-open {
    transform: translateX(0);
    visibility: visible;
  }
  .map-detail-panel .map-detail-content {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Reserve the scrollbar lane: without this, stepping between short and
       tall cards jitters the card width as the scrollbar appears/vanishes. */
    scrollbar-gutter: stable;
    padding: 0.5rem;
  }
  .map-detail-panel .map-post-card { margin-bottom: 0; width: 100%; }
  /* The panel opens from the post's own marker; the find icon is noise. */
  .map-detail-panel .post-find-icon { display: none; }
}

/* Loading shimmer for a selected card being fetched (panel + drawer). */
.map-detail-loading,
.map-drawer-loading {
  border-radius: 12px;
  background: linear-gradient(
    100deg,
    var(--vc-7, rgba(255, 255, 255, 0.04)) 30%,
    var(--vc-20, rgba(255, 255, 255, 0.09)) 50%,
    var(--vc-7, rgba(255, 255, 255, 0.04)) 70%
  );
  background-size: 200% 100%;
  animation: mapPeekShimmer 1.2s ease-in-out infinite;
}
.map-detail-loading { height: 50%; margin: 0.5rem; }
.map-drawer-loading { height: 40vh; margin: 0.5rem; }
@keyframes mapPeekShimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .map-detail-loading, .map-drawer-loading { animation: none; }
}

/* The pin family is NOT here: it is shared, so it stayed in
   custom-tailwind.css. See the note beside it there. */
/* Cluster bubbles — the zoomed-out count mode (mapClusters.js). The outer
 * box is the TRANSPARENT collision frame (--d = disc + CLUSTER_GAP per side;
 * it decides when MapKit merges two bubbles), the disc is the visible bubble
 * sized by count (--disc). Tokens only: cluster mode is global, so --vc is
 * unset and these fall back to the house accent. */
.map-cluster {
  width: var(--d);
  height: var(--d);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.map-cluster-disc {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: var(--disc);
  height: var(--disc);
  border-radius: 50%;
  background: var(--vc, var(--color-teal-500));
  opacity: 0.9;
  border: 2px solid rgba(255, 255, 255, 0.9);
  color: var(--vc-text, #fff);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
  text-shadow: 0 0 2px var(--color-teal-700);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
  user-select: none;
  transition: transform 0.15s, opacity 0.15s;
}
.map-cluster:hover .map-cluster-disc {
  transform: scale(1.08);
  opacity: 1;
}

/* Failure state — MapKit unconfigured (server-rendered visible), or the CDN
 * load / the token failed (map.js reveals it, the retry re-runs the loader).
 * An overlay inside .map-area above the empty map box. */
.map-unavailable {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 1rem;
  text-align: center;
  background: var(--vb, var(--color-gray-900));
  color: var(--vc-53, var(--color-gray-500));
  font-size: 14px;
}
.map-unavailable[hidden] { display: none; }
.map-unavailable-retry {
  padding: 0.4rem 1rem;
  border-radius: 9999px;
  background: var(--vc, var(--color-teal-500));
  color: var(--vc-text, #fff);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}
.map-unavailable-retry[hidden] { display: none; }
.map-page--unavailable .map-overlay-btns { display: none; }

@media (prefers-reduced-motion: reduce) {
  .map-pin,
  .map-cluster-disc { transition: none; }
}

/* Map overlay buttons (top-right corner). With the desktop detail panel open
   they slide left of its edge — the panel overlays the map's right side and
   would otherwise cover them. The offset mirrors .map-detail-panel's width
   (min(440px, 90%)) plus the buttons' own 12px inset, with the panel's
   transition so both move together. */
.map-overlay-btns {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  transition: right 0.25s ease;
}
@media (min-width: 1300px) {
  .map-area:has(.map-detail-panel.is-open) .map-overlay-btns {
    right: calc(min(440px, 90%) + 12px);
  }
  /* MapKit's own controls (the +/- zoom control, bottom-right) live in a
     closed shadow root inside this full-width host, anchored to ITS right
     edge — narrowing the host is the only way to keep them out from under
     the panel. Degrades to "under the panel" if MapKit renames the class. */
  .map-area:has(.map-detail-panel.is-open) .mk-controls-container {
    width: calc(100% - min(440px, 90%)) !important;
  }
}

.map-overlay-btns .map-refresh-btn {
  width: 36px;
  height: 36px;
  background: var(--vb, var(--color-gray-800));
  border: 1px solid var(--color-gray-600, var(--color-gray-600));
  border-radius: 0.5rem;
  color: var(--vtext, var(--color-gray-300));
}

.map-overlay-btns .map-refresh-btn:hover {
  background: var(--color-gray-700, var(--color-gray-700));
  color: var(--vtext, #fff);
}

/* Locate button */
.map-locate-btn {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--vb, var(--color-gray-800));
  border: 1px solid var(--color-gray-600, var(--color-gray-600));
  border-radius: 0.5rem;
  color: var(--vtext, var(--color-gray-300));
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.map-locate-icon {
  display: block;
  width: 1.7rem;
  height: 1.7rem;
  background: currentColor;
  mask-image: var(--icon);
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-image: var(--icon);
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
}

.map-locate-btn:hover {
  background: var(--color-gray-700, var(--color-gray-700));
  color: var(--vtext, #fff);
}

.map-locate-btn.loading {
  opacity: 0.6;
  pointer-events: none;
}

@media (max-width: 1023px) {
  .map-container {
    height: calc(100dvh - var(--mobile-nav-h, 64px));
  }

}

/* Post drawer — slides up from bottom on pin tap when sidebar is hidden */
.map-drawer-backdrop,
.map-drawer {
  display: none;
}

@media (max-width: 1299px) {
  .map-drawer-backdrop {
    display: block;
    position: absolute;
    inset: 0;
    /* Below the comment drawer (60): comments opened FROM the selected
       post's card must stack over this sheet. */
    z-index: 54;
    background: rgba(0, 0, 0, 0.35);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
  }

  .map-drawer-backdrop.is-open {
    opacity: 1;
    pointer-events: auto;
  }

  .map-drawer {
    display: flex;
    flex-direction: column;
    /* fixed, not absolute in the 100dvh map page: iOS 26+ Safari tints its
       bottom toolbar from the fixed / sticky element at the bottom edge
       (comments.css .cm-drawer-panel has the story). */
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 55;
    max-height: 90vh;
    background: var(--vb, var(--color-gray-900));
    border-top: 1px solid var(--color-gray-700, var(--color-gray-700));
    border-radius: 0.75rem 0.75rem 0 0;
    transform: translateY(100%);
    visibility: hidden;
    transition: transform 0.3s ease, visibility 0.3s;
    touch-action: pan-y;
    overscroll-behavior: contain;
  }

  .map-drawer.is-open {
    transform: translateY(0);
    visibility: visible;
  }

  .map-drawer-scroll {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }

  .map-drawer-handle {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 2.5rem;
    cursor: grab;
    touch-action: none;
  }

  .map-drawer-handle::after {
    content: '';
    width: 32px;
    height: 4px;
    background: var(--vc, var(--color-gray-600));
    border-radius: 2px;
  }

  .map-drawer-handle:active {
    cursor: grabbing;
  }

  .map-drawer-content {
    /* Breathing room between the head divider and the card. */
    padding: 0.5rem;
    width: 100%;
    max-width: 42rem;
    margin: 0 auto;
  }

  .map-drawer-content .map-post-card {
    margin-bottom: 0;
    width: 100%;
  }

  /* The Find icon points the user at the post's marker on the map. The
   * mobile drawer only opens by tapping that very marker, so the icon is
   * redundant there — hide it to keep the post header tidy. */
  .map-drawer-content .post-find-icon {
    display: none;
  }
}


/*# sourceMappingURL=mapCss.181c1a2e208fdb1d30e6.css.map*/