/* ==========================================================================
   Urbexology v2 — HUD, drawer, profiles, friends, auth tabs, symbols
   Loaded after style.css / animations.css and overrides legacy positioning.
   Visual language follows the existing site: 'IM Fell Double Pica' for
   display text, DM Sans body, parchment surfaces (238,229,216), #333
   buttons, small 5px radii, warm hairline borders.
   ========================================================================== */

:root {
  --v2-paper: rgba(238, 229, 216, 0.94);
  --v2-paper-soft: rgba(238, 229, 216, 0.55);
  --v2-white: rgba(255, 255, 255, 0.95);
  --v2-ink: #333;
  --v2-line: rgba(62, 44, 24, 0.22);
  --v2-btn-line: rgba(54, 38, 20, 0.46);
  --v2-btn-bg: rgba(248, 241, 229, 0.98);
  --v2-btn-bg-hover: rgba(255, 249, 238, 0.99);
  --v2-btn-shadow: 0 1px 2px rgba(22, 14, 7, 0.18);
  --v2-btn-shadow-pressed: inset 0 1px 2px rgba(22, 14, 7, 0.22);
  --v2-btn-radius: 3px;
  --v2-green: #2e7d32;
  --v2-green-dark: #1b5e20;
  --v2-brown: #a8763e;
  --v2-serif: 'IM Fell Double Pica', serif;
  --v2-radius: 5px;
  --v2-shadow: 0 2px 6px rgba(0, 0, 0, 0.22);
}

/* ============ top corner cluster (sits below the warning header) ============ */
/* Three compact buttons top-right; the search input only appears when the
   🔍 toggle is tapped. They sit below the always-on warning header strip. */
#v2-topbar {
  position: fixed;
  top: calc(var(--v2-ticker-h, 28px) + env(safe-area-inset-top, 0px) + 4px); /* clears warning header */
  right: 8px;
  left: auto;
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: none; /* children re-enable */
}
#v2-topbar > * { pointer-events: auto; }

/* Control buttons share one visual language so they read as part of the
   same product, not disconnected default widgets. */
#v2-profile-btn,
#v2-menu-btn,
#v2-topbar-discord,
#v2-add-fab,
#v2-dock #searchButton,
.v2-btn,
.v2-cta,
.v2-friend-row .v2-mini-btn,
#visibilityButton,
#notificationButton,
#alertsButton,
#v2-symbol-current,
#v2-symbol-picker button {
  border: 1px solid var(--v2-btn-line);
  border-radius: var(--v2-btn-radius);
  background: var(--v2-btn-bg);
  box-shadow: var(--v2-btn-shadow);
  transition: box-shadow 0.12s ease, background 0.12s ease;
}

#v2-profile-btn:hover,
#v2-menu-btn:hover,
#v2-topbar-discord:hover,
#v2-add-fab:hover,
#v2-dock #searchButton:hover,
.v2-btn:hover,
.v2-cta:hover,
.v2-friend-row .v2-mini-btn:hover,
#visibilityButton:hover,
#notificationButton:hover,
#alertsButton:hover,
#v2-symbol-current:hover,
#v2-symbol-picker button:hover {
  background: var(--v2-btn-bg-hover);
}

#v2-profile-btn:active,
#v2-menu-btn:active,
#v2-topbar-discord:active,
#v2-add-fab:active,
#v2-dock #searchButton:active,
.v2-btn:active,
.v2-cta:active,
.v2-friend-row .v2-mini-btn:active,
#visibilityButton:active,
#notificationButton:active,
#alertsButton:active,
#v2-symbol-current:active,
#v2-symbol-picker button:active {
  box-shadow: var(--v2-btn-shadow-pressed);
}

/* Discord chip — the community is the site's strongest authority signal, so
   it stays on screen next to the other topbar controls. Live online count
   fills in from the widget API (dot + number stay hidden if it fails). */
#v2-topbar-discord {
  height: 38px;
  box-sizing: border-box;
  display: flex;
  flex-direction: row;               /* style.css stacks .discord_link in a column */
  align-items: center;
  gap: 5px;
  padding: 0 10px;
  cursor: pointer;
  user-select: none;
}
#v2-topbar-discord svg { fill: #5865f2; display: block; flex: none; }
/* .discord_link::after "+78k!" doubles as the fallback when the live online
   count is unavailable; once the count fills, the static brag steps aside */
#v2-topbar-discord::after { margin: 0 0 0 2px; font-size: 0.72em; font-weight: 600; }
#v2-topbar-discord:has(#v2-topbar-discord-count:not(.hidden))::after { display: none; }
#v2-topbar-discord .v2-online-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #43be80;
  flex: none;
}
#v2-topbar-discord-count {
  font-size: 0.78em;
  font-weight: 600;
  color: var(--v2-ink);
  line-height: 1;
}

/* Brand wordmark — plain type, not a control: no box so it can't read as a button */
#v2-topbar-brand {
  height: 38px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  padding: 0 2px;
  font-family: 'IM Fell Double Pica', serif;
  font-weight: 700;
  font-size: 1.5em;
  letter-spacing: 0.01em;
  color: #1c130a;                    /* near-black ink — darker than the buttons' text */
  white-space: nowrap;
  user-select: none;
  pointer-events: none;              /* pure label — clicks fall through to the map */
  /* dense paper halo: solid edge + wide glow so it cuts through any imagery */
  text-shadow:
    -1px -1px 0 rgb(238, 229, 216),
     1px -1px 0 rgb(238, 229, 216),
    -1px  1px 0 rgb(238, 229, 216),
     1px  1px 0 rgb(238, 229, 216),
     0 0 6px rgb(238, 229, 216),
     0 0 14px rgba(238, 229, 216, 0.95),
     0 2px 18px rgba(238, 229, 216, 0.85);
}

/* ============ search: the map-corner control (index.js) is the ONE search ============ */
/* Re-theme its dropdown to the site's parchment look and give grouped results room. */
.maplibregl-ctrl-search.expanded { width: min(300px, calc(100vw - 80px)); }
/* Search chip needs a visible surface when expanded: unlike other maplibre
   controls (icon-only), this one contains a text INPUT — a transparent chip
   over a satellite tile makes the typed query unreadable. The generic
   `.maplibregl-ctrl-group { background: transparent }` rule below strips the
   default white; here we give it back with the site's parchment chip look.
   Two-class specificity (`.expanded`) beats the one-class `-group` rule. */
.maplibregl-ctrl-search.expanded {
  background: var(--v2-btn-bg);
  border: 1px solid var(--v2-btn-line);
  border-radius: var(--v2-btn-radius);
  box-shadow: var(--v2-btn-shadow);
}
.maplibregl-ctrl-search input[type="text"] { font-family: inherit; color: var(--v2-ink); }
.maplibregl-ctrl-search .maplibregl-ctrl-search-results {
  width: min(86vw, 360px);
  right: auto;                /* style.css pins left+right to the 260px control — let it breathe */
  max-height: 46vh;
  background: var(--v2-paper);
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-radius);
  box-shadow: var(--v2-shadow);
}
/* group heads are divs — out-rank style.css's generic results-div rule */
.maplibregl-ctrl-search .maplibregl-ctrl-search-results div.v2-result-head {
  padding: 7px 10px 2px;
  cursor: default;
  font-size: 1em;
}
.maplibregl-ctrl-search .maplibregl-ctrl-search-results div.v2-result-head:hover { background: transparent; }
.v2-result {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-bottom: 1px solid rgba(62, 44, 24, 0.12);
  background: transparent;
  cursor: pointer;
  text-align: left;
  font-size: 0.92em;
  font-family: inherit;
  color: var(--v2-ink);
}
.v2-result:last-child { border-bottom: none; }
.v2-result:hover { background: var(--v2-white); }
.v2-result > span:first-child {        /* long Nominatim names: one tidy line */
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.v2-result .v2-result-sub {
  margin-left: auto;
  font-size: 0.85em;
  color: #7a6a55;
  white-space: nowrap;
}
.v2-result-head {
  padding: 7px 10px 2px;
  font-family: var(--v2-serif);
  font-size: 1em;
  color: #5d4d39;
}

#v2-profile-btn, #v2-menu-btn {
  height: 38px;
  min-width: 38px;
  cursor: pointer;
  font-size: 1.15em;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  overflow: hidden;
  color: #1f170d;
}
#v2-topbar-avatar {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ============ bottom dock (transient search controls only) ============ */
#v2-dock {
  position: fixed;
  bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 999;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  background: var(--v2-paper);
  border: 1px solid var(--v2-line);
  border-radius: 6px;
  box-shadow: var(--v2-shadow);
  max-width: 94vw;
}
#v2-dock #searchButton { white-space: nowrap; }
/* nothing to say → no box: the dock only exists while searching (counter,
   spinner, ZOOM hint, Chercher button, auto-search toggle) */
