/* PUBLIC SIDE — trip review UI. Built against docs/ comp (2026-08-15).
   Dark instrument styling, deliberately distinct from the Pi's public/ dashboard:
   this app is backwards-looking and time-controlled, that one is real-time. */

:root {
  --bg:        #0b0f16;
  --panel:     #141a24;
  --panel-2:   #1a2130;
  --panel-3:   #212a3a;
  --border:    #242e3d;
  --border-2:  #2f3a4d;
  --text:      #e7eef9;
  --text-dim:  #94a3b8;
  --text-mute: #64748b;

  --blue:   #4a9eff;
  --green:  #34d399;
  --amber:  #f59e0b;
  --red:    #f87171;
  --purple: #a78bfa;
  --cyan:   #22d3ee;
  --orange: #fb923c;

  --r-sm: 7px;
  --r:    10px;
  --r-lg: 14px;

  --gap: 14px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}

button { font-family: inherit; color: inherit; cursor: pointer; }
a { color: var(--blue); }

/* ---------------------------------------------------------------- login */

.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
  background:
    radial-gradient(1100px 620px at 50% -10%, #16283f 0%, transparent 60%),
    var(--bg);
}

.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 30px 28px 24px;
  box-shadow: 0 20px 60px rgba(0,0,0,.5);
}

.login-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 24px; }
.brand-mark {
  display: grid; place-items: center;
  width: 42px; height: 42px; border-radius: var(--r);
  background: linear-gradient(150deg, #2a6fd4, #1d4d97);
  color: #fff;
}
.brand-name { font-size: 17px; font-weight: 640; letter-spacing: -.2px; }
.brand-sub  { font-size: 12px; color: var(--text-mute); margin-top: 1px; }

.field { display: block; margin-bottom: 15px; }
.field > span { display: block; font-size: 12px; color: var(--text-dim); margin-bottom: 6px; }
.field input {
  width: 100%; padding: 10px 12px;
  background: #0e131c;
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  color: var(--text); font-size: 14px;
}
.field input:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(74,158,255,.15); }

