*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: #FAFAF8;
}

#map {
  position: fixed; inset: 0;
  width: 100vw; height: 100vh;
}

/* MapLibre's own .maplibregl-ctrl-bottom-right (the actual stacking-context-establishing
   ancestor — not just .maplibregl-ctrl-attrib inside it, whose own z-index is capped by
   this one regardless of value) defaults to z-index:2, well below our own footer
   overlays (search ~10, fab 12, add-place bar 13). Tapping the compact "i" icon would
   expand the copyright text partially hidden underneath them instead of legible on top.
   Only needs to win against our own UI, not modals/popups above it. */
.maplibregl-ctrl-bottom-right { z-index: 14; }

#loading {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: #FAFAF8;
  font-size: 14px; color: #6B7280;
  z-index: 5;
  pointer-events: none;
}
#loading.hidden { display: none; }

.map-hint {
  position: fixed;
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  background: rgba(255,255,255,0.92);
  backdrop-filter: blur(8px);
  border-radius: 14px;
  padding: 12px 20px;
  font-size: 14px; color: #1A1A2E; font-weight: 500;
  box-shadow: 0 2px 16px rgba(0,0,0,0.2);
  z-index: 6;
  pointer-events: none;
  text-align: center;
  max-width: 280px;
}
.map-hint.hidden { display: none; }

.error-banner {
  position: fixed;
  top: 72px; left: 50%; transform: translateX(-50%);
  background: rgba(220,38,38,0.95);
  color: #fff;
  font-size: 12px; font-weight: 600;
  padding: 8px 16px;
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.25);
  z-index: 15;
  display: none;
  max-width: min(360px, calc(100vw - 32px));
  text-align: center;
}
.error-banner.visible { display: block; }

/* ── Place pins ── */
.pin {
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0,0,0,0.4);
  cursor: pointer;
}

/* ── Overlays (same glass-card pattern as /map/) ── */
.overlay {
  position: fixed;
  z-index: 10;
  pointer-events: auto;
}