/* nothing to say → no box: the dock only exists while searching (counter,
   spinner, ZOOM hint, Chercher button, auto-search toggle).
   NB keyed on inline display:none — these controls are toggled by legacy JS
   via style.display (their class="hidden" markup was dead weight, removed). */
#v2-dock:has(> #searchButton[style*="display: none"]):has(> #divautosearch[style*="display: none"]):has(> #zoomStr.hidden):has(#resultCounter:empty):not(:has(#searchLoadingLogo[style*="visibility: visible"])),
#v2-dock:has(> #searchButton[style*="display:none"]):has(> #divautosearch[style*="display:none"]):has(> #zoomStr.hidden):has(#resultCounter:empty):not(:has(#searchLoadingLogo[style*="visibility: visible"])) {
  display: none;
}

/* ============ add-spot FAB (bottom-right thumb zone) ============ */
/* Compact horizontal PILL — icon + label side-by-side — instead of a big
   cream disc. The old vertical/stacked layout at 67×72 with a full pill
   radius read as a generic Material/iOS FAB glued to the corner; the
   parchment aesthetic wants something crafted and light, not a solid
   opaque puck obscuring the map. Now: hairline border, translucent
   parchment with backdrop blur (so map still peeks through), tighter
   rounded-rectangle radius, smaller pin, subtle shadow that lifts it
   just enough to read as clickable. */
#v2-add-fab {
  position: fixed;
  right: 10px;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));   /* above the home bar */
  z-index: 999;
  box-sizing: border-box;
  display: inline-flex;
  flex-direction: row;             /* icon + label sit side-by-side */
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 14px 8px 10px;
  /* hairline + translucent parchment so map still shows through */
  background: rgba(248, 241, 229, 0.88);
  -webkit-backdrop-filter: blur(6px) saturate(1.05);
          backdrop-filter: blur(6px) saturate(1.05);
  /* soft rounded rectangle, not a full pill — feels crafted */
  border-radius: 14px;
  /* no visible min-height/min-width — chip hugs its content */
  min-height: 0;
  min-width: 0;
  max-width: min(180px, calc(100vw - 24px));
  /* Whole pill (icon + label + padding) is now interactive: a plain tap
     drops a pin at the current map center (handler in index.js). Without
     this, the label/padding rendered with default `auto` cursor while only
     the pin img inside showed `pointer` — visually inconsistent + fed the
     "clicking on add spot nothing happens" bug. */
  cursor: pointer;
}
#v2-add-fab .add-spot-text {
  /* Text inherits pointer cursor from parent above; ensure no override. */
  cursor: inherit;
}
#v2-add-fab .draggable-marker {
  /* Constrain BOTH dimensions so the tall Leaflet pin image (native ~25×47)
     never overflows the compact pill. object-fit:contain preserves aspect. */
  width: 20px;
  height: 20px;
  object-fit: contain;
  margin: 0;
  flex-shrink: 0;
}
/* ============ dragging state (JS toggles this on real drag movement) ============ */
/* While the pin follows the finger/cursor across the map, blow it up visually
   with transform:scale so the user can actually see what they're aiming. The
   chip-sized 20/22px thumbnail is fine while docked in the FAB pill but reads
   as "lost" once it lifts off and floats over the map. Using transform (not
   width/height) means the marker's LAYOUT BOX stays 20×20 — the flex row in
   the pill doesn't reflow around a suddenly-huge child. The `left`/`top`
   inline styles set by handleMove still translate the layout box correctly;
   transform:scale is applied on top of that translation. */
.draggable-marker.dragging {
  transform: scale(2.2);
  transform-origin: center;
  z-index: 1005;                    /* above pin-picker (1004), above map ctrls */
  filter: drop-shadow(0 6px 8px rgba(0, 0, 0, 0.5))
          drop-shadow(0 0 2px rgba(255, 255, 255, 0.7));
  pointer-events: none;             /* let elementsFromPoint see the map underneath at drop */
  /* No transition — the size-up must be instant to feel like a "lift" */
}
#v2-add-fab .add-spot-text {
  margin: 0;
  font-size: 13px;
  line-height: 1;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--v2-ink);
  mix-blend-mode: normal;         /* style.css inverts it for over-map contrast — not needed on a chip */
  filter: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;        /* long langs (hu/ru) truncate cleanly */
}
/* declutter parity: on-map controls hide while a spot panel is open */
body:has(#info-panel:not(.hidden)) #v2-add-fab { display: none; }
/* also hide the FAB while the pin-picker is active — the picker replaces it */
html.v2-pin-picker-open #v2-add-fab { display: none; }

/* ============ pin-picker (Google-Maps-style "position first, form second") ============ */
/* Fires on FAB click: overlay a pin at viewport center + a bottom action
   bar. The map itself stays fully interactive underneath (overlay uses
   pointer-events:none except for the bar buttons) so the user can pan/
   zoom to position the pin, then confirm. This gives them PREVIEW and
   ADJUSTMENT before the heavy addSpot modal opens — solving the previous
   "click drops instantly, no preview, no correction" problem. */
.v2-pin-picker {
  position: fixed;
  inset: 0;
  z-index: 1004;                     /* above map controls, below drawer/modals */
  pointer-events: none;              /* map remains pannable through the overlay */
}
.v2-pin-picker.hidden { display: none; }

/* Centered pin. Positioned so the TIP of the marker is at exact viewport
   center — that's where addLocation will read the coord from. The pin
   image is 25×47 native (tip at bottom center); after JS resize we anchor
   the tip via translate. */
.v2-pin-picker-marker {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 32px;
  height: auto;
  /* -50% X centers horizontally; -100% Y makes the BOTTOM of the img
     land on the exact center line, so the pin tip = viewport center. */
  transform: translate(-50%, -100%);
  filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.45));
  /* Subtle pulse to signal "I'm live, move the map to reposition me" */
  animation: v2-pin-picker-pulse 1.4s ease-in-out infinite;
}
@keyframes v2-pin-picker-pulse {
  0%, 100% { transform: translate(-50%, -100%) scale(1); }
  50%      { transform: translate(-50%, -100%) scale(1.08); }
}

/* Tiny crosshair dot at exact center, so the pin-tip anchor is undeniable */
.v2-pin-picker::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: rgba(46, 125, 50, 0.9);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9);
}

