:root {
  /* Two greens, because they sit on opposite backgrounds. `--track-map` draws
     the hiked track onto *light* OpenTopoMap tiles; `--track` is the UI accent
     on the dark chrome. A single mid-green fails contrast on one or the other. */
  --track-map: #15803d;
  --track: #22c55e;
  --green: #22c55e;
  --red: #f87171;
  --info: #60a5fa;

  /* Dark chrome. `--paper` is a surface, `--ink` is text on it. */
  --ink: #e8edf5;
  --muted: #94a3b8;
  --line: #33415580;
  --paper: #131a26;
  --paper-2: #1c2534;
  --scrim: rgba(255, 255, 255, .07);

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  /* On dark surfaces, elevation reads through a light rim rather than a shadow,
     so each shadow carries an inset hairline. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .04);
  --shadow-md: 0 4px 10px -2px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(255, 255, 255, .05);
  --shadow-lg: 0 12px 28px -6px rgba(0, 0, 0, .65), inset 0 1px 0 rgba(255, 255, 255, .06);

  --header-h: 52px;
  --ctl-h: 32px;   /* shared height: source selector, legend, 3D switch */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);

  color-scheme: dark;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overscroll-behavior: none;
  color: var(--ink);
  background: #0b1017;
}

button { font: inherit; color: inherit; }

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

/* ------------------------------------------------------------------ topbar */

.topbar {
  position: absolute;
  z-index: 3;
  top: 0;
  left: 0;
  right: 0;
  padding: calc(var(--safe-t) + .55rem) .85rem .55rem;
  background: rgba(11, 16, 23, .82);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
}

.topbar-row {
  display: flex;
  align-items: center;
  gap: .75rem;
  min-height: 28px;
}

.brand {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -.01em;
  white-space: nowrap;
}

/* The status message is a pill next to the title, not the title itself. */
.status {
  display: flex;
  align-items: center;
  gap: .4rem;
  min-width: 0;
  margin-left: auto;
  padding: .25rem .6rem .25rem .5rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper-2);
}
.status-dot {
  width: .55rem;
  height: .55rem;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--muted);
}
/* The dot carries a faint glow of its own color -- on a dark surface a flat
   6px dot reads as a speck. */
