/*
 * Converge PWA shared styles
 * Loaded on all user-facing pages to handle:
 *   - safe-area insets (notch / dynamic island)
 *   - pull-to-refresh containment
 *   - app-like text selection behavior
 *   - install + update banner UI
 *   - design tokens (via the @import below)
 *
 * Keep this file small; per-page styles live in each HTML file.
 */

/* Design tokens — loaded first so every page picks up the canonical
   variables (--color-*, --font-*, --space-*, etc.). Source of truth
   lives in docs/design/tokens.md. */
@import url('./tokens.css');

/* Prevent iOS pull-to-refresh from reloading mid-checkin */
html {
  overscroll-behavior-y: contain;
}

/* Safe-area insets — works alongside viewport-fit=cover.
   Top padding pushes flow content below the notch / Dynamic Island /
   status-bar area. The body's background still paints under the notch
   (padding area shows background-color), so pages with dark backgrounds
   keep the full-bleed look while their content stays legible.

   NOTE: top padding uses !important because several per-page inline
   <style> blocks override body padding with shorthand (e.g. `padding: 0
   0 60px`), and those blocks come after this file in document order.
   !important is the pragmatic way to protect a platform-level safety
   inset from being zeroed out by per-page layout choices. Bottom and
   side padding are deliberately NOT !important so pages that set their
   own bottom clearance (for tab bars, sticky buttons, etc.) still work. */
body {
  padding-top: env(safe-area-inset-top) !important;
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
}

/* Fixed-position top bars (navs, headers, modals) aren't affected by
   body padding because they're positioned against the viewport. Any
   page-level element that pins itself to the top opts into safe-area
   clearance by setting `data-pwa-safe-top` on its opening tag, or by
   class name if it already has one of these conventional names. */
[data-pwa-safe-top],
.top-nav[style*="fixed"],
header[style*="fixed"],
.app-header,
.mobile-nav {
  padding-top: calc(env(safe-area-inset-top) + 0px);
}

/* App-like: don't long-press-select interactive chrome, but DO allow
   selection on content (venue names, addresses, descriptions). */