/* Bottom action bar — the ONLY interactive part of the overlay */
.v2-pin-picker-bar {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  pointer-events: auto;              /* re-enable clicks on the bar */
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px 10px 16px;
  background: rgba(248, 241, 229, 0.94);
  -webkit-backdrop-filter: blur(8px) saturate(1.1);
          backdrop-filter: blur(8px) saturate(1.1);
  border: 1px solid var(--v2-btn-line);
  border-radius: 18px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.22);
  max-width: min(420px, calc(100vw - 24px));
}
.v2-pin-picker-hint {
  font-size: 13px;
  font-weight: 500;
  color: var(--v2-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.v2-pin-picker-cancel,
.v2-pin-picker-confirm {
  flex-shrink: 0;
  padding: 8px 14px;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 600;
  border: 1px solid var(--v2-btn-line);
  cursor: pointer;
  transition: background 0.12s ease, box-shadow 0.12s ease;
}
.v2-pin-picker-cancel {
  padding: 8px 12px;
  background: transparent;
  color: var(--v2-ink);
  min-width: 34px;
}
.v2-pin-picker-cancel:hover { background: rgba(0, 0, 0, 0.05); }
.v2-pin-picker-confirm {
  background: rgba(46, 125, 50, 0.95);
  color: #fff;
  border-color: rgba(46, 125, 50, 0.95);
}
.v2-pin-picker-confirm:hover { background: rgba(46, 125, 50, 1); }
.v2-pin-picker-confirm:focus-visible,
.v2-pin-picker-cancel:focus-visible {
  outline: 2px solid rgba(46, 125, 50, 0.85);
  outline-offset: 2px;
}
/* Narrow phones: shrink the hint before it clips the buttons */
@media (max-width: 480px) {
  .v2-pin-picker-hint { font-size: 12px; max-width: 40vw; }
}
/* Very narrow (iPhone SE etc.): the pin + confirm button say it all, hide hint */
@media (max-width: 380px) {
  .v2-pin-picker-hint { display: none; }
  .v2-pin-picker-bar { padding: 10px 10px 10px 12px; }
}

/* ============ always-on warning header (top edge) ============ */
/* The site's two safety messages (collaborative "POTENTIALLY abandoned"
   tagline + the red photographers/no-trespassing reminder) are critical
   enough to live at the TOP of the screen as a permanent header. They
   alternate every 9s (discrete swap, no fade). The header uses the FULL
   viewport width — the topbar buttons sit below it, not over it — so the
   message is never truncated. Wraps to up to 3 lines. Tap to read in full. */
#v2-warn-ticker {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  z-index: 998;
  min-height: calc(30px + env(safe-area-inset-top, 0px));
  padding: calc(6px + env(safe-area-inset-top, 0px)) 14px 6px 14px;
  /* Translucent so the map reads through — alpha tuned so serif text stays
     legible on busy satellite tiles. backdrop-filter softens the underlying
     tiles into a wash. */
  background:
    repeating-linear-gradient(45deg,
      rgba(154, 116, 70, 0.04) 0,
      rgba(154, 116, 70, 0.04) 2px,
      transparent 2px,
      transparent 4px),
    rgba(238, 229, 216, 0.72);
  -webkit-backdrop-filter: blur(8px) saturate(115%);
  backdrop-filter: blur(8px) saturate(115%);
  border-bottom: 1px solid rgba(62, 44, 24, 0.28);
  box-shadow:
    0 1px 0 rgba(62, 44, 24, 0.08),
    0 2px 0 rgba(62, 44, 24, 0.03);
  cursor: pointer;
  overflow: hidden;
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
}
#v2-warn-ticker:hover {
  background:
    repeating-linear-gradient(45deg,
      rgba(154, 116, 70, 0.03) 0,
      rgba(154, 116, 70, 0.03) 2px,
      transparent 2px,
      transparent 4px),
    rgba(245, 237, 224, 0.82);
}
.v2-warn-slide {
  grid-row: 1;
  grid-column: 1;
  font-family: var(--v2-serif);
  font-size: 0.86em;
  line-height: 1.3;
  letter-spacing: 0.005em;
  color: #2b1d10;
  /* subtle text-shadow so serif keeps contrast over translucent header on
     bright map tiles (snow, water glare, etc.) without looking glowy */
  text-shadow: 0 1px 0 rgba(255, 248, 235, 0.55);
  text-align: center;
  /* clamp at 3 lines max — enough for any language even on 320px */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  word-break: break-word;
  hyphens: auto;
  opacity: 0;
  pointer-events: none;
  /* smooth crossfade between the two safety messages so the swap reads as
     a gentle dissolve, not a flicker. Reduced-motion users get a discrete
     swap (rule below). */
  transition: opacity 0.9s ease;
}
.v2-warn-slide.on { opacity: 1; }
/* Stronger danger red: deeper saturation + slightly heavier weight + a warm
   cream halo so it pops against translucent header on busy satellite tiles.
   The reminder is safety-critical (no trespassing, photo-credit etc.) so it
   needs to read as ALARM, not as decorative text. */
.v2-warn-slide.v2-warn-red {
  color: #b8190a;
  font-weight: 800;
  letter-spacing: 0.01em;
  text-shadow:
    0 1px 0 rgba(255, 248, 235, 0.85),
    0 0 1px rgba(255, 248, 235, 0.85);
}
#v2-warn-ticker.expanded {
  z-index: 1001;                   /* drop the sheet ABOVE the topbar buttons when expanded */
  max-height: 60vh;
  overflow: auto;
  padding: calc(12px + env(safe-area-inset-top, 0px)) 18px 14px;
  display: block;                  /* exit grid in expanded mode so slides stack */
  /* expanded sheet is full-read mode — bump alpha so long text is easy on the eye */
  background:
    repeating-linear-gradient(45deg,
      rgba(154, 116, 70, 0.04) 0,
      rgba(154, 116, 70, 0.04) 2px,
      transparent 2px,
      transparent 4px),
    rgba(245, 237, 224, 0.95);
}
#v2-warn-ticker.expanded .v2-warn-slide {
  display: block;                  /* override line-clamp box in expanded mode */
  -webkit-line-clamp: unset;
  height: auto;
  line-height: 1.5;
  white-space: normal;
  opacity: 1;
  text-align: left;
  font-size: 0.98em;
}
#v2-warn-ticker.expanded #v2-warn-slide-a { margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px dashed rgba(62, 44, 24, 0.34); }
@media (prefers-reduced-motion: reduce) {
  .v2-warn-slide { transition: none !important; } /* discrete swaps, no fade */
}
/* the red reminder now lives on the header ticker — retire the drawer copy */
#menu .reminder { display: none; }
/* declutter parity while a spot panel is open */
body:has(#info-panel:not(.hidden)) #v2-warn-ticker { display: none; }

/* ============ drawer (replaces the old always-on panel) ============ */
#v2-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  z-index: 1001;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
#v2-backdrop.v2-show { opacity: 1; pointer-events: auto; }

#menu.v2-drawer {
  position: fixed;
  top: 0;
  right: 0;
  left: auto;
  bottom: 0;
  transform: translateX(105%);
  transition: transform 0.28s ease;
  width: min(360px, 94vw);
  height: 100%;
  max-height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  z-index: 1002;
  background: var(--v2-white);
  border-radius: 0;
  border-left: 1px solid var(--v2-line);
  box-shadow: -4px 0 16px rgba(0, 0, 0, 0.25);
  padding: 0 10px 18px;
  box-sizing: border-box;
  -webkit-overflow-scrolling: touch;
}
#menu.v2-drawer.v2-open { transform: translateX(0); }

.v2-drawer-head {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 2px 8px;
  background: var(--v2-white);
  z-index: 2;
  border-bottom: 1px solid var(--v2-line);
  margin-bottom: 6px;
}
.v2-drawer-head .site-title { font-size: 1.3em; }
#v2-drawer-close {
  border: none;
  background: transparent;
  font-size: 1.7em;
  line-height: 1;
  cursor: pointer;
  padding: 0 6px;
  color: #555;
  /* generous touch target — most visitors are on phones */
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.v2-section {
  margin: 10px 0;
  padding: 9px 10px;
  background: var(--v2-paper-soft);
  border: 1px solid var(--v2-line);
  border-radius: 6px;
}
/* ============ tailored line icons (retired emoji chrome) ============ */
/* Inline stroke SVGs inherit text ink via currentColor — same pattern as
   the topbar Discord mark. Emoji stay only where they're content (mode
   labels, warnings, user pin symbols), not UI chrome. */
.v2-ico {
  width: 1.05em;
  height: 1.05em;
  display: inline-block;
  vertical-align: -0.16em;
  flex: 0 0 auto;
}
/* icon-only chips need a slightly larger glyph to fill their touch target */
#v2-menu-btn .v2-ico { width: 1.3em; height: 1.3em; vertical-align: middle; }
#visibilityButton .v2-ico,
#notificationButton .v2-ico,
#alertsButton .v2-ico,
#aiSettings .v2-ico { width: 1.2em; height: 1.2em; vertical-align: -0.22em; }
/* notification button is a two-state control (bell = idle, check = armed,
   confirming the alert-zone placement). State lives on .notif-armed — the
   legacy innerHTML 🔔/✅ swap would destroy the inline SVGs. */
#notificationButton .ico-check { display: none; }
#notificationButton.notif-armed .ico-bell { display: none; }
#notificationButton.notif-armed .ico-check { display: inline-block; color: #2e7d32; }
/* avatar chips: person glyph scales with the chip (font-size drives em) */
.v2-avatar-fallback .v2-ico { width: 1em; height: 1em; vertical-align: middle; }
#v2-topbar-avatar-fallback .v2-ico { width: 1.25em; height: 1.25em; vertical-align: middle; }

.v2-section-title {
  font-family: var(--v2-serif);
  font-weight: 700;
  font-size: 1.15em;
  margin-bottom: 7px;
  border-bottom: 1px solid rgba(62, 44, 24, 0.14);
  padding-bottom: 3px;}

/* ============ profile card ============ */
/* CTA mirrors the site's .btn-dark (#333, 5px radius, soft shadow) */
.v2-cta {
  display: block;
  width: 100%;
  padding: 10px 12px;
  color: #1d150c;
  font-size: 1em;
  font-weight: 700;
  letter-spacing: 0.01em;
  font-family: inherit;
  cursor: pointer;
}
.v2-btn {
  display: inline-block;
  padding: 7px 10px;
  color: #1d150c;
  font-size: 0.88em;
  font-weight: 700;
  letter-spacing: 0.01em;
  font-family: inherit;
  cursor: pointer;
}
.v2-badge {
  display: inline-block;
  min-width: 18px;
  padding: 1px 5px;
  border-radius: 9px;
  background: #c62828;
  color: #fff;
  font-size: 0.8em;
  text-align: center;
}

.v2-profile-row { display: flex; align-items: center; gap: 10px; }
.v2-profile-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.v2-profile-meta b {
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: var(--v2-serif);
  font-size: 1.2em;
}
.v2-profile-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}
/* Pro upgrade chip lives in the Profile section (membership, not a "link");
   #notch is hidden by index.js once the account is already pro. Override
   the loud green legacy chip with a calmer parchment pill that matches the
   v2 button language. */
