:root {
  --navy-0: #070d15;
  --navy-1: #0d1620;
  --navy-2: #14202c;
  --navy-3: #1e2d3a;
  --blue-text: #c3d3e5;
  --blue-dim: #7d93ab;
  --cyan: #5cc0d6;
  /* Shared with js/app.js's LIVE_POSITION_COLOR (the live-position marker's
     fill) - both "this is live/current" indicators, so kept the same red. */
  --live-red: #ff3b3b;
  /* Map control buttons only (zoom/compass/follow) - lighter than --navy-2
     so their background plate actually reads as a raised control sitting on
     top of the map, rather than blending into the dark basemap beneath it. */
  --ctrl-bg: #24384a;
  --ctrl-bg-hover: #2f4a60;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--navy-0);
  font-family: -apple-system, "Segoe UI", Roboto, "Noto Sans", sans-serif;
  color: var(--blue-text);
}

#map {
  position: absolute;
  inset: 0;
}

.maplibregl-ctrl-attrib {
  background: rgba(7, 13, 21, 0.75) !important;
  color: var(--blue-dim) !important;
}
.maplibregl-ctrl-attrib a { color: var(--blue-text) !important; }

.maplibregl-ctrl-group {
  background: var(--ctrl-bg) !important;
  border: 1px solid var(--navy-3);
}
.maplibregl-ctrl-group button { filter: invert(1) hue-rotate(180deg) brightness(1.3); }

/* Not a .maplibregl-ctrl-group (deliberately) - that class's `button` rule
   above inverts icon colors for MapLibre's own light-on-dark PNG icons,
   which would also invert this button's red pulse into cyan. Styled to
   match that group's look (background, border, and now also corner radius -
   both var(--ctrl-bg)/4px, not this control's own separate lighter/rounder
   pill) by hand instead. Still a labeled pill's worth of *content* (icon +
   "Follow" text, not just a bare icon square) - just boxed the same as
   every other map control now. */
.follow-ctrl {
  background: var(--ctrl-bg);
  border: 1px solid var(--navy-3);
  border-radius: 4px;
  overflow: hidden;
}
.follow-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 29px;
  padding: 0 12px 0 10px;
  border: none;
  background: transparent;
  cursor: pointer;
  color: var(--blue-dim);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}
.follow-btn:hover { background: var(--ctrl-bg-hover); }
.follow-btn:active { transform: scale(0.97); }
.follow-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--blue-dim);
  flex: 0 0 auto;
}
/* Enabled = shared across everyone's open tab (see js/app.js's follow-mode
   polling), so the pulse needs to read as "this is on for everyone right
   now", not just a hover/focus state - hence red, not the usual cyan accent,
   on both the dot and the label text. The dot's opacity is driven by app.js's
   syncedPulse (inline style, not a CSS animation) - same clock as the
   live-position marker's shine layer, so the two visibly pulse in lockstep
   rather than two independent clocks drifting in and out of phase. */
.follow-btn.active {
  color: var(--live-red);
}
.follow-btn.active .follow-dot {
  background: var(--live-red);
  box-shadow: 0 0 6px 1px rgba(255, 59, 59, 0.7);
}

#tracker-panel {
  position: absolute;
  left: 14px;
  bottom: 30px;
  z-index: 5;
  background: rgba(13, 22, 32, 0.88);
  border: 1px solid var(--navy-3);
  border-radius: 10px;
  padding: 10px 14px;
  /* Fits whatever's actually showing (the 3-line summary, or the wider
     detail rows) rather than a fixed box - app.js animates between the two
     by measuring actual widths and transitioning an explicit px value; this
     max-content/max-width pair is just the resting state once that inline
     style is cleared. */
  width: max-content;
  max-width: min(320px, calc(100vw - 28px));
  max-height: calc(100vh - 60px);
  overflow-y: auto;
  backdrop-filter: blur(6px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  transition: width 0.36s cubic-bezier(0.4, 0, 0.2, 1);
}
#tracker-panel.hidden { display: none; }