.overlay-logo { top: 20px; left: 20px; }
.logo {
  display: flex; align-items: center; gap: 8px;
  text-decoration: none;
  background: rgba(255,255,255,0.92);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  padding: 8px 14px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.2);
}
.logo-mark { font-size: 18px; }
.logo-name { font-size: 15px; font-weight: 700; color: #436437; }
.logo-sub  { font-size: 12px; color: #6B7280; margin-top: 1px; }

/* ── Account (top) + style switcher/zoom icons (row below, style left, zoom icons
   right). align-items:stretch (flex default) makes the narrower of the two match the
   wider — this is what gives the account button the same width as the row below. ── */
/* z-index overrides the .overlay base (10) — needed here too, not just on .account-card:
   .overlay-account-group is itself position:fixed, its own stacking context, so
   .account-card's z-index:25 is capped at this element's level when compared against
   .place-popup (20), a sibling fixed overlay outside this group entirely. */
.overlay-account-group { top: 20px; right: 20px; z-index: 25; display: flex; flex-direction: column; gap: 8px; }
.zoomstyle-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
.zoom-slot .maplibregl-ctrl-group { margin: 0; }
/* Map + Filter share this column — flex stretch (default) gives them equal width. */
.map-filter-col { display: flex; flex-direction: column; gap: 8px; }
.style-card {
  /* position+z-index here, not just on .style-panel — see .account-card for why a
     descendant's z-index alone isn't enough to win against unrelated siblings. Higher
     than .filter-card: when it opens, style-panel occupies the exact same spot as
     filter-card right below it, and needs to paint over it, not the other way round. */
  position: relative;
  z-index: 6;
  background: rgba(255,255,255,0.92);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.2);
}
/* Floating dropdown, not pushed in-flow — same reasoning as .account-panel: opening it
   shouldn't resize/shift Map, Filter, Account or each other. */
.style-panel {
  display: none; flex-direction: column; gap: 2px;
  /* right:0, not left:0 — Map sits near the right edge of the viewport (the whole
     account/style/filter group is right-anchored), so left:0 pushed the dropdown
     further right, off toward the screen edge instead of into free space. */
  position: absolute; top: calc(100% + 8px); right: 0;
  padding: 4px 8px 8px;
  background: rgba(255,255,255,0.97);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.25);
}
.style-panel.open { display: flex; }
.style-option {
  border: none; background: transparent; border-radius: 8px;
  padding: 8px 10px; font-size: 13px; font-weight: 500; color: #1A1A2E;
  text-align: left; cursor: pointer; white-space: nowrap;
}
.style-option:hover { background: rgba(0,0,0,0.04); }
.style-option.active { background: #EDF3EA; color: #436437; font-weight: 700; }

.overlay-top {
  top: 20px; left: 50%; transform: translateX(-50%);
  width: min(420px, calc(100vw - 200px));
}
.search-wrap { position: relative; }
.search-input {
  appearance: none; width: 100%;
  background: rgba(255,255,255,0.95);
  backdrop-filter: blur(8px);
  border: none; border-radius: 12px;
  padding: 10px 40px 10px 14px;
  font-size: 14px; font-weight: 600; color: #1A1A2E;
  cursor: text; outline: none;
  box-shadow: 0 2px 16px rgba(0,0,0,0.25);
  box-sizing: border-box;
}
.search-input::placeholder { color: #9CA3AF; font-weight: 400; }
.search-btn {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 28px; height: 28px; border: none; border-radius: 8px;
  background: transparent; cursor: pointer; font-size: 14px;
}
.search-dropdown {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0;
  background: rgba(255,255,255,0.97);
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.2);
  max-height: 260px; overflow-y: auto;
  z-index: 100; display: none;
}
.search-dropdown.open { display: block; }
.search-option {
  padding: 10px 14px; cursor: pointer;
  font-size: 13px; color: #1A1A2E;
  border-bottom: 1px solid rgba(0,0,0,0.05);
}
.search-option:last-child { border-bottom: none; }
.search-option:hover { background: #EDF3EA; }

.account-card {
  /* z-index here, not just on .account-panel — a descendant's z-index only wins within
     its own ancestor's stacking context; the row below has to lose to .account-card
     itself, otherwise its later DOM position (plus the stacking context MapLibre's own
     CSS gives the reparented zoom control via `transform`) paints it on top regardless
     of the panel's own z-index. Higher than .style-card/.filter-card (6/5) — those only
     need to outrank each other, Account needs to outrank both of them too. Also higher
     than .place-popup (20) — opening Account while a place bubble is open (common on
     phones, where both live near the same corner) should bring Account to the front,
     not leave the bubble on top. Below the true modals (auth-overlay/add-place-form, 30). */
  position: relative;
  z-index: 25;
  background: rgba(255,255,255,0.92);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.2);
}
.back-btn {
  display: flex; align-items: center; gap: 6px;
  text-decoration: none;
  background: transparent;
  border-radius: 12px;
  padding: 8px 14px;
  font-size: 13px; font-weight: 500; color: #1A1A2E;
  transition: background 0.15s;
  white-space: nowrap;
  cursor: pointer; border: none;
  width: 100%;
}
.back-btn:hover { background: rgba(0,0,0,0.04); }
/* Once the user has a profile photo, Account shrinks to a small round button (same
   28px-ish size + no border as the app's own header avatar, OnboardingScreen.tsx) and
   hugs the right edge — above the zoom controls, since .zoomstyle-row below already
   puts #zoomSlot on the right (justify-content:space-between). Style/Filter and the
   zoom controls themselves are untouched either way; only Account's own card changes.
   No avatar yet (or logged out) keeps today's full-width pill exactly as it was. */
.account-card.account-card-avatar {
  align-self: flex-end; width: auto;
  background: none; backdrop-filter: none; box-shadow: none; border-radius: 50%;
}
.back-btn.account-btn-avatar {
  display: block; width: 36px; height: 36px; padding: 0; border-radius: 50%; overflow: hidden;
}
.back-btn.account-btn-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Floating dropdown, not pushed in-flow — so opening it layers over the style/zoom row
   below instead of being pushed down by or hidden under it (own background/shadow
   since it's no longer inside .account-card's box once opened). */
.account-panel {
  display: none; flex-direction: column;
  position: absolute; top: calc(100% + 8px); right: 0;
  width: min(340px, calc(100vw - 40px)); padding: 12px 16px 16px;
  max-height: calc(100vh - 100px); overflow-y: auto;
  text-align: center;
  background: rgba(255,255,255,0.97);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.25);
}
.account-panel.open { display: flex; }