#v2-profile-section #notch.notch-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: fit-content;
  margin: 10px 0 0;
  padding: 6px 12px;
  background: var(--v2-btn-bg);
  color: #1f170d;
  border: 1px solid var(--v2-btn-line);
  border-radius: var(--v2-btn-radius);
  box-shadow: var(--v2-btn-shadow);
  font-family: inherit;
  font-size: 0.9em;
  font-weight: 600;
  word-break: normal;
}
#v2-profile-section #notch.notch-badge:hover {
  background: var(--v2-btn-bg-hover);
}

.v2-avatar, .v2-avatar-sm, .v2-avatar-lg {
  border-radius: 50%;
  object-fit: cover;
  background: #ddd;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border: 2px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.v2-avatar { width: 46px; height: 46px; font-size: 1.5em; }
.v2-avatar-sm { width: 30px; height: 30px; font-size: 1em; }
.v2-avatar-lg { width: 84px; height: 84px; font-size: 2.6em; }
.v2-avatar-fallback { color: #666; }

/* ============ community stats ============ */
.v2-stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  text-align: center;
}
.v2-stat {
  background: var(--v2-white);
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-radius);
  padding: 6px 2px;
  display: flex;
  flex-direction: column;
}
.v2-stat b {
  font-family: var(--v2-serif);
  font-size: 1.25em;
  line-height: 1.15;
}
.v2-stat span { font-size: 0.72em; color: #6b5d4f; }

/* ============ auth tabs ============ */
/* segmented control, square like the site's buttons */
.v2-auth-tabs {
  display: flex;
  gap: 0;
  margin: 8px auto 12px;
  max-width: 420px;
  background: var(--v2-white);
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-radius);
  overflow: hidden;
}
.v2-auth-tab {
  flex: 1;
  padding: 9px 4px;
  border: none;
  border-right: 1px solid var(--v2-line);
  background: transparent;
  cursor: pointer;
  font-size: 0.95em;
  font-family: inherit;
  color: #555;
}
.v2-auth-tab:last-child { border-right: none; }
.v2-auth-tab.active {
  background: var(--v2-ink);
  color: #fff;
}
.v2-auth-pane {
  max-width: 420px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.v2-auth-pane input[type="email"],
.v2-auth-pane input[type="password"],
.v2-auth-pane input[type="text"] {
  width: 100%;
  box-sizing: border-box;
  height: 42px;
  padding: 0 10px;
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-radius);
  font-size: 1em;
  font-family: inherit;
  background: #fff;
}
.v2-auth-hint { font-size: 0.85em; color: var(--v2-green); margin: 0; }
.v2-auth-link { font-size: 0.88em; color: #666; text-decoration: underline; }
.v2-auth-msg {
  font-size: 0.95em;
  padding: 8px 10px;
  border-radius: var(--v2-radius);
  background: var(--v2-paper-soft);
  border: 1px solid var(--v2-line);
  margin: 8px auto 0;
  max-width: 420px;
}
.v2-auth-msg.v2-error { background: #fff2e5; border-color: #ffa726; color: #e65100; }
.v2-auth-msg.v2-ok { background: #e8f5e9; border-color: #c8e6c9; color: var(--v2-green-dark); }

/* ============ modals (profile edit / friends / public profile) ============ */
.v2-modal-close {
  position: absolute;
  top: 8px;
  right: 12px;
  border: none;
  background: transparent;
  box-shadow: none;             /* style.css gives every <button> a shadow plate */
  font-size: 1.8em;
  line-height: 1;
  cursor: pointer;
  color: #555;
  z-index: 3;
  min-width: 36px;
  min-height: 36px;
}
#v2-profile-modal .modal-content,
#v2-friends-modal .modal-content,
#v2-pubprofile-modal .modal-content {
  position: relative;
  max-width: 460px;
  width: min(460px, 94vw);
  max-height: 88vh;
  overflow-y: auto;
  border-radius: 6px;
}

/* ============ Help popup (#onboarding "Mémo") ============ */
/* Was a wall of bold headings on translucent paper with no close button.
   Now: an opaque reference card — every feature reads as one calm line. */
#onboarding { display: flex; align-items: center; justify-content: center; top: 0; background: rgba(20, 14, 6, 0.45); }
#onboarding.hidden { display: none; }
#onboarding .modal-content {
  position: relative;
  width: min(560px, 94vw);
  max-height: 86vh;
  overflow-y: auto;
  background: rgb(238, 229, 216);   /* opaque — translucent paper let the map ghost through */
  border: 1px solid var(--v2-line);
  border-radius: 8px;
  padding: 0 16px 14px;
  text-align: left;
}
#onboarding .headerSection {
  margin: 0 -16px 4px;              /* full-bleed banner */
  padding: 14px 16px;
}
#onboarding .headerTitle { font-size: 1.6em; }
#onboarding .v2-modal-close {
  position: sticky;                 /* stays reachable while the list scrolls */
  top: 6px;
  float: right;
  margin-right: -6px;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}
#onboarding .modal-content h3 {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0;
  padding: 9px 2px;
  font-size: 0.92em;
  font-weight: 500;
  line-height: 1.45;
  text-align: left;
  border-bottom: 1px solid rgba(62, 44, 24, 0.12);
}
#onboarding .modal-content h3 img {
  width: 1.15em;
  height: auto;
  flex: none;
  margin-top: 2px;
  background: none;
  box-shadow: none;
}
/* the AI row carries its "see more" button inline */
#onboarding .modal-content span.flex {
  border-bottom: 1px solid rgba(62, 44, 24, 0.12);
  align-items: center;
  gap: 10px;
}
#onboarding .modal-content span.flex h3 { border-bottom: none; flex: 1; }
#onboarding #showAItuto { flex: none; white-space: nowrap; }
#onboarding .modal-content > .text-center {
  padding-top: 12px;
  font-size: 0.85em;
}
@media (max-width: 640px) {
  /* phones: bottom sheet, same family as the add-spot form */
  #onboarding { align-items: flex-end; }
  #onboarding .modal-content {
    width: 100%;
    max-height: 82vh;
    border-radius: 14px 14px 0 0;
    border-bottom: none;
    padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  }
}

#v2-profile-modal h3,
#v2-friends-modal h3,
#v2-pubprofile-modal h3 {
  font-family: var(--v2-serif);
  font-size: 1.5em;
  margin: 0.3em 0 0.5em;
}
.v2-avatar-edit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.v2-form { display: flex; flex-direction: column; gap: 9px; }
.v2-form label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 0.88em;
  color: #444;
  text-align: left;
}
.v2-form input, .v2-form textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 9px 10px;
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-radius);
  font-size: 1em;
  font-family: inherit;
  background: #fff;
}
.v2-form .v2-check {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  font-size: 0.92em;
}
.v2-form .v2-check input { width: auto; }

/* ============ friends ============ */
.v2-friend-add { display: flex; gap: 6px; margin-bottom: 10px; }
.v2-friend-add input {
  flex: 1;
  min-width: 0;
  padding: 9px 10px;
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-radius);
  font-size: 1em;
  font-family: inherit;
}
.v2-friend-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 4px;
  border-bottom: 1px solid rgba(62, 44, 24, 0.12);
}
.v2-friend-row:last-child { border-bottom: none; }
.v2-friend-row .v2-friend-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: left;
  cursor: pointer;
  background: none;
  border: none;
  font-size: 1em;
  font-family: inherit;
  font-weight: 600;
  padding: 0;
  color: var(--v2-ink);
}
.v2-friend-row .v2-friend-name:hover { text-decoration: underline; }
.v2-friend-row .v2-mini-btn {
  padding: 4px 8px;
  cursor: pointer;
  font-size: 0.85em;
  font-weight: 600;
  font-family: inherit;
}
.v2-empty { color: #6b5d4f; font-size: 0.9em; padding: 6px 0; }

/* ============ public profile ============ */
.v2-pub-bio { white-space: pre-wrap; color: #444; max-height: 30vh; overflow-y: auto; }
.v2-pub-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  margin: 8px 0;
}
.v2-pub-links a, .v2-pub-links span {
  font-size: 0.88em;
  background: var(--v2-paper-soft);
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-radius);
  padding: 4px 10px;
  color: var(--v2-ink);
  text-decoration: none;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.v2-pub-links a:hover { background: var(--v2-paper); }

/* ============ spot info panel additions ============ */
.v2-symbol-head { display: flex; align-items: center; justify-content: space-between; }
#v2-symbol-current {
  width: 34px;
  height: 34px;
  font-size: 1.15em;
  cursor: pointer;
}
#v2-symbol-picker {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 4px;
  margin-top: 6px;
}
#v2-symbol-picker button {
  height: 34px;
  font-size: 1.05em;
  cursor: pointer;
  padding: 0;
}
#v2-symbol-picker button.v2-selected { outline: 2px solid var(--v2-green); }