/* Every "label: value" row (summary and detail alike) is a two-column grid
   with the same label-column width, so every value - "3m ago", "83%",
   "350.45 km (43.3%)" - starts at the exact same x no matter how long its
   own label is. */
.trow {
  display: grid;
  grid-template-columns: 118px 1fr;
  column-gap: 8px;
  font-size: 12.5px;
  color: var(--blue-text);
  padding: 2px 0;
  line-height: 1.4;
}
.trow-label {
  color: var(--blue-dim);
}
.trow-label::after {
  content: ':';
}
.trow-continuation {
  padding-top: 0;
}
.trow-continuation .trow-label::after {
  content: '';
}
.trow-value a {
  color: var(--cyan);
  text-decoration: none;
}
.trow-value a:hover { text-decoration: underline; }
.trow-battery .trow-value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.trow-battery svg { flex: 0 0 auto; }

/* Always present in the DOM (see renderTrackerPanel) - collapsed to
   nothing via max-height/opacity rather than display:none, purely so the
   open/close has something to actually transition between. max-height's
   target (480px) is a generous cap above the tallest this content gets, not
   a measured value - max-height transitions animate against that number
   directly, not the content's real height, so keeping it reasonably close
   keeps the animation speed feeling consistent instead of mostly elapsing
   through unused range. Width and height/opacity animate together here;
   since the panel is briefly narrower than its final width while this
   opens, rows can wrap onto an extra line for a moment and the panel grows
   a bit past its settled height before snapping back down once the width
   catches up - a known, accepted quirk, not a bug to chase further. */
.tracker-detail {
  /* width: 0 (not just max-height: 0/overflow: hidden) matters here: an
     ancestor sized via `width: max-content` (the panel) still measures a
     hidden-but-present child's full content width for that computation
     unless the child's own width is explicitly pinned - overflow: hidden
     alone only clips paint, it doesn't stop the intrinsic-size contribution
     that was making the panel just as wide collapsed as expanded. */
  width: 0;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  margin-top: 0;
  transition: max-height 0.36s ease-in-out, opacity 0.3s ease-in-out, margin-top 0.36s ease-in-out;
}
.tracker-detail.expanded {
  width: auto;
  max-height: 480px;
  opacity: 1;
  margin-top: 4px;
}
.tracker-detail hr {
  border: none;
  border-top: 1px solid var(--navy-3);
  margin: 6px 0;
}
.tracker-offtrack {
  color: #ffb4b4;
  font-weight: 700;
  font-size: 12.5px;
  padding: 2px 0 6px;
}

/* A full-width, unmistakably clickable bar rather than a bare icon - text
   names the action, the arrow just reinforces open/closed state. */
.tracker-expand-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin-top: 8px;
  padding: 6px 0;
  border: 1px solid var(--navy-3);
  border-radius: 6px;
  background: var(--navy-2);
  color: var(--cyan);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  text-align: center;
}
.tracker-expand-btn:hover { background: var(--navy-3); }
.tracker-expand-btn:active { transform: scale(0.98); }
.tracker-expand-arrow {
  font-size: 10px;
}

.mp-popup h3 {
  margin: 0 0 4px;
  font-size: 13.5px;
  color: var(--navy-1);
}
.mp-popup p {
  margin: 2px 0;
  font-size: 12px;
  color: #2c3d4e;
}
.mp-popup .mp-stats {
  color: #0e6b6b;
  font-weight: 600;
}
.mp-popup .mp-folder {
  color: #8393a3;
  font-style: italic;
}

.maplibregl-popup-content {
  background: #eef4fa;
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(0,0,0,0.4);
}
.maplibregl-popup-tip { border-top-color: #eef4fa !important; border-bottom-color: #eef4fa !important; }

#loading {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--navy-0);
  color: var(--blue-dim);
  font-size: 13px;
  letter-spacing: 0.04em;
  z-index: 10;
  transition: opacity 0.4s ease;
  pointer-events: none;
}
#loading.hidden { opacity: 0; }
