@font-face {
  font-family: "Objectivity";
  src: url("/static/fonts/Objectivity-Light.woff2") format("woff2");
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Objectivity";
  src: url("/static/fonts/Objectivity-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Objectivity";
  src: url("/static/fonts/Objectivity-Medium.woff2") format("woff2");
  font-weight: 500 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Objectivity";
  src: url("/static/fonts/Objectivity-Bold.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

:root {
  --bg: #ffffff;
  --surface: #f4f5f7;
  --text: #1c2240;
  --text-dim: #6f78a6;
  --separator: #e8e9eb;
  --separator-strong: #d1d5db;
  --accent: #ee8425;
  --accent-hover: #d36a14;
  --on-accent: #ffffff;
  --status-healthy: #2ea366;
  --status-offline: #c0392b;
  --font: "Objectivity", "Avenir Next", "Avenir", "Futura", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #29357e;
    --surface: rgba(255, 255, 255, 0.06);
    --text: #ffffff;
    --text-dim: rgba(255, 255, 255, 0.72);
    --separator: rgba(255, 255, 255, 0.18);
    --separator-strong: rgba(255, 255, 255, 0.28);
    color-scheme: dark;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}

.shell {
  min-height: 100dvh;
  max-width: 80rem;
  margin: 0 auto;
  padding: clamp(1rem, 4vw, 2.5rem);
  display: flex;
  flex-direction: column;
}
/* The map page is the one page that locks to the viewport so the map stays
   pinned under the header and only the sidebar scrolls. Every other page just
   flows and scrolls at the viewport. */
.shell-locked {
  height: 100dvh;
  overflow: hidden;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
}
.topbar form { margin: 0; }

.map-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(18rem, 1fr);
  gap: 1.5rem;
  flex: 1;
  min-height: 0;
}
.map {
  width: 100%;
  height: 100%;
  border-radius: 6px;
  overflow: hidden;
  background: var(--surface);
}
.sidebar {
  overflow: auto;
  min-height: 0;
}

/* Stack only in portrait. Landscape phones get the side-by-side layout
   because vertical space is the scarce one there. */
@media (max-width: 50rem) and (orientation: portrait) {
  .map-layout {
    grid-template-columns: 1fr;
    grid-template-rows: 50dvh minmax(0, 1fr);
    gap: 1rem;
  }
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  text-decoration: none;
  color: inherit;
}
.brand img {
  display: block;
  height: 40px;
  width: auto;
}
.brand .mark { display: block; transform: translateY(-2px); }
.brand .name { display: inline-block; line-height: 1; }
.brand .name b {
  display: block;
  font-weight: 500;
  letter-spacing: 0.16em;
  font-size: 19px;
}
.brand .name .sys {
  display: flex;
  justify-content: space-between;
  width: 100%;
  margin-top: 5px;
  font-weight: 400;
  font-size: 11px;
}
.brand .name .sys i { font-style: normal; }

h1 {
  font-weight: 600;
  font-size: 1.25rem;
  margin: 0 0 1rem;
}

a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--separator);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.25em;
  transition: text-decoration-color 120ms;
}
a:hover { text-decoration-color: var(--accent); }
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

.device-list {
  border-bottom: 1px solid var(--separator);
  font-size: 0.9375rem;
}
.device-row {
  display: grid;
  /* minmax(0, ...) so a long device name can't force the row wider than its container. */
  grid-template-columns: minmax(0, 1fr) 6em 5em;
  align-items: center;
  gap: 0.75rem;
  padding: 0.875rem 0.75rem;
  border-top: 1px solid var(--separator);
}
.device-row > :first-child { overflow-wrap: anywhere; }
.device-row.group-row {
  display: flex;
  justify-content: space-between;
  background: var(--surface);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  padding-block: 0.5rem;
}
.device-row.group-row::-webkit-details-marker { display: none; }
.group-label {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
}
.group-label::before {
  content: "";
  width: 0.4375rem;
  height: 0.4375rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 150ms;
}
.device-group[open] > .group-row .group-label::before { transform: rotate(45deg); }
/* Selected map marker → accent stripe on the matching sidebar header. */
.device-group.selected > .device-row.group-row {
  box-shadow: inset 3px 0 0 var(--accent);
}
.device-row.group-row + .device-row { border-top-color: var(--separator-strong); }

.device-manage {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.8125rem;
  color: var(--text-dim);
  text-decoration: none;
}
.device-manage:hover { color: var(--accent); }
.manage-icon { flex-shrink: 0; }

.dot {
  flex-shrink: 0;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--text-dim);
}

.device-status {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8125rem;
  text-transform: capitalize;
}
.device-status.healthy .dot { background: var(--status-healthy); }
.device-status.offline .dot { background: var(--status-offline); }

.count {
  /* Fixed width so dot X stays put as the ratio digits change. */
  width: 7em;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}
.count.offline .dot { background: var(--status-offline); }

.muted { color: var(--text-dim); }

/* Secondary tab nav within a device. Sits under the device heading. A single
   non-wrapping row that scrolls horizontally within itself when the tabs
   outgrow the width — the page never scrolls sideways, and adding tabs later
   just makes the strip scroll sooner. Console rides along, right-aligned. */