/* symbol badge on a map pin */
.v2-marker-symbol {
  position: absolute;
  top: -4px;
  left: 50%;
  transform: translate(-50%, -100%);
  font-size: 15px;
  line-height: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 3px #fff;
  pointer-events: none;
}

/* ============ legal row ============ */
.v2-legal-row {
  text-align: center;
  font-size: 0.82em;
  color: #6b5d4f;
  padding: 10px 0 4px;
}
.v2-legal-row a { color: #6b5d4f; }

/* ============ in-drawer tweaks for legacy blocks ============ */
#menu.v2-drawer .facultative { display: block; }
/* But when a .facultative row is ALSO tagged .centered-row (used by the
   "Check cascadology.com! 🌊" cross-promo link), the block above stomps its
   `display: flex` and `justify-content: center` becomes inert — the link
   ends up left-aligned instead of centered. Restore flex-centering with a
   higher-specificity selector (matches the same #menu.v2-drawer scope +
   an extra class, per the pattern documented later in this file). */
#menu.v2-drawer .facultative.centered-row {
  display: flex;
  justify-content: center;
  align-items: center;
}
#menu.v2-drawer hr.hr-compact { margin: 8px 0; }
/* MapLibre top-left controls clear the wrapped warning header. */
.maplibregl-ctrl-top-left { margin-top: calc(var(--v2-ticker-h, 28px) + env(safe-area-inset-top, 0px)); }

/* ============ map control group: unify look across stock + custom ============ */
/* MapLibre's stock controls (+/-/compass/locate/search) and our custom layer
   toggles (#wikiButton, #extraButton, #trainButton, water, satellite) all
   ride in `.maplibregl-ctrl-group`. Give them one consistent calm look so
   the lower-left stack doesn't read as a different generation of UI. */
.maplibregl-ctrl-group {
  background: transparent;
  box-shadow: none;
  border: none;
}
.maplibregl-ctrl-group:not(:empty) {
  margin: 8px;
}
.maplibregl-ctrl-group > button {
  background-color: var(--v2-btn-bg) !important;     /* JS sets inline bg on custom controls; override */
  border: 1px solid var(--v2-btn-line) !important;
  border-radius: var(--v2-btn-radius) !important;
  box-shadow: var(--v2-btn-shadow);
  margin-bottom: 4px;                                /* visual breathing room between siblings */
}
.maplibregl-ctrl-group > button + button { border-top-width: 1px !important; }
.maplibregl-ctrl-group > button:hover {
  background-color: var(--v2-btn-bg-hover) !important;
}
/* Custom layer toggle "active" state: legacy JS sets style.backgroundColor='gray'
   (or 'grey' for wikiButton) when on. Repaint that as a calm green-tinted
   highlight so it stops reading like raw template UI. Inline colour wins
   specificity-wise — use attribute selector on the exact colour string the
   JS writes, and cover BOTH structural forms (native +/-/geolocate/compass
   buttons live inside .maplibregl-ctrl-group, but the 5 custom toggles are
   standalone .maplibregl-ctrl.leaflet-bar divs), and BOTH spellings. */
.maplibregl-ctrl-group > button[style*="background-color: gray"],
.maplibregl-ctrl-group > button[style*="background-color:gray"],
.maplibregl-ctrl-group > button[style*="background-color: grey"],
.maplibregl-ctrl-group > button[style*="background-color:grey"],
.maplibregl-ctrl.leaflet-bar[style*="background-color: gray"],
.maplibregl-ctrl.leaflet-bar[style*="background-color:gray"],
.maplibregl-ctrl.leaflet-bar[style*="background-color: grey"],
.maplibregl-ctrl.leaflet-bar[style*="background-color:grey"] {
  background-color: rgba(46, 125, 50, 0.18) !important;   /* parchment-friendly green wash */
  border-color: rgba(46, 125, 50, 0.55) !important;
  box-shadow: var(--v2-btn-shadow), inset 0 0 0 1px rgba(46, 125, 50, 0.22);
}
/* The raster icon backgrounds (Wikipedia logo, satellite) sit on the button
   itself via JS-set backgroundImage; preserve them. */

/* ============ custom map-toggle buttons: responsive sizing ============ */
/* #wikiButton, #extraButton, #trainButton, #waterButton, #timelineButton are
   standalone .maplibregl-ctrl.leaflet-bar divs (NOT children of
   .maplibregl-ctrl-group), so the styling block above doesn't reach them.
   JS also hard-codes width:30px / height:30px inline plus line-height:30px
   and font-size:18px on the emoji ones, and background-size:20px on the
   Wikipedia logo. Those inline values stick at every viewport, so on mobile
   the icons look tiny inside the 42px chip while native ctrl-group icons
   maintain a ~67% icon-to-chip ratio. Match MapLibre's own responsive
   breakpoint (max-width:640px) and scale the icon/emoji proportionally. */
#wikiButton,
#extraButton,
#trainButton,
#waterButton,
#timelineButton {
  width: 29px !important;
  height: 29px !important;
  line-height: 29px !important;
  /* Match native ctrl-group visual: border-radius + calm background so the
     five custom toggles read as siblings of +/-/geolocate/compass, not
     a leftover generation. */
  border-radius: var(--v2-btn-radius);
  box-shadow: var(--v2-btn-shadow);
  border: 1px solid var(--v2-btn-line);
}
/* Emoji chips: scale font-size in step with chip height. */
#extraButton,
#trainButton,
#waterButton,
#timelineButton {
  font-size: 20px !important;
}
/* Wikipedia logo: scale background-image in step with chip height. */
#wikiButton {
  background-size: 20px 20px !important;
}
@media (max-width: 640px) {
  #wikiButton,
  #extraButton,
  #trainButton,
  #waterButton,
  #timelineButton {
    width: 40px !important;
    height: 40px !important;
    line-height: 40px !important;
  }
  #extraButton,
  #trainButton,
  #waterButton,
  #timelineButton {
    font-size: 26px !important;
  }
  #wikiButton {
    background-size: 26px 26px !important;
  }
}
/* Keyboard focus ring for the div-based custom buttons (they became
   tab-focusable via role="button" + tabindex="0"). Match the parchment
   accent so it doesn't clash with the map. Only when tabbing, not on click. */
#wikiButton:focus-visible,
#extraButton:focus-visible,
#trainButton:focus-visible,
#waterButton:focus-visible,
#timelineButton:focus-visible {
  outline: 2px solid rgba(46, 125, 50, 0.85);
  outline-offset: 2px;
}

/* ============ suppress transitions during viewport resize ============ */
/* Several elements have `transition: width` (notably
   .maplibregl-ctrl-search which is 30px on desktop / 40px on mobile via
   a 640px media query). When the user resizes the window, rotates their
   phone, or the mobile keyboard opens/closes, the viewport crosses the
   breakpoint and the search chip visibly SLIDES from 30→40 (or reverse)
   over 300ms — a distracting "the button animates on rescale" bug.
   Standard fix: set an <html class="is-resizing"> during resize + kill
   transitions, then release after the resize settles (see resize handler
   at the end of index.js). */
html.is-resizing,
html.is-resizing *,
html.is-resizing *::before,
html.is-resizing *::after {
  transition: none !important;
  animation-duration: 0s !important;
}

/* transient notification banners drop below the warning header + topbar row */
.notification-banner { top: calc(80px + env(safe-area-inset-top, 0px)); }
/* When the spot info-panel or the notifications panel is open, hide the
   transient noproof safety banner so it doesn't visually overlap panel
   content (it's fixed top-center at z9999, above both). The safety text is
   a session-level warning, not per-panel info. */