.btn-primary {
  width: 100%; padding: 11px;
  background: var(--blue); border: 0; border-radius: var(--r-sm);
  color: #06101f; font-size: 14px; font-weight: 640;
  margin-top: 4px;
}
.btn-primary:hover { background: #63aeff; }

.login-error {
  background: rgba(248,113,113,.1);
  border: 1px solid rgba(248,113,113,.35);
  color: #fecaca;
  padding: 9px 11px; border-radius: var(--r-sm);
  font-size: 13px; margin: 0 0 15px;
}
.login-foot { font-size: 11.5px; color: var(--text-mute); line-height: 1.55; margin: 18px 0 0; }

/* ---------------------------------------------------------------- shell */

.topbar {
  /* Wrapping is unconditional: with a fixed single line the chip overflowed the
     viewport by a few px in the gap between breakpoints (760px measured). */
  display: flex; align-items: center; flex-wrap: wrap; gap: 16px; row-gap: 8px;
  padding: 10px 18px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 40;
}
.topbar .brand-mark { width: 34px; height: 34px; border-radius: 9px; }
.topbar-brand { display: flex; align-items: center; gap: 10px; }
.topbar-title { font-size: 16px; font-weight: 640; letter-spacing: -.2px; white-space: nowrap; }

.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px;
  font-size: 11px; font-weight: 640; letter-spacing: .4px;
  text-transform: uppercase;
}
.pill-blue  { background: rgba(74,158,255,.16); color: #8cc4ff; }
.pill-green { background: rgba(52,211,153,.14); color: #6ee7b7; }
.pill-amber { background: rgba(245,158,11,.14); color: #fcd34d; }
.pill-grey  { background: rgba(148,163,184,.14); color: var(--text-dim); }

.topbar-spacer { flex: 1; }

.range-select, .plain-select {
  background: var(--panel-2);
  border: 1px solid var(--border-2);
  border-radius: var(--r-sm);
  color: var(--text);
  padding: 7px 11px;
  font-size: 13px;
}
.range-select:focus, .plain-select:focus { outline: none; border-color: var(--blue); }

.user-chip { display: flex; align-items: center; gap: 9px; min-width: 0; }
.avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: linear-gradient(150deg, #3f7fd6, #2a5697);
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700; color: #fff;
}
.user-name { font-size: 13px; font-weight: 560; }
.user-group { font-size: 11px; color: var(--text-mute); }
.link-quiet { color: var(--text-mute); font-size: 12px; text-decoration: none; }
.link-quiet:hover { color: var(--text); }

main { padding: var(--gap); display: flex; flex-direction: column; gap: var(--gap); }

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.panel-head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 16px 0;
}
.panel-title {
  font-size: 12px; font-weight: 700; letter-spacing: .8px;
  text-transform: uppercase; color: var(--text);
}
.panel-note { font-size: 11.5px; color: var(--text-mute); font-weight: 400; text-transform: none; letter-spacing: 0; }

/* ---------------------------------------------------------------- stage */

.stage { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap); }

/* The stage is a 2-col grid and the right column is taller, so the map panel is
   stretched to match. A fixed-height map then leaves dead space beneath it —
   fill the panel instead. */
.map-panel { position: relative; overflow: hidden; padding: 0; min-height: 430px; }
#map { position: absolute; inset: 0; border-radius: var(--r-lg); background: #0e1520; }

.map-legend {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  display: flex; gap: 14px; align-items: center;
  background: rgba(16,22,32,.86);
  backdrop-filter: blur(8px);
  border: 1px solid var(--border-2);
  border-radius: var(--r);
  padding: 7px 12px;
  font-size: 11.5px; color: var(--text-dim);
}
.legend-item { display: flex; align-items: center; gap: 6px; }
.legend-dot { width: 9px; height: 9px; border-radius: 50%; }
.legend-line { width: 16px; height: 3px; border-radius: 2px; }

/* Coverage mode swaps which set of swatches the legend shows; the toggle stays. */
.legend-std, .legend-cov { display: flex; gap: 14px; align-items: center; }
.map-legend .legend-cov { display: none; }
.map-legend.cov-on .legend-cov { display: flex; }
.map-legend.cov-on .legend-std { display: none; }

.legend-toggle {
  border: 1px solid var(--border-2); background: transparent; color: var(--text-dim);
  border-radius: 999px; padding: 3px 10px; font-size: 11px; cursor: pointer;
}
.legend-toggle:hover { color: var(--text); border-color: var(--text-mute); }
.legend-toggle.on { color: var(--blue); border-color: var(--blue); }

/* Mapbox popup, restyled for the dark app (its default chrome is white).
   Scoped under .map-panel for specificity: mapbox-gl.css loads AFTER this file,
   so a bare .mapboxgl-popup-content selector loses to the library's own. */
.map-panel .mapboxgl-popup-content {
  background: rgba(16,22,32,.95); color: var(--text);
  border: 1px solid var(--border-2); border-radius: var(--r);
  padding: 10px 26px 10px 12px; font: inherit;
  box-shadow: 0 6px 24px rgba(0,0,0,.5);
}
.map-panel .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip { border-top-color: rgba(16,22,32,.95); }
.map-panel .mapboxgl-popup-anchor-top .mapboxgl-popup-tip { border-bottom-color: rgba(16,22,32,.95); }
.map-panel .mapboxgl-popup-anchor-left .mapboxgl-popup-tip { border-right-color: rgba(16,22,32,.95); }
.map-panel .mapboxgl-popup-anchor-right .mapboxgl-popup-tip { border-left-color: rgba(16,22,32,.95); }
.map-panel .mapboxgl-popup-close-button { color: var(--text-dim); font-size: 16px; }

.cov-pop { font-size: 12px; line-height: 1.55; min-width: 170px; }
.cov-pop .cov-when { color: var(--text-dim); font-size: 11px; }
.cov-pop .cov-grade { font-weight: 600; font-size: 13px; margin-bottom: 2px; }
.cov-pop .cov-row { color: var(--text-dim); }
.cov-pop .cov-row b { color: var(--text); font-weight: 500; }

.map-empty {
  position: absolute; inset: 0; display: grid; place-items: center;
  text-align: center; color: var(--text-mute); font-size: 13px; padding: 24px;
}

/* --- moment panel */

.moment-head {
  display: flex; align-items: baseline; gap: 10px;
  padding: 13px 16px 10px; flex-wrap: wrap;
}
.moment-when { font-size: 12px; color: var(--text-dim); }
.moment-place { font-size: 12.5px; color: var(--text-dim); display: flex; align-items: center; gap: 5px; }
.moment-panel { display: flex; flex-direction: column; }

.tiles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  padding: 0 16px 12px;
}
.tile {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 11px 12px 12px;
  min-width: 0;
}
.tile-head { display: flex; align-items: center; gap: 7px; margin-bottom: 7px; }
.tile-icon { width: 22px; height: 22px; display: grid; place-items: center; border-radius: 6px; flex: none; }
.tile-label {
  font-size: 11px; color: var(--text-dim); font-weight: 560;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tile-value { font-size: 23px; font-weight: 660; letter-spacing: -.6px; line-height: 1.1; }
.tile-value .unit { font-size: 12px; font-weight: 500; color: var(--text-dim); margin-left: 2px; }
.tile-sub { font-size: 11.5px; color: var(--text-dim); margin-top: 3px; }
.tile-foot {
  font-size: 11px; color: var(--text-mute);
  margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--border);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tile.is-empty .tile-value { color: var(--text-mute); font-size: 15px; font-weight: 500; }

.media-panel {
  margin: 0 16px 16px; padding: 22px;
  background: var(--panel-2);
  border: 1px dashed var(--border-2);
  border-radius: var(--r);
  display: grid; place-items: center; gap: 8px;
  color: var(--text-mute); font-size: 12.5px; text-align: center;
  min-height: 96px;
}

/* ---------------------------------------------------------------- scrubber */

.scrub { padding: 12px 16px 14px; }
.scrub-top {
  display: flex; align-items: center; gap: 14px;
  flex-wrap: wrap; margin-bottom: 12px;
}
.transport { display: flex; align-items: center; gap: 6px; }
.tbtn {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  background: var(--panel-2); border: 1px solid var(--border-2);
  border-radius: 8px; color: var(--text-dim);
}
.tbtn:hover { background: var(--panel-3); color: var(--text); }
.tbtn.play {
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--blue); border-color: var(--blue); color: #06101f;
}
.tbtn.play:hover { background: #63aeff; }
.tbtn:disabled { opacity: .35; cursor: not-allowed; }

.scrub-clock { display: flex; align-items: baseline; gap: 9px; }
.clock-date { font-size: 15px; font-weight: 640; letter-spacing: -.2px; }
.clock-time { font-size: 15px; font-weight: 500; color: var(--text-dim); font-variant-numeric: tabular-nums; }

.speeds { display: flex; gap: 3px; background: var(--panel-2); border-radius: 8px; padding: 3px; }
.speed {
  padding: 5px 11px; border-radius: 6px; border: 0; background: transparent;
  color: var(--text-dim); font-size: 12px; font-weight: 560;
}
.speed.active { background: var(--blue); color: #06101f; }

/* --- the track */

.track-wrap { position: relative; padding: 4px 0 0; }
.track {
  position: relative; height: 16px;
  background: var(--panel-2);
  border-radius: 8px;
  cursor: pointer;
  overflow: hidden;
}
.track-seg { position: absolute; top: 0; bottom: 0; }
.seg-driving   { background: var(--blue); }
.seg-stopped   { background: var(--orange); }
.seg-overnight { background: #7c5cd6; }

/* Sits in .track-wrap, not .track. Two reasons it used to vanish: .track clips its
   overflow, and .seg-driving raises itself to z-index 2 — so the head was painted
   underneath every blue driving stretch, which is most of a travel day. */
.track-head {
  position: absolute; top: 0; left: 0; width: 14px; height: 24px;
  margin-left: -7px; pointer-events: none; will-change: transform;
  display: grid; place-items: center;
  z-index: 6;
}
.track-head::after {
  content: ''; width: 14px; height: 14px; border-radius: 50%;
  background: #fff; border: 3px solid var(--purple);
  box-shadow: 0 0 0 3px rgba(11,15,22,.9), 0 2px 8px rgba(0,0,0,.6);
}
.track-input {
  position: absolute; inset: -6px 0; width: 100%;
  opacity: 0; cursor: pointer; margin: 0;
}

.track-axis {
  display: flex; justify-content: space-between;
  margin-top: 7px; font-size: 11px; color: var(--text-mute);
}
.scrub-legend { display: flex; gap: 14px; justify-content: flex-end; margin-top: 8px; font-size: 11.5px; color: var(--text-dim); }

/* ---------------------------------------------------------------- lowers */

.lowers { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: var(--gap); }

.chart-box { padding: 12px 16px 16px; height: 268px; position: relative; }
.chart-legend {
  display: flex; flex-wrap: wrap; gap: 12px;
  padding: 8px 16px 0; font-size: 11.5px; color: var(--text-dim);
}
.chart-legend button {
  display: flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 0; color: inherit; font-size: inherit;
}
.chart-legend button.off { opacity: .38; text-decoration: line-through; }

.kv-list { padding: 10px 16px 16px; display: flex; flex-direction: column; gap: 2px; }
.kv-row {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 0; border-bottom: 1px solid var(--border);
}
.kv-row:last-child { border-bottom: 0; }
.kv-icon { width: 26px; height: 26px; display: grid; place-items: center; color: var(--text-mute); flex: none; }
.kv-body { min-width: 0; flex: 1; }
.kv-label { font-size: 11.5px; color: var(--text-dim); }
.kv-value { font-size: 14px; font-weight: 600; margin-top: 1px; }
.kv-value .unit { font-size: 11px; font-weight: 500; color: var(--text-dim); margin-left: 2px; }
.kv-sub { font-size: 11px; color: var(--text-mute); margin-top: 1px; }

.empty-note {
  padding: 26px 18px; text-align: center;
  color: var(--text-mute); font-size: 12.5px; line-height: 1.6;
}
.empty-note strong { color: var(--text-dim); font-weight: 600; }

/* ---------------------------------------------------------------- statusbar */

.statusbar {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 18px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  font-size: 12.5px;
}
.status-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--green); flex: none; }
.status-dot.warn { background: var(--amber); }
.status-dot.alert { background: var(--red); }
.status-text { color: var(--text-dim); }
.status-right { margin-left: auto; color: var(--text-mute); display: flex; align-items: center; gap: 14px; }

/* ---------------------------------------------------------------- misc */

.hidden { display: none !important; }

.loading-veil {
  position: fixed; inset: 0; z-index: 90;
  display: grid; place-items: center;
  background: var(--bg); color: var(--text-mute); font-size: 13px;
  transition: opacity .25s ease;
}
.loading-veil.gone { opacity: 0; pointer-events: none; }

.toast {
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  background: var(--panel-3); border: 1px solid var(--border-2);
  color: var(--text); padding: 9px 15px; border-radius: 999px;
  font-size: 12.5px; z-index: 80;
  opacity: 0; transition: opacity .2s ease; pointer-events: none;
}
.toast.show { opacity: 1; }

/* Mapbox chrome, toned down to match the panels */
.mapboxgl-ctrl-group { background: rgba(16,22,32,.9) !important; border: 1px solid var(--border-2) !important; }
.mapboxgl-ctrl-group button + button { border-top: 1px solid var(--border-2) !important; }
.mapboxgl-ctrl-icon { filter: invert(85%); }
.mapboxgl-ctrl-attrib { background: rgba(11,15,22,.7) !important; }
.mapboxgl-ctrl-attrib a { color: var(--text-mute) !important; }

.rv-marker {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--blue); border: 3px solid #fff;
  box-shadow: 0 2px 10px rgba(0,0,0,.6);
  display: grid; place-items: center; color: #06101f;
  cursor: grab;
}
/* The marker is draggable along the route — say so on hover, and make the grab
   obvious while it is happening. */