.tabs {
  display: flex;
  flex-wrap: nowrap;
  gap: 1rem;
  border-bottom: 1px solid var(--separator);
  margin-bottom: 1.5rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none; /* the tabs themselves signal scrollability */
  font-size: 0.9375rem;
  font-weight: 600;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  flex: none; /* keep natural width; the strip scrolls rather than squishing */
  padding-bottom: 0.75rem;
  white-space: nowrap;
  color: var(--text-dim);
  text-decoration: none;
}
/* Active indicator as an inset shadow, not a border + negative margin, so the
   horizontal-scroll container can't turn it into a stray vertical scrollbar. */
.tab.active {
  color: var(--accent);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.tab.disabled {
  color: var(--separator-strong);
  cursor: not-allowed;
}
.tab-external {
  flex: none;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  text-decoration: none;
}
.tab-external:hover { color: var(--accent); }

/* Heading: breadcrumb trail, then the device title (the page's subject) with
   its state pill and last-seen recency as one inline status cluster. */
.detail-heading {
  padding: 0.25rem 0 1.25rem;
}
.breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
  font-size: 0.8125rem;
  color: var(--text-dim);
}
.breadcrumb a { color: inherit; }
.breadcrumb .sep { color: var(--separator-strong); }
.title-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
}
/* Pill sits at the right edge so it doesn't crowd the title. */
.title-row .state-pill { margin-left: auto; }
.device-title {
  margin: 0;
  min-width: 0; /* let a long unbroken name shrink so the pill keeps its right edge */
  font-size: 1.375rem;
  font-weight: 600;
  overflow-wrap: anywhere;
}
.status-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.45rem 0 0;
  font-size: 0.8125rem;
  color: var(--text-dim);
}
.status-line .sep { color: var(--separator-strong); }
.state-pill {
  flex: none;
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: capitalize;
  border: 1px solid transparent;
}
.state-pill.healthy {
  color: var(--status-healthy);
  background: color-mix(in srgb, var(--status-healthy) 10%, transparent);
  border-color: color-mix(in srgb, var(--status-healthy) 32%, transparent);
}
.state-pill.offline {
  color: var(--status-offline);
  background: color-mix(in srgb, var(--status-offline) 10%, transparent);
  border-color: color-mix(in srgb, var(--status-offline) 32%, transparent);
}

/* Metrics container: a stack of titled sections, each its own stats grid. */
.metrics {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.metrics-section {
  margin: 0 0 0.6rem;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* Stats grid. Hairline dividers come from a 1px gap over a separator-colored
   backing. Fixed column counts (4 → 2 → 1) rather than auto-fit so it never
   lands on an awkward 3-up row that orphans the 4th card. */
.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--separator);
  border: 1px solid var(--separator);
  border-radius: 6px;
  overflow: hidden;
}
/* Tablet: drop straight to 2×2, skipping 3-up. */
@media (max-width: 56rem) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Phone: single column. */
@media (max-width: 30rem) {
  .stats { grid-template-columns: minmax(0, 1fr); }
}
.stat {
  background: var(--bg);
  padding: 1.25rem;
}
.stat-label {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-dim);
}
.stat-value {
  margin: 0.4rem 0 0;
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}
/* No reading (none yet, or a faulted point): a muted "—". */
.stat-value.empty { color: var(--text-dim); }
.stat-unit {
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--text-dim);
}
/* Connecting / offline placeholder shown before any section is laid out. */
.metrics-note {
  margin: 0;
  padding: 1.25rem;
  background: var(--bg);
  border: 1px solid var(--separator);
  border-radius: 6px;
  color: var(--text-dim);
}

label {
  display: block;
  font-weight: 500;
  font-size: 0.9375rem;
}

input {
  display: block;
  width: 100%;
  margin-top: 0.25rem;
  padding: 0.5rem 0.75rem;
  font: inherit;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--separator);
  border-radius: 4px;
}
input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 0;
  border-color: var(--accent);
}

button {
  font: inherit;
  font-weight: 500;
  padding: 0.5rem 1.125rem;
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background 120ms;
}
button:hover { background: var(--accent-hover); }
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

button.logout {
  background: transparent;
  color: inherit;
  padding: 0;
  font-weight: 400;
  border-radius: 0;
  text-decoration: underline;
  text-decoration-color: var(--separator);
  text-underline-offset: 0.25em;
  transition: text-decoration-color 120ms;
}
button.logout:hover {
  background: transparent;
  text-decoration-color: var(--accent);
}

form > * + * { margin-top: 0.75rem; }

.auth {
  width: min(22rem, 100%);
  margin-inline: auto;
  padding: clamp(3rem, 10vh, 6rem) 1rem 2rem;
  text-align: center;
}
.auth .brand {
  margin: 0 auto 1.25rem;
}
.auth .brand img {
  height: 3rem;
}
.auth h1 {
  font-size: 1.5rem;
  font-weight: 500;
  margin: 0 0 1.5rem;
}
.auth .error {
  margin: 0 0 1rem;
  text-align: left;
}
.auth form { text-align: left; }
.auth form button {
  display: block;
  width: 100%;
  margin-top: 1.5rem;
}

.error { color: var(--accent); font-weight: 500; }

.empty-state {
  margin: 2rem auto;
  text-align: center;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.site-tooltip-popup .maplibregl-popup-content {
  background: var(--text);
  color: var(--bg);
  font-family: var(--font);
  font-weight: 500;
  font-size: 0.8125rem;
  padding: 0.3rem 0.55rem;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.site-tooltip-popup .maplibregl-popup-tip { display: none; }