body:has(#info-panel:not(.hidden)) .notification-banner,
body:has(#notification-panel:not(.hidden)) .notification-banner { display: none; }
/* give the mode row room: chips left, tool buttons right, wrap on overflow */
#menu.v2-drawer .v2-section .flex.justify-between { flex-wrap: wrap; gap: 6px; }
#visibilityButton, #notificationButton, #alertsButton {
  padding: 5px 9px;
  cursor: pointer;
  font-size: 1em;
  color: #1f170d;
  font-weight: 600;
}

/* ============ mobile ============ */
@media (max-width: 640px) {
  #v2-topbar { top: calc(var(--v2-ticker-h, 30px) + env(safe-area-inset-top, 0px) + 4px); right: 6px; gap: 6px; }
  /* 44px touch targets on phones (most of the crew explores from one) */
  #v2-profile-btn, #v2-menu-btn { height: 44px; min-width: 44px; }
  /* warning header reserves more right-padding to clear the floating buttons */
  .v2-warn-slide { padding-right: 20px; }
  #v2-topbar-discord { height: 44px; padding: 0 8px; }
  #v2-topbar-brand { height: 44px; font-size: 19px; padding: 0 2px; max-width: calc(100vw - 252px); overflow: hidden; text-overflow: ellipsis; display: block; line-height: 44px; }
  /* While the corner search is expanded there's no room left on a phone row —
     the wordmark yields, then returns (same transient pattern as the dock). */
  body:has(.maplibregl-ctrl-search.expanded) #v2-topbar-brand,
  body:has(.maplibregl-ctrl-search.expanded) #v2-topbar-discord { display: none; }
  /* corner search: 16px input avoids iOS auto-zoom */
  .maplibregl-ctrl-search input[type="text"] { font-size: 16px; }
  .maplibregl-ctrl-search.expanded { width: min(300px, calc(100vw - 60px)); }
  #v2-dock {
    bottom: calc(10px + env(safe-area-inset-bottom, 0px));
    gap: 6px;
    padding: 6px 10px;
    max-width: calc(100vw - 90px);  /* leave the add FAB's corner free */
    left: 10px;
    transform: none;                /* left-anchored: never slides under the FAB */
  }
  #v2-dock #searchButton { font-size: 0.9em; padding: 10px 12px; min-height: 44px; }
  /* mobile: same compact pill shape as desktop — override the old 60×60 slab
     that dated from when the FAB was a big vertical Material puck */
  #v2-add-fab {
    right: 8px;
    bottom: calc(20px + env(safe-area-inset-bottom, 0px));
    padding: 10px 14px 10px 10px;    /* +2px vertical for 44px thumb target */
    font-size: 14px;
  }
  #v2-add-fab .draggable-marker { width: 22px; height: 22px; }
  #v2-add-fab .add-spot-text { font-size: 14px; }
  /* maplibre's stock 29px controls are under Apple's 44px guideline — most of
     the crew is on a phone, give zoom/locate/compass/search-icon real targets */
  .maplibregl-ctrl-group button,
  .maplibregl-ctrl-search .maplibregl-ctrl-icon { width: 40px; height: 40px; }
  .maplibregl-ctrl-search { width: 40px; height: 40px; }
  .maplibregl-ctrl-search.expanded { height: 40px; }
  #menu.v2-drawer { width: 100vw; border-left: none; }
  .v2-stats-grid { grid-template-columns: repeat(2, 1fr); }
  #v2-symbol-picker button { min-width: 44px; min-height: 44px; }
  #v2-symbol-current { min-height: 44px; }
  /* transient banners on narrow screens: clear the warning header + button row */
  .notification-banner { top: calc(86px + env(safe-area-inset-top, 0px)); }
}

@media (max-height: 520px) {
  #v2-dock { bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
}

/* ============ login modal: readable card (was 25%-alpha glass over the map) ============ */
/* Scoped to #mail_loginModal only — the pro/upgrade modals keep their glass look. */
#mail_loginModal .modal-content {
  box-sizing: border-box;          /* width includes padding — was overflowing 390px phones */
  background: var(--v2-paper);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid rgba(62, 44, 24, 0.28);
  box-shadow: 0 12px 40px rgba(20, 14, 6, 0.35);
  width: min(440px, calc(100vw - 24px));
  max-height: 86vh;
  padding: 14px 16px 18px;
  overflow-y: auto;
  scrollbar-gutter: auto;
}
/* doubled selector: must out-rank the inline <style> block in the HTML (same
   specificity would lose on document order) */
#mail_loginModal .modal-content .login-headline,
#mail_loginModal#mail_loginModal .login-headline {
  font-size: 1.45em;            /* was 2.2em — three screen-tall lines on phones */
  line-height: 1.25;
  margin: 26px 0 0.4em;          /* clears the corner language chip (26px + 10px offset) */
}
/* welcome popup: language select tucked in the card's corner (original spot),
   small — the headline is the hero, not the dropdown */
#mail_loginModal .modal-content { position: relative; }
#mail_loginModal #languageSelect2 {
  position: absolute;
  top: 10px;
  left: 12px;
  z-index: 2;
  max-width: 86px;
  height: 26px;
  padding: 0 2px;
  font-size: 0.72em;
  font-family: inherit;
  color: var(--v2-ink);
  background: var(--v2-white);
  border: 1px solid var(--v2-line);
  border-radius: var(--v2-radius);
  cursor: pointer;
}
#mail_loginModal .v2-auth-tab { padding: 11px 4px; font-size: 0.92em; white-space: nowrap; }
#mail_loginModal .checklist { font-size: 0.88em; }
/* magic pane: the legacy .join-form-container lays input + Turnstile (fixed
   ~300px iframe) + button in ONE ROW — impossible on phones. Stack it. */
#mail_loginModal #v2-auth-magic .join-form-container {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  max-width: 420px;
  gap: 8px;
}
#mail_loginModal #v2-auth-magic #login_email {
  width: 100%;
  box-sizing: border-box;
  height: 42px;
  font-size: 16px; /* legacy 480px rule sets 14px -> iOS auto-zooms the primary auth field */
}
#mail_loginModal #v2-auth-magic #mail_login_submit { width: 100%; }
@media (max-width: 640px) {
  #mail_loginModal .modal-content .login-headline { font-size: 1.25em; }
  #mail_loginModal .modal-content { width: calc(100vw - 16px); max-height: 88vh; }
}

/* ============ reduced motion: decorative animation off, functional kept ============ */
/* Spinners (lds-ripple, timeline-spin, spin) stay — they communicate state.
   Pulses, drifts, bobs and pop-ins are decoration and can trigger vestibular
   discomfort; collapse them to their end state. */
@media (prefers-reduced-motion: reduce) {
  .zoom-effect,
  #draggable-marker,
  .login-headline,
  #v2-add-fab .draggable-marker,
  .v2-pin-picker-marker,
  .draggable-marker.dragging,
  .lds-ripple div,
  .comments-loading .spinner,
  .timeline-loading .spinner {
    animation: none !important;
  }
  .modal-content,
  #addSpotContent,
  #menu.v2-drawer,
  #v2-backdrop,
  #satellite-timeline-panel,
  .v2-pin-picker,
  .maplibregl-ctrl-search {
    animation: none !important;
    transition-duration: 0.01ms !important;
  }
}

/* ============ legacy full-screen overlays vs the v2 drawer ============ */
/* The isolation settings (#myNav) is a full-screen takeover — it must cover
   the drawer (z 1002) + backdrop (1001); its legacy z-index of 1000 left it
   trapped UNDER the menu it was opened from. */
#myNav { z-index: 1003; }

/* ============ links & info row (drawer) ============ */
/* one tidy line: Discord chip · Instagram · Pro badge · language select.
   Selectors carry #menu.v2-drawer to out-rank the generic
   `#menu.v2-drawer .facultative { display: block }` un-hide rule above. */
#menu.v2-drawer .v2-links-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 4px 0 8px;
}
#menu.v2-drawer .v2-links-row .discord_link,
#menu.v2-drawer .v2-links-row .social-link-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  flex: 0 0 auto;
}
.v2-links-row .social-link-row img { margin: 0; }
#menu.v2-drawer .v2-links-row #languageSelect1 {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 180px;
  margin-left: auto;     /* push the select to the right edge */
  height: 36px;
}

/* ============ add-spot sheet (redesigned: was a ghost card lost in map noise) ============ */
/* The container doubles as a dim backdrop so the form reads against any map.
   Same IDs as ever — index.js logic untouched. */