.rv-marker:hover { box-shadow: 0 2px 14px rgba(0,0,0,.75), 0 0 0 4px rgba(74,144,266,.28); }
.rv-marker.is-dragging,
.rv-marker:active { cursor: grabbing; box-shadow: 0 2px 16px rgba(0,0,0,.8), 0 0 0 6px rgba(74,144,266,.36); }
.stop-marker {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--orange); border: 2px solid rgba(11,15,22,.8);
}
.stop-marker.overnight { background: #7c5cd6; }

/* ---------------------------------------------------------------- responsive */

@media (max-width: 1180px) {
  .lowers { grid-template-columns: 1fr 1fr; }
  .lowers > .panel:first-child { grid-column: 1 / -1; }
}
@media (max-width: 980px) {
  .stage { grid-template-columns: 1fr; }
  #map { height: 320px; }
  .tiles { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
  .lowers { grid-template-columns: 1fr; }
  .topbar { flex-wrap: wrap; gap: 10px; }
  .scrub-top { gap: 10px; }
  .scrub-legend { justify-content: flex-start; }
  .user-meta { display: none; }
}

/* ================================================================ admin area */

.admin-body { background: var(--bg); }
.admin-main { max-width: 1180px; margin: 0 auto; padding: 20px 16px 60px;
              display: flex; flex-direction: column; gap: var(--gap); }

.admin-nav { display: flex; gap: 4px; }
.admin-nav a {
  padding: 6px 12px; border-radius: 7px; font-size: 13px;
  color: var(--text-dim); text-decoration: none;
}
.admin-nav a:hover { background: var(--panel-2); color: var(--text); }
.admin-nav a.on { background: var(--panel-3); color: var(--text); font-weight: 560; }

.admin-head h1 { font-size: 22px; margin: 6px 0 4px; letter-spacing: -.4px; }
.admin-sub { color: var(--text-dim); font-size: 13px; line-height: 1.65; margin: 0; max-width: 76ch; }
.admin-sub strong { color: var(--text); font-weight: 600; }

/* flash */
.flash {
  padding: 11px 14px; border-radius: var(--r);
  font-size: 13.5px; border: 1px solid;
}
.flash-ok  { background: rgba(52,211,153,.10); border-color: rgba(52,211,153,.35); color: #a7f3d0; }
.flash-bad { background: rgba(248,113,113,.10); border-color: rgba(248,113,113,.35); color: #fecaca; }
.flash-secret {
  margin-top: 10px; padding: 12px; border-radius: var(--r-sm);
  background: rgba(0,0,0,.30); display: flex; flex-direction: column; gap: 5px;
}
.flash-secret span { font-size: 11.5px; color: var(--text-dim); }
.flash-secret code {
  font-family: var(--mono); font-size: 17px; color: #fff;
  letter-spacing: .3px; user-select: all;
}
.flash-secret em { font-size: 11.5px; color: var(--text-mute); font-style: normal; }

/* stat tiles */
.stat-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--gap); }
.stat-tile {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 14px 16px;
}
.stat-tile.stat-warn { border-color: rgba(245,158,11,.45); }
.stat-value { font-size: 27px; font-weight: 660; letter-spacing: -.8px; line-height: 1.1; }
.stat-label { font-size: 12px; color: var(--text-dim); margin-top: 3px; }
.stat-sub   { font-size: 11px; color: var(--text-mute); margin-top: 2px; }

/* forms */
.form-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; padding: 14px 16px 16px; }
.form-row.compact { padding: 0 0 12px; }
.form-row .field { margin: 0; flex: 1 1 170px; min-width: 140px; }
.form-note { flex: 1 1 100%; font-size: 11.5px; color: var(--text-mute); margin: 0; }

.btn-inline { width: auto; padding: 10px 18px; margin: 0; }
.btn-quiet {
  padding: 8px 13px; border-radius: var(--r-sm); font-size: 12.5px;
  background: var(--panel-2); border: 1px solid var(--border-2); color: var(--text-dim);
}
.btn-quiet:hover { background: var(--panel-3); color: var(--text); }
.btn-sm { padding: 5px 10px; font-size: 11.5px; }
.btn-danger {
  padding: 8px 13px; border-radius: var(--r-sm); font-size: 12.5px;
  background: rgba(248,113,113,.10); border: 1px solid rgba(248,113,113,.35); color: #fca5a5;
}
.btn-danger:hover { background: rgba(248,113,113,.20); color: #fecaca; }
.inline-form { display: inline-flex; gap: 6px; align-items: center; margin: 0; }
.mini-input {
  padding: 7px 10px; font-size: 12.5px; width: 210px;
  background: #0e131c; border: 1px solid var(--border-2);
  border-radius: var(--r-sm); color: var(--text);
}
.mini-input:focus { outline: none; border-color: var(--blue); }

.add-panel > summary {
  padding: 13px 16px; cursor: pointer; font-size: 13.5px;
  font-weight: 560; color: var(--text-dim); list-style: none;
}
.add-panel > summary::-webkit-details-marker { display: none; }
.add-panel > summary:hover { color: var(--text); }
.add-panel[open] > summary { border-bottom: 1px solid var(--border); }

/* user cards */
.user-card.is-off { opacity: .6; }
.user-card-head { display: flex; align-items: center; gap: 12px; padding: 14px 16px; flex-wrap: wrap; }
.uc-id { min-width: 0; }
.uc-name { font-size: 15px; font-weight: 620; display: flex; align-items: center; gap: 8px; }
.uc-email { font-size: 12px; color: var(--text-mute); margin-top: 1px; }
.uc-usage { display: flex; gap: 22px; margin-left: auto; flex-wrap: wrap; }
.uc-stat { text-align: right; }
.uc-stat-label { display: block; font-size: 10.5px; color: var(--text-mute);
                 text-transform: uppercase; letter-spacing: .5px; }
.uc-stat-value { display: block; font-size: 14px; font-weight: 600; margin-top: 2px; }
.uc-stat-value.dim  { color: var(--text-mute); font-weight: 500; }
.uc-stat-value.warn { color: var(--amber); }

.user-card-body { padding: 0 16px 14px; border-top: 1px solid var(--border); padding-top: 13px; }
.uc-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.uc-meta { font-size: 11.5px; color: var(--text-mute); margin-left: auto; }
.uc-meta strong { color: var(--text-dim); font-weight: 600; }
.uc-meta em { font-style: normal; color: var(--amber); }

/* groups */
.group-head { display: flex; align-items: center; gap: 10px; padding: 14px 16px; flex-wrap: wrap; }
.group-name { font-size: 15px; font-weight: 620; display: flex; align-items: center; gap: 9px; }
.group-slug {
  font-family: var(--mono); font-size: 11px; color: var(--text-mute);
  background: var(--panel-2); padding: 2px 7px; border-radius: 5px;
}
.group-members { font-size: 11.5px; color: var(--text-mute); margin-top: 2px; }
.group-body {
  display: grid; grid-template-columns: 1fr 1fr; gap: 24px;
  padding: 14px 16px 18px; border-top: 1px solid var(--border);
}
.group-col .field { margin-bottom: 14px; }

.radio-stack { display: flex; flex-direction: column; gap: 6px; }
.radio-row, .cap-row {
  display: flex; gap: 9px; align-items: flex-start;
  padding: 9px 11px; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--panel-2);
  cursor: pointer;
}
.radio-row:hover, .cap-row:hover { border-color: var(--border-2); }
.radio-row input, .cap-row input { margin: 2px 0 0; accent-color: var(--blue); flex: none; }
.radio-row strong, .cap-row strong { display: block; font-size: 13px; font-weight: 580; }
.radio-row em, .cap-row em {
  display: block; font-style: normal; font-size: 11.5px;
  color: var(--text-mute); margin-top: 2px; line-height: 1.45;
}
.radio-row:has(input:checked), .cap-row:has(input:checked) {
  border-color: rgba(74,158,255,.5); background: rgba(74,158,255,.07);
}
.cap-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.cap-row.cap-danger:has(input:checked) {
  border-color: rgba(245,158,11,.5); background: rgba(245,158,11,.08);
}

/* tables */
.table-wrap { overflow-x: auto; }
.admin-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.admin-table th {
  text-align: left; font-size: 10.5px; text-transform: uppercase; letter-spacing: .6px;
  color: var(--text-mute); font-weight: 600;
  padding: 10px 14px; border-bottom: 1px solid var(--border);
}
.admin-table td { padding: 10px 14px; border-bottom: 1px solid var(--border); vertical-align: top; }
.admin-table tr:last-child td { border-bottom: 0; }
.admin-table tr:hover td { background: rgba(255,255,255,.018); }
.admin-table .mono { font-family: var(--mono); font-size: 11.5px; color: var(--text-dim); }
.cell-sub { font-size: 11px; color: var(--text-mute); margin-top: 2px; }
.cell-right { text-align: right; }
.row-fail td { color: var(--text-dim); }

.dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 6px; }
.dot-ok  { background: var(--green); }
.dot-bad { background: var(--red); }