/* ── Type filters — expanding panel under Map, same "card with an expanding panel"
   pattern as Style/Account, instead of a permanent chip row along the bottom eating
   into map space. ── */
.filter-card {
  /* position+z-index here, not just on .filter-panel — see .account-card. */
  position: relative;
  z-index: 5;
  background: rgba(255,255,255,0.92);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.2);
}
/* Floating dropdown, not pushed in-flow — opening it shouldn't resize/shift Map, Filter
   or Account (same reasoning as .account-panel/.style-panel). */
.filter-panel {
  display: none;
  /* right:0, not left:0 — same reasoning as .style-panel: Filter sits near the right
     edge of the viewport, so anchor the dropdown to open leftward, not off-screen. */
  position: absolute; top: calc(100% + 8px); right: 0;
  padding: 4px 10px 10px;
  background: rgba(255,255,255,0.97);
  backdrop-filter: blur(8px);
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.25);
}
.filter-panel.open { display: block; }
.filter-chip-wrap {
  display: flex; flex-wrap: wrap; gap: 6px;
  max-width: 260px;
}
.filter-chip {
  display: flex; align-items: center; gap: 6px;
  background: #F9FAFB;
  border: 1px solid #E5E7EB;
  border-radius: 20px;
  padding: 6px 12px;
  font-size: 12px; font-weight: 600; color: #1A1A2E;
  cursor: pointer; white-space: nowrap;
  transition: opacity 0.15s;
}
.filter-chip.off { opacity: 0.4; }
.filter-chip-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }

/* ── Place popup — speech bubble anchored above the tapped pin (same idea as the
   Law-Paws info bubble on RegionMapScreen), not a fixed spot on screen. left/top are
   set per-pin by near-me.js (positionPopupAt); translate(-50%,-100%) anchors the
   bubble's bottom-center — where the arrow sits — exactly on that point. ── */