button,
a.btn,
.btn,
.chip,
.plan-card,
.nav-item,
nav a {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* ── Desktop side-rail nav ─────────────────────────────────────────
   The per-page .bottom-nav is a fixed bottom tab bar on phones. On
   viewports ≥960px it converts to a left side rail. Body picks up
   matching left padding so content doesn't slide under it.

   Scope notes:
   - body:has(.bottom-nav) keeps the landing page unaffected — it
     uses .site-nav (top bar), not .bottom-nav, so the rule won't
     match and no left padding is added.
   - html:not(.landing-mode) excludes the explore-map iframe embedded
     on the landing page (?landing=1 sets the class), so the iframe
     stays full-bleed.
   - !important is needed because per-page <style> blocks come after
     pwa.css in document order; same convention as the safe-area
     padding-top rule above. */
@media (min-width: 960px) {
  html:not(.landing-mode) body:has(.bottom-nav) {
    padding-left: 80px !important;
  }
  html:not(.landing-mode) .bottom-nav {
    top: 0 !important;
    bottom: 0 !important;
    right: auto !important;
    left: 0 !important;
    width: 80px !important;
    flex-direction: column !important;
    justify-content: flex-start !important;
    gap: 4px !important;
    padding: calc(env(safe-area-inset-top) + 16px) 0
             calc(env(safe-area-inset-bottom) + 16px) !important;
    border-top: none !important;
    border-right: 1px solid rgba(255, 255, 255, 0.06);
  }
  html:not(.landing-mode) .bottom-nav .bnav-item {
    flex: 0 0 auto !important;
    padding: 10px 4px !important;
  }
  html:not(.landing-mode) .bottom-nav .bnav-icon svg {
    width: 24px !important;
    height: 24px !important;
  }

  /* Fixed-position chrome (position:fixed elements anchored to the
     viewport, not the content area) slides under the 80px rail
     because body padding-left doesn't reach them. Each fixed
     selector that uses a small `left:` value needs to shift right
     by the rail width. Selectors are scoped to body:has(.bottom-nav)
     so the landing page is unaffected.

     Selectors below cover every fixed-position element with a left
     anchor that exists on PWA pages today; if a new page adds its
     own fixed chrome, extend this block. */
  html:not(.landing-mode) body:has(.bottom-nav) .map-controls,
  html:not(.landing-mode) body:has(.bottom-nav) .filter-bar-outer,
  html:not(.landing-mode) body:has(.bottom-nav) .filter-panel {
    left: 80px !important;
  }
  html:not(.landing-mode) body:has(.bottom-nav) .time-scrubber {
    left: 92px !important; /* 80 rail + 12 gutter */
  }
  /* Center-anchored elements: shift center by half the rail width so
     they center over the content area, not the viewport. */
  html:not(.landing-mode) body:has(.bottom-nav) .teaser-cta,
  html:not(.landing-mode) body:has(.bottom-nav) .map-hint-pill {
    left: calc(50% + 40px) !important;
  }
}

/* ── Shared banner styling for install + update prompts ────────────── */
.converge-pwa-banner {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(16px + env(safe-area-inset-bottom));
  max-width: 456px;
  margin: 0 auto;
  background: #222240;
  border: 1px solid rgba(124, 92, 255, 0.35);
  border-radius: 16px;
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  z-index: 9999;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
  animation: converge-pwa-slide-up 260ms ease-out;
}

@keyframes converge-pwa-slide-up {
  from { transform: translateY(120%); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.converge-pwa-banner-text {
  flex: 1;
  color: #FAF7F2;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 13px;
  line-height: 1.3;
}
.converge-pwa-banner-text strong {
  font-weight: 700;
  font-size: 14px;
}
.converge-pwa-banner-text span {
  color: #B0ADA8;
}
.converge-pwa-banner-text b {
  color: #FAF7F2;
  font-weight: 600;
}

.converge-pwa-banner-actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.converge-pwa-btn-primary,
.converge-pwa-btn-ghost {
  border: none;
  border-radius: 10px;
  padding: 9px 14px;
  font-family: inherit;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}

.converge-pwa-btn-primary {
  background: #7C5CFF;
  color: #FAF7F2;
}
.converge-pwa-btn-primary:active {
  background: #d04d44;
}

.converge-pwa-btn-ghost {
  background: transparent;
  color: #B0ADA8;
}
.converge-pwa-btn-ghost:active {
  color: #FAF7F2;
}

/* ── iOS install-instructions card ─────────────────────────────────
   Instruction-only (iOS has no install API). The × dismisses; the
   down-arrow points at Safari's bottom toolbar where the real Share
   button lives. */
.converge-pwa-ios-card {
  position: fixed;
  left: 12px;
  right: 12px;
  /* Bottom offset leaves room for Safari's own bottom toolbar (~50px)
     plus the safe-area inset. This keeps our arrow ending just above
     the Share button rather than overlapping it. */
  bottom: calc(64px + env(safe-area-inset-bottom));
  max-width: 456px;
  margin: 0 auto;
  background: #222240;
  border: 1px solid rgba(124, 92, 255, 0.35);
  border-radius: 16px;
  padding: 14px 44px 22px 16px; /* extra right-pad for the × button */
  z-index: 9999;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
  animation: converge-pwa-slide-up 260ms ease-out;
  color: #FAF7F2;
}

.converge-pwa-ios-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 13px;
  line-height: 1.35;
}
.converge-pwa-ios-body strong {
  font-weight: 700;
  font-size: 14px;
}
.converge-pwa-ios-body span {
  color: #B0ADA8;
}
.converge-pwa-ios-body b {
  color: #FAF7F2;
  font-weight: 600;
}

.converge-pwa-ios-share-icon {
  display: inline-block;
  width: 13px;
  height: 13px;
  vertical-align: -2px;
  color: #7C5CFF;
}

.converge-pwa-ios-close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
  color: #B0ADA8;
  font-size: 22px;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  border-radius: 50%;
  -webkit-tap-highlight-color: transparent;
}
.converge-pwa-ios-close:active {
  color: #FAF7F2;
  background: rgba(255, 255, 255, 0.08);
}

.converge-pwa-ios-arrow {
  position: absolute;
  bottom: -16px;
  left: 50%;
  transform: translateX(-50%);
  color: #7C5CFF;
  font-size: 20px;
  line-height: 1;
  font-weight: 700;
  animation: converge-pwa-arrow-nudge 1.8s ease-in-out infinite;
  pointer-events: none;
  text-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
}

@keyframes converge-pwa-arrow-nudge {
  0%, 100% { transform: translateX(-50%) translateY(0); opacity: 0.7; }
  50% { transform: translateX(-50%) translateY(4px); opacity: 1; }
}