#addSpot {
  background: rgba(20, 14, 6, 0.45);
  top: 0;                          /* override .upgradeFrame's top: 2% */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  box-sizing: border-box;
}
#addSpot.hidden { display: none; }
#addSpotContent {
  position: relative;
  margin: 0;
  box-sizing: border-box;
  background: rgb(238, 229, 216);   /* opaque: the dock/map must not ghost through the sheet */
  border: 1px solid rgba(62, 44, 24, 0.28);
  border-radius: 8px;
  box-shadow: 0 12px 40px rgba(20, 14, 6, 0.35);
  width: min(460px, 100%);
  max-height: 88vh;
  overflow-y: auto;
  padding: 16px 18px 18px;
  gap: 0.7rem;
  animation: addspot-pop 0.22s ease-out;   /* replaces the 1s ghost popIn */
}
@keyframes addspot-pop {
  from { transform: translateY(14px) scale(0.98); opacity: 0; }
  to   { transform: none; opacity: 1; }
}
#addSpotContent h3 {
  font-size: 1.35em;
  margin: 0;
  padding-bottom: 0.35rem;
  padding-right: 28px;             /* clear the ✕ */
  text-align: left;
  border-bottom: 2px solid var(--v2-green, #2e7d32);
}
.addspot-coords {
  font-size: 0.78em;
  color: #6b5d4f;
  font-variant-numeric: tabular-nums;
  margin-top: -2px;
}
.addspot-coords:empty { display: none; }
/* one quiet rules box instead of two shouting cards (IDs out-rank style.css's #addSpotContent h4) */
#addSpotContent .addspot-rules {
  background: rgba(255, 255, 255, 0.55);
  border: 1px solid var(--v2-line);
  border-left: 3px solid var(--v2-green, #2e7d32);
  border-radius: var(--v2-radius);
  padding: 8px 10px;
}
#addSpotContent .addspot-rules h4 {
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  font-size: 0.84em;
  font-weight: normal;
  line-height: 1.45;
  color: #4a3f33;
}
#addSpotContent .addspot-rules h4 + h4 { margin-top: 4px; }
#addSpotForm { gap: 0.8rem; }
#addSpotForm #description {
  min-height: 64px;
  font-size: 16px;                 /* no iOS zoom */
  background: var(--v2-white);
}
#addSpotForm #description:focus {
  border-color: var(--v2-green, #2e7d32);
  box-shadow: 0 0 0 3px rgba(46, 125, 50, 0.15);
}
#addSpotForm label[for="fileToUpload"] {
  margin: 0;
  padding: 0.8rem;
  background: var(--v2-white);
  border: 2px dashed rgba(62, 44, 24, 0.3);
  color: #6b5d4f;
  font-weight: 600;
}
#addSpotForm label[for="fileToUpload"]:hover {
  background: #fff;
  border-color: var(--v2-green, #2e7d32);
  color: var(--v2-green-dark, #1b5e20);
}
#addSpotForm .preview:empty { display: none; }
#addSpotForm .preview img { border-radius: var(--v2-radius); border: 1px solid var(--v2-line); }
#addSpotForm .addspot-pro-row,
#addSpotForm div:has(> #pro_only_checkbox) {   /* out-rank style.css's yellow card */
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.86em;
  color: #4a3f33;
  background: transparent;
  border: none;
  padding: 0 2px;
}
.addspot-pro-row input[type="checkbox"] { width: 18px; height: 18px; margin: 0; flex: 0 0 auto; }
.addspot-pro-row label { cursor: pointer; }
/* the submit was a Discord-purple outline button — make it the primary action */
#addSpotForm button[type="submit"].discord-account-button {
  margin: 2px 0 0;
  padding: 12px;
  border: none;
  border-radius: var(--v2-radius);
  background: var(--v2-ink);
  color: #fff;
}
#addSpotForm button[type="submit"].discord-account-button:hover {
  background: #4a4a4a;
  color: #fff;
  transform: none;               /* legacy hover lifted the button 2px */
}
#addSpotForm button[type="submit"] .legend { font-size: 1em; }
#addSpotContent #logged-as { margin-top: 6px; }
/* phones: bottom sheet — the dropped pin stays visible above the form */
@media (max-width: 640px) {
  #addSpot { align-items: flex-end; padding: 0; }
  #addSpotContent {
    width: 100%;
    max-width: none;
    border-radius: 14px 14px 0 0;
    border-bottom: none;
    max-height: 76vh;
    padding: 14px 16px calc(16px + env(safe-area-inset-bottom, 0px));
    animation: addspot-rise 0.24s ease-out;
  }
  #addSpotContent::before {        /* grab handle */
    content: "";
    display: block;
    width: 40px;
    height: 4px;
    border-radius: 2px;
    background: rgba(62, 44, 24, 0.3);
    margin: 0 auto 10px;
  }
  @keyframes addspot-rise {
    from { transform: translateY(28px); opacity: 0.4; }
    to   { transform: none; opacity: 1; }
  }
}

/* ============================================================================
   Info panel (spot popup) redesign
   ----------------------------------------------------------------------------
   Was: a stacked list of 6 look-alike sections with big whitespace, 3
   near-duplicate external map links up top, no visible close button, and a
   safety banner that visually overlapped the panel on mobile.
   Now: hero image band → title/meta → primary CTA + overflow → grouped
   personal-marking → note → community. Sections are tighter, the panel has
   a real × close, and the map link band is one "📍 Directions" chip with
   overflow (Google Earth / Historical satellite) tucked behind ⋯.
   ============================================================================ */

/* × close button is anchored to the top-right of the panel. #info-panel is
   position:fixed (a positioned parent) so absolute works. style.css nudges it
   with translate(50%,-50%) so it STRADDLES the panel corner (floating-badge
   dismiss, à la Google Maps cards).  */
#info-panel {
  position: fixed;
  /* Flex column collapses the whitespace text nodes that would otherwise be
     preserved by style.css's `#info-panel { white-space: pre-wrap }` rule —
     that rule is there to keep comment line-breaks copyable, but as a
     side-effect it was rendering the `\n      ` between #info-panel-close
     and #info-panel-content as visible blank lines (~55px). The absolute
     close button doesn't participate in flex flow, so this is safe. */
  display: flex;
  flex-direction: column;
  /* The panel must NOT be a scroll container, for two reasons:
     (a) an abspos child anchored with `right` inside a scroller positions
         against the scrollable-content edge, not the visible box — which
         shoved the × button past the border and created a phantom
         horizontal scroll;
     (b) the corner-straddling × (translate 50%,-50%) must be able to poke
         outside the box without being clipped.
     Scrolling lives on #info-panel-content instead. */
  overflow: visible;
}
#info-panel-content {
  /* Same flex-column fix at the content level: our redesigned HTML has
     meaningful indentation between block children (and HTML comments), which
     the inherited `white-space: pre-wrap` would render as anonymous
     line-boxes at ~20px each (~400px total for this panel). */
  display: flex;
  flex-direction: column;
  /* Content is the scroll container (see #info-panel note above). min-height:0
     lets this flex item shrink below its content size so overflow kicks in.
     The negative margin + equal padding absorbs the panel's 15px padding so
     (a) the scrollbar hugs the panel edge and (b) the hero image's -15px
     bleed stays inside this box instead of tripping horizontal overflow. */
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;
  margin: -15px;
  padding: 15px;
}
#info-panel > .v2-modal-close {
  /* Floating-badge × that straddles the panel's top-right corner (style.css
     adds translate(50%,-50%)). Because half of it sits over the map, it needs
     a real surface: solid white chip, hairline border, soft shadow.
     right:6px (not 0) keeps the poked-out half inside the viewport — the
     panel sits only 10px from the screen edge. */
  top: 0;
  right: 6px;
  z-index: 4;
  width: 28px;
  height: 28px;
  min-width: 28px;
  min-height: 28px;
  padding: 0;
  border-radius: 50%;
  background: #fff;
  color: #6a5c48;                        /* warm gray glyph */
  font-size: 1.25em;
  line-height: 1;
  border: 1px solid rgba(62, 44, 24, 0.18);
  box-shadow: 0 2px 8px rgba(20, 14, 6, 0.22);
  transition: color 0.15s, background 0.15s, transform 0.1s;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
#info-panel > .v2-modal-close:hover {
  background: #f4efe6;                  /* warm paper tint on hover */
  color: #1b120a;
}
#info-panel > .v2-modal-close:active { transform: translate(50%, -50%) scale(0.92); }
#info-panel > .v2-modal-close:focus-visible {
  outline: 2px solid var(--v2-green, #4a7a52);
  outline-offset: 2px;
}

/* Hero image: 16/9 band at the very top for extras with photos. Hidden by
   default (JS unhides + populates for extras). */