.panel-blurb {
  padding: 4px 16px 12px; font-size: 12px; color: var(--text-mute);
  line-height: 1.6; max-width: 90ch;
}
.panel-blurb code {
  font-family: var(--mono); font-size: 11px;
  background: var(--panel-2); padding: 1px 5px; border-radius: 4px; color: var(--text-dim);
}

@media (max-width: 900px) {
  .stat-row { grid-template-columns: repeat(2, 1fr); }
  .group-body { grid-template-columns: 1fr; gap: 14px; }
  .cap-grid { grid-template-columns: 1fr; }
  .uc-usage { margin-left: 0; gap: 16px; }
  .uc-stat { text-align: left; }
  .admin-nav { order: 3; width: 100%; }
}

/* ---------------------------------------------------------------- media strip */

.media-strip {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  margin: 0 16px 16px;
}
.media-strip.is-empty { grid-template-columns: 1fr; }

.media-shot { margin: 0; background: var(--panel-2); border: 1px solid var(--border);
              border-radius: var(--r); overflow: hidden; }
/* Two stacked layers per camera so a new still can be decoded off-screen and
   revealed by a cross-fade. Rebuilding the <img> instead left a blank frame on
   roughly a quarter of playback frames at 30 m/s. */
.shot-stack {
  display: block; position: relative;
  width: 100%; aspect-ratio: 16 / 9; background: #0e1520;
}
.media-shot img.shot-layer {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0; transition: opacity 110ms linear;
}
.media-shot img.shot-layer.is-on { opacity: 1; }