.place-popup {
  position: fixed;
  left: 0; top: 0;
  transform: translate(-50%, -100%);
  width: min(340px, calc(100vw - 32px));
  background: #fff;
  border-radius: 16px;
  padding: 16px 18px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.25);
  z-index: 20;
  display: none;
}
.place-popup.open { display: block; }
.place-popup::after {
  content: '';
  position: absolute;
  bottom: -8px; left: 50%; transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 9px solid transparent;
  border-right: 9px solid transparent;
  border-top: 9px solid #fff;
  filter: drop-shadow(0 2px 1px rgba(0,0,0,0.1));
}
.popup-close {
  position: absolute; top: 10px; right: 10px;
  width: 24px; height: 24px; border: none; border-radius: 12px;
  background: #F3F4F6; color: #6B7280; font-size: 16px; cursor: pointer;
}
.popup-type {
  display: inline-block;
  font-size: 10px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: #fff; background: #436437;
  border-radius: 6px; padding: 3px 8px; margin-bottom: 8px;
}
.popup-name { font-size: 16px; font-weight: 700; color: #1A1A2E; margin-bottom: 4px; padding-right: 20px; }
.popup-address { font-size: 13px; color: #6B7280; margin-bottom: 12px; }
.popup-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.popup-actions a {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; color: #436437;
  background: #EDF3EA; border-radius: 8px; padding: 7px 11px;
  text-decoration: none;
}

/* ── Locked (source=user) popup ── */
.locked-popup { text-align: center; padding: 24px 20px; }
.locked-icon {
  width: 44px; height: 44px; border-radius: 50%;
  background: #EDF3EA; display: flex; align-items: center; justify-content: center;
  font-size: 20px; margin: 0 auto 12px;
}
.locked-text { font-size: 14px; color: #1A1A2E; line-height: 1.5; margin-bottom: 16px; }
.locked-btn {
  background: #436437; color: #fff; border: none; border-radius: 12px;
  padding: 12px 24px; font-size: 14px; font-weight: 700; cursor: pointer;
}

/* ── Auth modal ── */
.auth-overlay {
  position: fixed; inset: 0;
  background: rgba(26,26,46,0.5);
  z-index: 30;
  display: none;
  align-items: center; justify-content: center;
}
.auth-overlay.open { display: flex; }
.auth-card {
  position: relative;
  background: #fff; border-radius: 20px;
  padding: 28px 24px 24px;
  width: min(340px, calc(100vw - 40px));
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}
.auth-tabs {
  display: flex; background: #F3F4F6; border-radius: 10px; padding: 4px; margin-bottom: 14px;
}
.auth-tab {
  flex: 1; border: none; background: transparent; border-radius: 8px;
  padding: 9px; font-size: 13px; font-weight: 600; color: #6B7280; cursor: pointer;
}
.auth-tab.active { background: #fff; color: #1A1A2E; box-shadow: 0 1px 4px rgba(0,0,0,0.1); }
.auth-sub { font-size: 12px; color: #6B7280; line-height: 1.5; margin-bottom: 16px; }
.auth-input {
  display: block; width: 100%;
  border: 1px solid #E5E7EB; border-radius: 10px;
  padding: 11px 14px; font-size: 14px; color: #1A1A2E;
  margin-bottom: 10px; outline: none;
}
.auth-input:focus { border-color: #436437; }
.auth-error { font-size: 12px; color: #DC2626; margin-bottom: 8px; min-height: 14px; line-height: 1.5; }
/* Sign Up only — hidden for Sign In (returning users already agreed at registration,
   see near-me.js openAuth()). Same idea as the homepage's own .privacy-row, but
   near-me.css doesn't load base.css's CSS variables (this page is a standalone shell),
   so the colors below are the same hardcoded hex this file already uses throughout
   (#436437 primary, #6B7280 secondary, #D1D5DB borders) rather than var(--color-*). */
.auth-privacy-row { display: flex; align-items: flex-start; gap: 8px; cursor: pointer; margin-bottom: 10px; }
.auth-privacy-row input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 16px; height: 16px; min-width: 16px;
  border: 2px solid #D1D5DB; border-radius: 4px;
  background: #fff; cursor: pointer; margin-top: 1px;
  position: relative;
}
.auth-privacy-row input[type="checkbox"]:checked { background: #436437; border-color: #436437; }
.auth-privacy-row input[type="checkbox"]:checked::after {
  content: ''; position: absolute; left: 3px; top: 0px;
  width: 5px; height: 9px;
  border: 2px solid #fff; border-top: none; border-left: none;
  transform: rotate(45deg);
}
.auth-privacy-label { font-size: 12px; color: #6B7280; line-height: 1.5; }
.auth-privacy-label a { color: #436437; text-decoration: underline; }
.auth-link-btn {
  display: block; width: 100%; background: none; border: none; padding: 0;
  margin-bottom: 12px; color: #436437; font-size: 12px; font-weight: 600;
  text-decoration: underline; cursor: pointer; text-align: center;
}
.resend-link {
  background: none; border: none; padding: 0;
  color: #436437; font-size: 12px; font-weight: 700;
  text-decoration: underline; cursor: pointer;
}
.resend-link:disabled { color: #9CA3AF; cursor: default; text-decoration: none; }
.auth-submit {
  width: 100%; background: #436437; color: #fff; border: none; border-radius: 12px;
  padding: 13px; font-size: 14px; font-weight: 700; cursor: pointer;
}
.auth-submit:disabled { opacity: 0.6; cursor: default; }

/* ── Edit Profile / Delete Account ── */
/* Used as a standalone modal heading (Change Email / Confirm Deletion, centered, no
   back button) — Edit Profile itself lives inline in .account-panel now (see
   .profile-edit-header below), which already inherits that panel's own
   max-height/overflow-y, no separate scroll container needed. */
.edit-profile-title { font-size: 17px; font-weight: 700; color: #1A1A2E; margin: 0 0 14px; text-align: center; }
/* Edit Profile's own header, inline in .account-panel — back arrow + left-aligned
   title, not the centered standalone .edit-profile-title above (that's for Change
   Email/Confirm Deletion, which still float as separate small modals on top).
   Positioned absolute, floating over the top-left corner rather than taking its own
   row — otherwise it'd push the avatar below down from where it sits in the profile
   view, making it visibly jump when switching views. #profileEditView provides the
   positioning context so this aligns with .account-panel's own padding without having
   to duplicate that padding value here. Doesn't collide with the avatar itself: the
   avatar is centered and 64px wide, this sits in the narrow left margin beside it. */
#profileEditView { position: relative; }
.profile-edit-header {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; align-items: center; gap: 4px;
}
.profile-edit-back {
  background: none; border: none; padding: 4px 8px; margin-left: -8px;
  font-size: 22px; line-height: 1; color: #436437; cursor: pointer;
}
.profile-edit-title { font-size: 15px; font-weight: 700; color: #1A1A2E; }
.edit-field-label { font-size: 12px; font-weight: 600; color: #6B7280; margin-bottom: 6px; }
.edit-email-row { display: flex; align-items: center; gap: 8px; }
.edit-field-readonly {
  flex: 1;
  font-size: 14px; color: #6B7280;
  border: 1px solid #E5E7EB; border-radius: 10px;
  padding: 11px 14px; margin-bottom: 10px;
  background: #F9FAFB;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.edit-email-change-btn {
  background: none; border: none; padding: 0; margin-bottom: 10px;
  font-size: 13px; font-weight: 700; color: #436437;
  text-decoration: underline; cursor: pointer; white-space: nowrap;
}
/* .delete-confirm-btn's red is right for "Delete Account" but wrong for an affirmative
   "send this email" action — override just the color, keep its sizing/layout. */
.edit-email-send-btn { background: #436437; }
.edit-email-send-btn:disabled { opacity: 0.6; cursor: default; }
.edit-section-label {
  font-size: 12px; font-weight: 700; color: #1A1A2E;
  letter-spacing: 0.5px; text-transform: uppercase;
  margin: 18px 0 10px; padding-top: 14px; border-top: 1px solid #F3F4F6;
}
.edit-profile-success { font-size: 12px; color: #34C759; margin-bottom: 8px; min-height: 14px; line-height: 1.5; }
.edit-delete-btn {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  width: 100%; background: none; border: none;
  padding: 14px 0 4px; margin-top: 4px;
  font-size: 13px; color: #6B7280; cursor: pointer;
}
.delete-account-body { font-size: 13px; color: #6B7280; line-height: 1.5; margin-bottom: 16px; }
.delete-account-actions { display: flex; gap: 10px; margin-top: 4px; }
.delete-cancel-btn {
  flex: 1; background: #fff; border: 1.5px solid #E5E7EB; border-radius: 12px;
  padding: 12px; font-size: 14px; font-weight: 600; color: #1A1A2E; cursor: pointer;
}
.delete-confirm-btn {
  flex: 1; background: #DC2626; border: none; border-radius: 12px;
  padding: 12px; font-size: 14px; font-weight: 700; color: #fff; cursor: pointer;
}
.delete-confirm-btn:disabled { opacity: 0.6; cursor: default; }

/* ── Community correction/report actions on the place popup ── */
.popup-community-actions {
  display: flex; gap: 8px; margin-top: 12px;
  padding-top: 12px; border-top: 1px solid #F3F4F6;
}
.popup-mini-btn {
  flex: 1;
  background: #EDF3EA; color: #436437; border: none; border-radius: 8px;
  padding: 8px 10px; font-size: 12px; font-weight: 600; cursor: pointer;
}
.popup-mini-btn-danger { background: #FFF5F5; color: #DC2626; }
.mini-form { display: none; margin-top: 10px; }
.mini-form.open { display: block; }
.mini-form select.auth-input { cursor: pointer; }

/* ── Floating "add place" button ── */
.fab {
  /* Left side, clear of the native MapLibre zoom control (bottom-right) and the
     centered filter chips — was on the right before and sat right on top of zoom. */
  position: fixed;
  left: 20px; bottom: 16px;
  width: 44px; height: 44px; border-radius: 50%;
  background: #fff; color: #436437; border: 2px solid #436437;
  font-size: 24px; font-weight: 700; line-height: 1; cursor: pointer;
  box-shadow: 0 4px 16px rgba(0,0,0,0.3);
  z-index: 12;
  display: none;
  align-items: center; justify-content: center;
}
.fab.visible { display: flex; }

/* ── Add-place: crosshair + bottom bar ── */
.crosshair {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 8; display: none;
  flex-direction: column; align-items: center;
  pointer-events: none;
}
.crosshair.visible { display: flex; }
.crosshair-dot {
  width: 26px; height: 26px; border-radius: 50%;
  background: #436437; border: 3px solid #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
  margin-bottom: -3px;
}
.crosshair-stem { width: 2px; height: 14px; background: #436437; }

.add-place-bar {
  position: fixed; left: 0; right: 0; bottom: 0;
  background: #fff; border-radius: 20px 20px 0 0;
  padding: 16px 20px calc(16px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
  z-index: 13; display: none;
  text-align: center;
}
.add-place-bar.visible { display: block; }
.add-place-hint { font-size: 13px; color: #6B7280; margin: 0 0 12px; }
.add-place-bar-btns { display: flex; gap: 10px; }
.ap-search-wrap { position: relative; margin-bottom: 10px; text-align: left; }
.ap-search-wrap .auth-input { margin-bottom: 0; }
/* Bar sits at the bottom of the screen — dropdown has to open upward, not down off-screen. */
.ap-search-dropdown { top: auto; bottom: calc(100% + 4px); }
.btn-secondary, .btn-primary {
  flex: 1; border: none; border-radius: 12px; padding: 12px; font-size: 14px; font-weight: 700; cursor: pointer;
}
.btn-secondary { background: #F3F4F6; color: #6B7280; }
.btn-primary { background: #436437; color: #fff; }

/* ── Add-place form ── */
.add-place-form {
  position: fixed; inset: 0;
  background: rgba(26,26,46,0.5);
  z-index: 30; display: none;
  align-items: center; justify-content: center;
}
.add-place-form.open { display: flex; }
.form-card {
  position: relative; background: #fff; border-radius: 20px;
  padding: 24px; width: min(360px, calc(100vw - 40px));
  max-height: calc(100vh - 60px); overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}
.form-title { font-size: 18px; font-weight: 700; color: #1A1A2E; margin-bottom: 14px; }
.form-label {
  display: block; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.4px; color: #6B7280; margin: 12px 0 6px;
}
.type-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.type-chip {
  border: 1px solid #E5E7EB; background: #F9FAFB; border-radius: 20px;
  padding: 6px 12px; font-size: 12px; font-weight: 600; color: #6B7280; cursor: pointer;
}
.type-chip.active { background: #436437; border-color: #436437; color: #fff; }

/* ── Community profile panel ── */
.profile-loading { font-size: 13px; color: #6B7280; padding: 12px 0 4px; }
.profile-avatar-wrap { position: relative; width: 64px; margin: 0 auto 10px; }
.profile-avatar {
  width: 64px; height: 64px; border-radius: 50%;
  background: #EDF3EA; font-size: 28px;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  cursor: pointer;
}
.profile-avatar img { width: 100%; height: 100%; object-fit: cover; }
/* Same corner-badge idea as the app's own cameraBtn on EditProfileScreen. */
.profile-avatar-edit {
  position: absolute; right: -2px; bottom: -2px;
  width: 24px; height: 24px; border-radius: 50%;
  background: #436437; border: 2px solid #fff;
  font-size: 11px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0;
}
.profile-avatar-edit:disabled { opacity: 0.6; cursor: default; }
.profile-avatar-error { font-size: 11px; color: #DC2626; text-align: center; margin-bottom: 4px; min-height: 13px; }
.edit-avatar-remove-btn {
  display: block; margin: 0 auto 10px;
  background: none; border: none; padding: 0;
  font-size: 12px; color: #DC2626; text-decoration: underline; cursor: pointer;
}
.edit-avatar-remove-btn:disabled { opacity: 0.6; cursor: default; }
.profile-name { font-size: 16px; font-weight: 700; color: #1A1A2E; }
.profile-level { font-size: 14px; color: #436437; font-weight: 600; margin-top: 4px; }
.profile-points { font-size: 12px; color: #6B7280; margin-top: 4px; }
/* Tabs — same pill pattern as .auth-tabs */
.profile-tabs {
  display: flex; background: #F3F4F6; border-radius: 10px; padding: 4px;
  margin: 16px 0 14px;
}
.profile-tab {
  flex: 1; border: none; background: transparent; border-radius: 8px;
  padding: 8px 4px; font-size: 12px; font-weight: 600; color: #6B7280; cursor: pointer;
}
.profile-tab.active { background: #fff; color: #1A1A2E; box-shadow: 0 1px 4px rgba(0,0,0,0.1); }
.profile-tab-panel { text-align: left; }

/* Badges tab — all badges, earned + locked, same grid idea as the app's badgeGrid */
.profile-badge-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.profile-badge-card {
  background: #F9FAFB; border: 1px solid #E5E7EB; border-radius: 12px;
  padding: 12px 8px; text-align: center;
}
.profile-badge-card.locked { opacity: 0.6; }
.profile-badge-emoji { font-size: 26px; }
.profile-badge-label { font-size: 11px; font-weight: 700; color: #1A1A2E; margin-top: 4px; }
.profile-badge-sub { font-size: 10px; color: #6B7280; margin-top: 3px; }

/* Statistics tab — summary chips + 12-month bar chart + points legend */
.profile-summary-row { display: flex; gap: 8px; }
.profile-summary-chip {
  flex: 1; background: #F9FAFB; border: 1px solid #E5E7EB; border-radius: 12px;
  padding: 10px; text-align: center;
}
.profile-summary-num { font-size: 18px; font-weight: 700; color: #436437; }
.profile-summary-lbl { font-size: 10px; color: #6B7280; margin-top: 2px; }
.profile-chart-title { font-size: 12px; color: #1A1A2E; font-weight: 600; margin: 16px 0 8px; }
.profile-chart { display: flex; align-items: flex-end; height: 80px; gap: 3px; }
.profile-bar-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 0; }
.profile-bar-value { font-size: 8px; color: #6B7280; }
.profile-bar-track { width: 100%; height: 50px; background: #F3F4F6; border-radius: 3px; display: flex; align-items: flex-end; }
.profile-bar-fill { width: 100%; background: #436437; border-radius: 3px; min-height: 2px; }
.profile-bar-month { font-size: 7px; color: #6B7280; }
.profile-legend {
  background: #F9FAFB; border: 1px solid #E5E7EB; border-radius: 12px;
  padding: 12px; margin-top: 14px;
}
.profile-legend-title { font-size: 12px; font-weight: 700; color: #1A1A2E; margin-bottom: 6px; }
.profile-legend-row { display: flex; justify-content: space-between; font-size: 12px; color: #6B7280; padding: 3px 0; }
.profile-legend-row span:last-child { color: #436437; font-weight: 600; }

/* Activity tab — own submissions, paginated */
.profile-activity-list { display: flex; flex-direction: column; }
.profile-activity-row {
  display: flex; align-items: center; gap: 8px; padding: 10px 0;
  border-bottom: 1px solid #F3F4F6;
}
.profile-activity-row:last-child { border-bottom: none; }
.profile-activity-icon { font-size: 15px; }
.profile-activity-info { flex: 1; min-width: 0; }
.profile-activity-place {
  font-size: 12px; font-weight: 600; color: #1A1A2E;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.profile-activity-meta { display: flex; align-items: center; gap: 6px; margin-top: 2px; }
.profile-activity-date { font-size: 10px; color: #6B7280; }
.profile-activity-status { font-size: 10px; font-weight: 600; }
.profile-activity-pts { font-size: 12px; font-weight: 700; color: #436437; flex-shrink: 0; }
.profile-activity-empty { font-size: 12px; color: #6B7280; text-align: center; padding: 16px 0; }
.profile-load-more {
  width: 100%; background: transparent; border: none; color: #436437;
  font-size: 12px; font-weight: 700; padding: 10px 0; cursor: pointer;
}

.profile-signout {
  margin-top: 18px; width: 100%;
}

/* ── SEO intro card — injected server-side by maps/category.php and maps/city.php
   (real, crawlable <h1>/<p>/<a> text, not JS-rendered), absent entirely on plain
   /near-me/. Same glass-card language as the rest of the page; dismissible since it's
   a landing hook, not something that should permanently sit in the way of the map. ── */
.overlay-seo-intro { top: 76px; left: 50%; transform: translateX(-50%); width: min(480px, calc(100vw - 40px)); }
.seo-intro-card {
  position: relative;
  background: rgba(255,255,255,0.95);
  backdrop-filter: blur(8px);
  border-radius: 14px;
  padding: 14px 40px 14px 16px;
  box-shadow: 0 2px 16px rgba(0,0,0,0.2);
  max-height: 40vh;
  overflow-y: auto;
}
.seo-breadcrumb { font-size: 11px; color: #6B7280; margin-bottom: 6px; }
.seo-breadcrumb a { color: #436437; text-decoration: none; font-weight: 600; }
.seo-breadcrumb a:hover { text-decoration: underline; }
.seo-intro-card h1 { font-size: 17px; font-weight: 700; color: #1A1A2E; margin-bottom: 6px; }
.seo-intro-card p { font-size: 13px; color: #1A1A2E; line-height: 1.5; }
.seo-close {
  position: absolute; top: 10px; right: 10px;
  width: 22px; height: 22px; border: none; border-radius: 11px;
  background: #F3F4F6; color: #6B7280; font-size: 14px; cursor: pointer;
}
.seo-city-links { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.seo-city-links a {
  font-size: 12px; font-weight: 600; color: #436437;
  background: #EDF3EA; border-radius: 14px; padding: 5px 10px;
  text-decoration: none;
}
.seo-city-links a:hover { background: #DCE9D6; }

/* ── Disclaimer ── */
#disclaimer {
  position: fixed;
  bottom: 4px; left: 50%; transform: translateX(-50%);
  font-size: 10px; color: rgba(26,26,46,0.4);
  z-index: 9;
  pointer-events: none;
  white-space: nowrap;
}
/* Privacy/Terms links need to stay clickable even though the rest of this element is
   deliberately click-through (sits low over the map, shouldn't intercept map drags).
   Hidden along with the rest of #disclaimer on mobile (below) — the sign-up modal's
   own Privacy Policy link (shown at the actual point of consent) still covers that
   case either way. */
#disclaimer a { pointer-events: auto; color: rgba(26,26,46,0.6); text-decoration: underline; }

/* ── Responsive ── */
@media (max-width: 640px) {
  /* Search moves to the footer — up top it was squeezed between the logo and the
     account/style/filter cluster on narrow screens, forcing them to overlap. Sits
     directly beside the add-place fab (bottom-left) rather than spanning the full
     width above it — left:76px reserves the fab's space even when it's hidden
     (anonymous user / zoomed out), so nothing jumps around when it appears. right:44px
     leaves room for MapLibre's own compact attribution ("i") icon at bottom-right —
     that control already handles click-to-reveal copyright text on its own, nothing
     custom needed there. Dropdown opens upward, same as .ap-search-dropdown, so it
     doesn't run off the bottom of the viewport. */
  .overlay-top {
    top: auto; bottom: 16px; left: 76px; right: 44px; transform: none;
    width: auto;
  }
  .search-dropdown { top: auto; bottom: calc(100% + 4px); }
  #disclaimer { display: none; }
}