.info-hero {
  display: none;
  aspect-ratio: 16 / 9;
  width: calc(100% + 30px);        /* bleed past panel's 15px horizontal padding */
  margin: -15px -15px 12px;
  overflow: hidden;
  background: #f4efe6;
  position: relative;
}
.info-hero:not(.hidden) { display: block; }
.info-hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Title + meta row */
.info-title-row {
  text-align: left !important;      /* override .info-panel-section {text-align:center} */
  padding-right: 16px;              /* small buffer under the corner-straddling × */
  /* Flex column collapses the whitespace text nodes between the H4 and the
     meta DIV — otherwise each `\n<whitespace>` between block-level siblings
     was rendered as an anonymous line-box at body's line-height:1.5 (~24px).
     That's what was inflating the title-row from ~50px to 200px+. */
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.info-title {
  margin: 0 0 4px;
  font-size: 1.05em;
  font-weight: 700;
  color: var(--v2-ink, #1b120a);
  line-height: 1.25;
  word-break: break-word;
}
.info-title:empty { display: none; }
/* No real title (only extras with names have one) → hide the whole row so it
   doesn't render as a stray divider. */
.info-title-row:has(.info-title:empty) { display: none; }

/* Action row: 3 equal-width links to external map viewers. Brand names only
   (Google Maps / Google Earth / ArcGIS are identical in all 28 languages —
   see trads.js opengmaps/openearth/openarcgis), so the HTML needs no per-lang
   variants. Stacked emoji-over-label so long brand names fit at any width. */
.info-actions-row {
  display: flex;
  align-items: stretch;
  gap: 6px;
  text-align: left !important;
}
.info-action-link {
  flex: 1 1 0;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 7px 4px;
  border-radius: var(--radius-md, 8px);
  background: rgba(0, 0, 0, 0.04);
  color: #2b1f10 !important;
  text-decoration: none !important;
  border: 1px solid rgba(0, 0, 0, 0.08);
  transition: background 0.15s, transform 0.1s;
  box-sizing: border-box;
  min-width: 0;
}
.info-action-link .ico { font-size: 1.15em; line-height: 1; }
.info-action-link .lbl {
  font-size: 0.72em;
  font-weight: 500;
  line-height: 1.15;
  text-align: center;
  overflow-wrap: break-word;
  max-width: 100%;
}
.info-action-link:hover { background: rgba(0, 0, 0, 0.08); }
.info-action-link:active { transform: scale(0.98); }

/* Tighten section spacing: 12px → 10px vertical, 8px on mobile.
   Keep dividers but soften them (was #d8cfc0, now near-transparent). */
#info-panel .info-panel-section {
  margin-bottom: 10px;
  padding-bottom: 10px;
  border-bottom-color: rgba(62, 44, 24, 0.08);
  /* Flex column collapses whitespace-only text nodes between sibling elements
     (e.g. between two `.hidden` buttons) — otherwise each `\n<spaces>` was
     rendered as an anonymous line-box at body's line-height:1.5 (~24px), which
     was inflating sections holding only-hidden children from 0 to 100px+. */
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* Some sections are still explicitly flex-row (color palette, actions row).
   Their more-specific rules below re-set flex-direction: row. */
#info-color-palette,
.info-actions-row {
  flex-direction: row !important;
}

/* Footer actions: obsolete/delete are destructive, they get a discreet look */
#info-panel .info-footer-actions {
  padding-bottom: 0;
  border-bottom: none;
  margin-bottom: 0;
}
#info-panel .info-footer-actions .btn-dark {
  opacity: 0.72;
  font-size: 0.85em;
  padding: 8px 10px;
}
#info-panel .info-footer-actions .btn-dark:hover { opacity: 1; }

/* .message-container in style.css uses box-sizing: content-box + width: 100% +
   padding: 4px 2px — that leaks 4px past the panel and creates a horizontal
   scrollbar. Scope box-sizing:border-box to the panel version so it fits. */
#info-panel #info-comments-container { box-sizing: border-box; }

/* Color palette: label on its own line, chips in a tight row below. Labels
   vary a lot in length across the 28 languages ("Change color" vs "Changer la
   couleur" vs "Промяна на цвета") — reserving the full first line for the
   label keeps the 7 chips from wrapping into ragged justify-between rows. */
#info-color-palette {
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
#info-color-palette > span {
  flex-basis: 100%;
  font-size: 0.9em;
  color: #4a3826;
  font-weight: 500;
  text-align: left;                /* match the Symbol row's label alignment */
}
#info-color-palette .icon-btn {
  min-width: 28px;
  min-height: 28px;
  padding: 0;
}

/* Symbol row: label + trigger button on the same line */
#v2-symbol-row {
  text-align: left !important;
}
.v2-symbol-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.v2-symbol-head > span {
  font-size: 0.9em;
  color: #4a3826;
  font-weight: 500;
}

/* Mobile: panel becomes a bottom sheet-ish full-width card */
@media (max-width: 640px) {
  #info-panel {
    top: auto;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    right: 8px;
    left: 8px;
    width: auto;
    max-width: none;
    max-height: 70vh;
    border-radius: 12px;
  }
  .info-hero { aspect-ratio: 21 / 9; }        /* shorter on mobile to save vertical */
  #info-panel > .v2-modal-close {
    width: 32px;
    height: 32px;
    min-width: 32px;
    min-height: 32px;
    font-size: 1.4em;
    right: 10px;                  /* 16px straddle − 8px panel offset needs more inset */
  }
  .info-title-row { padding-right: 24px; }     /* straddling × needs less gutter */
}

/* ============================================================================
   Notification panel empty states
   ----------------------------------------------------------------------------
   The 📢 alerts button used to be a silent no-op when clicked by anonymous
   users. Every click now opens the panel with a one-line state message
   (translated via trads where a key exists) instead of a blank white box.
   ============================================================================ */
.notification-empty {
  padding: 18px 16px;
  text-align: center;
}
.notification-empty p {
  margin: 0;
  color: #4a3826;
  font-size: 0.92em;
  line-height: 1.4;
}
.notification-empty-cta {
  margin-top: 12px;
  padding: 8px 22px;
  font-size: 0.9em;
  font-weight: 600;
  border-radius: var(--radius-md, 8px);
  cursor: pointer;
}

/* ============================================================================
   Cross-modal design fixes (audit pass 2, Nov 2026)
   ----------------------------------------------------------------------------
   Ten .upgradeFrame modals previously had no visible × close button (they
   dismissed via click-outside only — invisible affordance). We inserted
   `<button class="v2-modal-close" data-close="ID">` as the first child of
   each `.modal-content` and wire them through v2.js's delegated handler.
   These rules make sure the × doesn't collide with modal headers and
   patch the two modals whose content overflows horizontally.
   ============================================================================ */

/* Ensure every modal-content that hosts a v2-modal-close has enough padding
   at the top-right so its heading doesn't collide with the × button
   (position: absolute; top: 8px; right: 12px; ~36px square). */
.modal.upgradeFrame .modal-content { position: relative; }
.modal.upgradeFrame .modal-content > .v2-modal-close {
  z-index: 5;
}
.modal.upgradeFrame .modal-content > .v2-modal-close ~ * {
  /* first non-close child gets extra top space so its text isn't behind × */
}
.modal.upgradeFrame .modal-content > .v2-modal-close + * {
  padding-right: 40px;              /* first sibling reserves close-button gutter */
}

/* visibilityModal: the noUiSlider pips overhang by ~26px on mobile (400x780).
   Clip cleanly rather than showing a horizontal scrollbar. Also give the
   slider itself some horizontal padding so extreme labels stay inside. */
/* Visibility filter preset buttons (Least seen | Most seen | All): the raw
   browser button height of ~17px is below the WCAG 24px touch-target minimum,
   near-impossible to tap accurately on mobile. Bump padding + min-height so
   they render as proper chips matching the site's button aesthetic. */
#visibilityModal .text-center button {
  min-height: 32px;
  padding: 6px 12px;
  border-radius: var(--v2-btn-radius);
  border: 1px solid var(--v2-btn-line);
  background: var(--v2-btn-bg);
  color: var(--v2-ink);
  font-size: 0.9em;
  cursor: pointer;
  margin: 4px 3px;
}
#visibilityModal .text-center button:hover { background: var(--v2-btn-bg-hover); }
#visibilityModal .modal-content {
  overflow-x: hidden;
  padding-left: max(15px, env(safe-area-inset-left, 0px));
  padding-right: max(15px, env(safe-area-inset-right, 0px));
}
#visibilityModal #range_visibility { margin: 0 8px; }

/* onboardingModal: +3px overflow on mobile from an image or scroll gif that
   ignores its container. Clip so no phantom scroll bar. */
#onboardingModal .modal-content { overflow-x: hidden; }

/* commentModal: preview thumbnails + character counter can push width past
   the mobile screen if the user pastes a very long line before wrap kicks in.
   Also clip and ensure the textarea uses border-box so its width: 95% + padding
   doesn't overflow. */
#commentModal .modal-content { overflow-x: hidden; }
#commentModal textarea, #commentModal .comment-submit-btn { box-sizing: border-box; }

/* `.pro-modal-content button` (style.css L642) gives EVERY button in the pro
   upgrade / antiDumb / mail_login modals a chunky navy background + heavy
   shadow (that's the CTA style). Our new × close buttons inherit it and end
   up as 71×48 dark rectangles — jarringly loud for a dismiss affordance.
   Override with the transparent minimal styling used by every other modal. */
.pro-modal-content .v2-modal-close,
#mail_loginModal .v2-modal-close {
  padding: 0 !important;
  background: transparent !important;
  color: #555 !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  transition: none !important;
  min-width: 36px !important;
  min-height: 36px !important;
  width: auto;
  height: auto;
  font-size: 1.8em !important;
  line-height: 1;
}
.pro-modal-content .v2-modal-close:hover,
#mail_loginModal .v2-modal-close:hover {
  background: rgba(0, 0, 0, 0.08) !important;
  transform: none !important;
  color: #000 !important;
}