/* A camera with no frame near this instant keeps its box and says so, so the strip
   is the same height whether or not there is a picture. */
.media-shot.is-blank .shot-stack::after {
  content: 'No frame near this moment';
  position: absolute; inset: 0; display: grid; place-items: center;
  padding: 0 14px; text-align: center;
  font-size: 11.5px; color: var(--text-mute);
  background: repeating-linear-gradient(-45deg,
    rgba(255,255,255,.014) 0 10px, transparent 10px 20px), var(--panel-2);
}

@media (prefers-reduced-motion: reduce) {
  .media-shot img.shot-layer { transition: none; }
}
.media-shot a { display: block; }
.media-shot figcaption {
  display: flex; align-items: baseline; gap: 8px;
  padding: 7px 10px; font-size: 11px; color: var(--text-mute);
}
.media-shot figcaption strong { color: var(--text-dim); font-weight: 600; font-size: 11.5px; }

.media-empty {
  padding: 22px; background: var(--panel-2);
  border: 1px dashed var(--border-2); border-radius: var(--r);
  display: grid; place-items: center; gap: 8px; text-align: center;
  color: var(--text-mute); font-size: 12.5px; line-height: 1.55; min-height: 96px;
}
.media-empty strong { color: var(--text-dim); }

@media (max-width: 620px) { .media-strip { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------------- level panel
   Built to the operator's IMU comp (2026-08-16): bubble target + numeric roll and
   pitch + front/side attitude silhouettes. Spans two tile columns.

   The RV artwork is hand-drawn SVG, not the manufacturer's product photography —
   this page is shared with invited people, and it also has to rotate, recolour with
   the theme, and stay sharp at any size. */

.tile-wide { grid-column: span 2; }
.tile-wide .tile-value { font-size: 15px; }

.level-body { display: flex; gap: 14px; align-items: center; }

/* No reading at this instant: keep the layout, drop the confidence. The silhouettes
   would otherwise sit dead level and read as a measurement of "level". */
.tile.is-nodata .level-body,
.tile.is-nodata .attitude-row { opacity: .38; filter: grayscale(1); }
.tile.is-nodata .att-note { visibility: hidden; }

.level-dial { flex: none; position: relative; width: 136px; height: 132px; }
.level-dial svg { display: block; }
.dial-ring    { fill: none; stroke: var(--border-2); }
.dial-cross   { stroke: var(--border-2); stroke-dasharray: 2 3; }
.dial-tick    { fill: var(--text-mute); font-size: 7px; letter-spacing: .5px; }
.dial-bubble  { fill: var(--green); stroke: rgba(0,0,0,.5); stroke-width: 1; }
.dial-bubble.off   { fill: var(--amber); }
.dial-bubble.bad   { fill: var(--red); }
.dial-bubble.raw   { fill: var(--text-dim); }
.dial-center  { fill: none; stroke: var(--border-2); }

.level-readout { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.lr-item { }
.lr-label { font-size: 10px; color: var(--text-mute); text-transform: uppercase; letter-spacing: .6px; }
.lr-value { font-size: 21px; font-weight: 660; letter-spacing: -.5px; line-height: 1.15; }
.lr-axis  { font-size: 10px; color: var(--text-mute); }

.level-badge {
  align-self: flex-start; margin-top: 2px; white-space: nowrap;
  padding: 4px 10px; border-radius: 6px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase;
}
.lb-ok   { background: rgba(52,211,153,.14); color: #6ee7b7; }
.lb-warn { background: rgba(245,158,11,.14); color: #fcd34d; }
.lb-bad  { background: rgba(248,113,113,.14); color: #fca5a5; }
.lb-raw  { background: rgba(148,163,184,.14); color: var(--text-dim); }

.attitude-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; }
.att-box {
  background: rgba(0,0,0,.18); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: 8px 10px 6px;
}
.att-head { font-size: 9.5px; color: var(--text-mute); text-transform: uppercase; letter-spacing: .55px; }
.att-head span { color: var(--text-dim); }
.att-svg { display: block; width: 100%; height: auto; margin: 2px 0 1px; }
.att-deg { font-size: 12.5px; font-weight: 640; text-align: center; }

.rv-body   { fill: #dfe7f2; }
.rv-dark   { fill: #2c3646; }
.rv-glass  { fill: #7fa8d8; opacity: .85; }
.rv-trim   { fill: #9fb0c6; }
.att-ground{ stroke: var(--green); stroke-width: 2; stroke-linecap: round; }
.att-level { stroke: var(--text-mute); stroke-width: 1; stroke-dasharray: 3 3; opacity: .7; }
.att-note  { font-size: 9px; color: var(--text-mute); text-align: center; margin-top: 2px; }

@media (max-width: 980px) { .tile-wide { grid-column: span 2; } }
@media (max-width: 620px) {
  .tile-wide { grid-column: span 2; }
  .level-body { flex-direction: column; align-items: stretch; }
  .level-dial { align-self: center; }
}
.att-sides {
  display: flex; justify-content: space-between;
  font-size: 9px; color: var(--text-mute);
  text-transform: uppercase; letter-spacing: .4px; padding: 0 4px;
}

/* Vertical form. .form-row is a horizontal flex whose fields grow to fill; reusing
   it in a column made each password field stretch to fill the panel height and left
   great gaps between them. */
.form-col {
  display: flex; flex-direction: column; align-items: stretch;
  gap: 2px; padding: 14px 16px 16px; max-width: 420px;
}
.form-col .field { flex: none; margin-bottom: 12px; }
.form-col .btn-primary { width: auto; align-self: flex-start; padding: 10px 20px; }
.form-col .form-note { margin-top: 10px; }

/* A 40-minute drive inside a week-wide track is under two pixels and vanishes. Give
   every band a floor, and let driving paint over the stopped bands around it. */
.track-seg { min-width: 2px; }
.seg-driving { z-index: 2; box-shadow: 0 0 0 .5px var(--blue); }

/* ---------------------------------------------------------------- narrow widths
   Grid and flex items default to min-width:auto, which means a wide child (the
   chart canvas, a table, a long unbroken value) refuses to let its track shrink.
   Below 720px that pushed the whole page 50-400px wider than the viewport and gave
   every panel a horizontal scrollbar. min-width:0 lets them actually collapse. */
.stage > *, .lowers > *, .tiles > *, .attitude-row > *,
.level-body > *, .moment-panel > *, .scrub > * { min-width: 0; }

.chart-box { min-width: 0; }
.chart-box canvas { max-width: 100% !important; }

/* Long values should wrap or ellipsis rather than widen their container. */
.kv-value, .tile-value, .lr-value, .stat-value { overflow-wrap: anywhere; }
.admin-table td, .admin-table th { word-break: normal; }

@media (max-width: 720px) {
  main { padding: 10px; }
  .panel-head { flex-wrap: wrap; }
  .chart-box { height: 230px; padding: 10px 10px 14px; }
  .chart-legend { padding: 8px 10px 0; gap: 9px; font-size: 11px; }
  .kv-list, .tiles, .media-strip { padding-left: 10px; padding-right: 10px; }
  .scrub { padding: 10px; }
  /* The transport row and the speed picker each need a full line at this width. */
  .scrub-top { flex-wrap: wrap; row-gap: 10px; }
  .speeds { width: 100%; justify-content: space-between; }
  .speed { flex: 1; text-align: center; }
  .statusbar { flex-wrap: wrap; row-gap: 6px; }
  .status-right { margin-left: 0; width: 100%; }
}

@media (max-width: 520px) {
  .tiles { grid-template-columns: 1fr; }
  .tile-wide { grid-column: 1 / -1; }
  .attitude-row { grid-template-columns: 1fr; }
  .topbar { padding: 10px 12px; row-gap: 8px; }
  .range-select { order: 5; width: 100%; }
  .moment-head { padding-left: 10px; padding-right: 10px; }
}

/* ---------------------------------------------------------------- power panel */
.pw-state { margin-left: auto; font-size: 11px; font-weight: 640; text-transform: uppercase; letter-spacing: .5px; }
.pw-soc { margin: 2px 0 10px; }
.pw-soc-top { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.pw-soc-val { font-size: 27px; font-weight: 660; letter-spacing: -.7px; line-height: 1.05; }
.pw-soc-sub { font-size: 11.5px; color: var(--text-dim); }
.pw-bar { height: 6px; border-radius: 3px; background: var(--panel-3); margin-top: 7px; overflow: hidden; }
.pw-bar span { display: block; height: 100%; border-radius: 3px; transition: width .3s ease; }

.pw-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 16px; }
.pw-col-head { font-size: 9.5px; color: var(--text-mute); text-transform: uppercase;
               letter-spacing: .6px; margin-bottom: 4px; }
.pw-row { display: flex; justify-content: space-between; gap: 8px; padding: 3px 0;
          border-bottom: 1px solid var(--border); font-size: 12px; }
.pw-row:last-child { border-bottom: 0; }
.pw-label { color: var(--text-mute); }
.pw-value { font-weight: 600; text-align: right; }
.pw-value em { display: block; font-style: normal; font-weight: 400;
               font-size: 10px; color: var(--text-mute); }

.pw-load {
  margin-top: 10px; padding: 8px 10px; border-radius: var(--r-sm);
  background: rgba(0,0,0,.18); border: 1px solid var(--border);
  font-size: 11.5px; color: var(--text-dim);
}
.pw-load strong { color: var(--text); font-weight: 640; }
.pw-load em { display: block; font-style: normal; font-size: 10.5px; color: var(--text-mute); margin-top: 2px; }

@media (max-width: 520px) { .pw-cols { grid-template-columns: 1fr; } }