.status[data-level="green"] .status-dot { background: var(--green); box-shadow: 0 0 0 3px #22c55e26; }
.status[data-level="red"]   .status-dot { background: var(--red);   box-shadow: 0 0 0 3px #f8717133; }
.status[data-level="info"]  .status-dot { background: var(--info);  box-shadow: 0 0 0 3px #60a5fa26; }
.status[data-level="red"] { border-color: #7f1d1d; background: #2a1416; }
/* Not started, or over: hollow, so nothing on the banner looks like a live pulse. */
.status[data-level="idle"] .status-dot { background: none; box-shadow: inset 0 0 0 2px var(--muted); }

.status-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: .8rem;
  font-weight: 600;
  max-width: 46vw;
}

.status-meta {
  margin: .3rem 0 0;
  color: var(--muted);
  font-size: .72rem;
  font-variant-numeric: tabular-nums;
}

/* Keep MapLibre's controls clear of the topbar and the dock. `--dock-h` is the
   dock's measured height, set by map.js -- the dock grows a row on narrow
   screens, so a hardcoded offset would either overlap it or float above it. */
.maplibregl-ctrl-top-right { top: calc(var(--safe-t) + var(--header-h) + .5rem); }
.maplibregl-ctrl-bottom-left { bottom: calc(var(--dock-h, 96px) + .25rem); }
.maplibregl-ctrl-bottom-right { bottom: calc(var(--dock-h, 96px) + .25rem); }

/* MapLibre's controls ship as white boxes with near-black icons. Repaint the
   surfaces and invert the icons, which are background-image SVGs we can't
   recolor directly. Never touch their `position`. */
.maplibregl-ctrl-group {
  border-radius: var(--r-md) !important;
  box-shadow: var(--shadow-md) !important;
  background: var(--paper) !important;
  border: 1px solid var(--line);
}
.maplibregl-ctrl-group button + button { border-top: 1px solid var(--line); }
.maplibregl-ctrl-group button:not(:disabled):hover { background: var(--scrim); }
.maplibregl-ctrl-group button .maplibregl-ctrl-icon { filter: invert(1) brightness(1.6); }

.maplibregl-ctrl-scale {
  border-color: var(--muted);
  background: rgba(19, 26, 38, .72);
  color: var(--ink);
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  font-size: 10px;
  font-weight: 600;
}

.maplibregl-ctrl-attrib {
  font-size: 10px;
  background: rgba(19, 26, 38, .78) !important;
  color: var(--muted);
}
.maplibregl-ctrl-attrib a { color: var(--ink); }
.maplibregl-ctrl-attrib-button { filter: invert(1) brightness(1.6); }

/* -------------------------------------------------------------------- fabs */

/* Sits just above the attribution/scale row, which sits just above the dock. */
.fabs {
  position: absolute;
  z-index: 2;
  right: .6rem;
  bottom: calc(var(--dock-h, 96px) + 0.5rem);
}

.fab {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--paper);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  transition: transform .12s ease, opacity .12s ease, background .12s ease;
}
.fab:hover { background: var(--paper-2); }
.fab:active { transform: scale(.94); }
.fab:disabled { opacity: .45; cursor: default; }
.fab svg { width: 22px; height: 22px; }
.fab svg circle, .fab svg path { fill: none; stroke: var(--track); stroke-width: 1.9; stroke-linecap: round; }
.fab svg circle:first-child { fill: var(--track); stroke: none; }
.fab svg .ring { opacity: .45; }

/* -------------------------------------------------------------------- dock */

.dock {
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  gap: .4rem;
  padding: .45rem .5rem calc(var(--safe-b) + .5rem);
  background: linear-gradient(to top, rgba(11, 16, 23, .94) 58%, rgba(11, 16, 23, 0));
  pointer-events: none;
}
.dock-row { display: flex; align-items: center; gap: .5rem; }
/* Source selector | legend | 3D switch, all on one line at --ctl-h. */
.dock-row-split { justify-content: space-between; padding: 0 .1rem; }
.dock-row-split > * { height: var(--ctl-h); }

/* Day chips: a clean scrollable row, color-coded by route. */
.days {
  display: flex;
  gap: .35rem;
  overflow-x: auto;
  scrollbar-width: none;
  padding: .15rem;
  margin: -.15rem;
  pointer-events: auto;
}
.days::-webkit-scrollbar { display: none; }
/* `display: flex` beats the UA's `[hidden] { display: none }`, so restate it. */
.days[hidden], .segmented[hidden] { display: none; }

/* Route source selector: alpenvereinaktiv | bergfex | Off */
.segmented {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  box-shadow: var(--shadow-sm);
  pointer-events: auto;
  /* Shrinks and scrolls before it pushes the legend or the switch off-row. */
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.segmented::-webkit-scrollbar { display: none; }

.seg {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  height: 100%;
  padding: 0 .7rem;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--muted);
  font-size: .74rem;
  font-weight: 600;
  white-space: nowrap;
  text-transform: capitalize;
  cursor: pointer;
  transition: color .12s ease, background .12s ease;
}
.seg:hover { color: var(--ink); }
.seg[aria-checked="true"] {
  background: var(--paper-2);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}

/* Two targets in one pill: `.day-toggle` shows/hides the route, `.day-info`
   opens its stats. Both stay >=34px tall for thumbs. */
.day {
  display: inline-flex;
  align-items: stretch;
  flex: 0 0 auto;
  min-height: 34px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  color: var(--muted);
  font-size: .8rem;
  font-weight: 600;
  box-shadow: var(--shadow-sm);
  transition: color .12s ease, border-color .12s ease, background .12s ease;
}
.day:hover { border-color: #475569; }
.day .swatch { background: currentColor; opacity: .35; }

.day-toggle, .day-info {
  display: inline-flex;
  align-items: center;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.day-toggle { gap: .4rem; padding: 0 .6rem 0 .75rem; border-radius: 999px 0 0 999px; }
.day-toggle:active { transform: scale(.97); }

.day-info {
  justify-content: center;
  min-width: 30px;
  padding: 0 .1rem;
  border-left: 1px solid var(--line);
  border-radius: 0 999px 999px 0;
  font-style: italic;
  font-family: Georgia, "Times New Roman", serif;
  opacity: .75;
}
.day-info:hover, .day-info:active { opacity: 1; background: var(--scrim); }

/* Tint the chip with its own route color. Mixing *into the dark surface* keeps
   the fill dark, so the light label stays legible. */
.day[data-on="true"] {
  color: color-mix(in srgb, var(--c) 70%, #fff);
  border-color: color-mix(in srgb, var(--c) 55%, transparent);
  background: color-mix(in srgb, var(--c) 20%, var(--paper));
}
.day[data-on="true"] .swatch { background: var(--c); opacity: 1; }
.day[data-on="true"] .day-info { border-left-color: color-mix(in srgb, var(--c) 45%, transparent); }

.swatch {
  width: .6rem;
  height: .6rem;
  flex: 0 0 auto;
  border-radius: 3px;
}
.swatch-track { background: var(--track); }

.legend {
  display: inline-flex;
  align-items: center;
  flex: 0 1 auto;
  min-width: 0;
  gap: .4rem;
  padding: 0 .5rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  box-shadow: var(--shadow-sm);
  color: var(--muted);
  font-size: .74rem;
  font-weight: 600;
  white-space: nowrap;
  pointer-events: none;
}

/* Switch */
.switch {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  gap: .45rem;
  padding: 0 .5rem 0 .6rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  pointer-events: auto;
}
.switch-label { color: var(--muted); font-size: .74rem; font-weight: 600; }
.switch-btn {
  position: relative;
  width: 42px;
  height: 24px;
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #263143;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
/* The "on" fill must contrast with the *knob*, which is near-white. `--ink` is
   near-white in this theme, so the accent color carries the state instead. */
.switch-btn[aria-checked="true"] { background: var(--track); border-color: var(--track); }
.switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #f8fafc;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
  transition: transform .15s ease;
}
.switch-btn[aria-checked="true"] .switch-knob { transform: translateX(18px); }

/* ------------------------------------------------------------ bottom sheet */

.sheet {
  position: absolute;
  z-index: 4;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 62vh;
  overflow-y: auto;
  padding: .5rem 1.1rem calc(var(--safe-b) + 1.2rem);
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: 0 -10px 40px rgba(0, 0, 0, .6);
  animation: rise .2s cubic-bezier(.22, 1, .36, 1);
}
@keyframes rise { from { transform: translateY(100%); } }

.sheet-grip {
  width: 36px;
  height: 4px;
  margin: .15rem auto .9rem;
  border-radius: 2px;
  background: var(--line);
}
.sheet-close {
  position: absolute;
  top: .25rem;
  right: .4rem;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--muted);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}
.sheet-close:hover { background: var(--scrim); }

.sheet h2 { margin: 0 0 .15rem; font-size: 1.05rem; letter-spacing: -.01em; }
.sheet .sub { margin: 0 0 1rem; color: var(--muted); font-size: .82rem; line-height: 1.4; }

.kv {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .45rem 1rem;
  margin: 0;
  font-size: .88rem;
}
.kv dt { color: var(--muted); }
.kv dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }
/* The upload lag is context for the stamp beside it, not a value of its own. */
.kv .delay { display: block; color: var(--muted); font-weight: 500; font-size: .8rem; }

.profile { width: 100%; height: 118px; margin-top: 1rem; overflow: visible; }
.profile .area { fill: color-mix(in srgb, var(--c) 22%, transparent); stroke: none; }
.profile .line { fill: none; stroke: color-mix(in srgb, var(--c) 75%, #fff); stroke-width: 1.75; stroke-linejoin: round; }
.profile text { font-size: 10px; fill: var(--muted); font-weight: 600; }

/* --------------------------------------------------------- map decorations */

/* No `position: relative` here. MapLibre positions the marker with its own
   `.maplibregl-marker { position: absolute }`, which this rule would override
   (same specificity, loaded later) -- the marker would then lay out as a block
   and stretch the full width of the map. `absolute` already anchors ::after. */
.last-seen {
  width: max-content;
  padding: .3rem .55rem;
  border-radius: var(--r-sm);
  background: var(--track-map); /* sits on the map, so it uses the map green */
  color: #fff;
  font-size: .72rem;
  font-weight: 700;
  white-space: nowrap;
  box-shadow: var(--shadow-md);
  pointer-events: none;
}
.last-seen::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -4px;
  width: 8px;
  height: 8px;
  transform: translateX(-50%) rotate(45deg);
  background: var(--track-map);
}

/* Below ~446px the selector + legend + switch cannot share a row. The legend is
   decorative and the other two are controls, so it is the one that goes; the
   green track speaks for itself. */
@media (max-width: 449px) {
  .legend { display: none; }
}

@media (min-width: 900px) {
  .sheet { left: auto; right: 1rem; bottom: 1rem; width: 380px; border-radius: var(--r-lg); }
  .dock { padding-inline: 1rem; }
  .status-text { max-width: 32vw; }
}
