/* Beekon console — shell + component vocabulary.
 *
 * Rules that carry the brand and must not drift:
 *   - Elevation is surface tone + 1px hairlines. There is no drop shadow in the
 *     brand except one amber-tinted glow; overlays are the only exception here.
 *   - Tables/panels use the 1px-gap grid motif: gap:1px over a --line
 *     background with --bg-elev cells, so borders never double up.
 *   - Mono is a semantic layer (ids, keys, coordinates, micro-labels), not
 *     decoration.
 *   - Empty and error states are VISUALLY DISTINCT. Conflating them was the
 *     worst information-design fault of the console this replaces.
 */

/* ---------- base ---------- */

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; height: 100%; }

body {
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.5;
  letter-spacing: var(--tr-body);
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-family: var(--f-display); font-weight: 500; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }

:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--accent-text);
  outline-offset: 1px;
  border-radius: var(--r-sm);
}

/* The router moves focus to each view's heading so keyboard and screen-reader
   users land in the new page. That is a programmatic focus on a non-interactive
   element — it must not paint a focus ring, which would read as a selected
   control. Interactive elements keep theirs. */
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible { outline: none; }

/* Screen-reader-only, but focusable (skip link). */
.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;
}
.skip:focus-visible {
  position: fixed; top: var(--s-5); left: var(--s-5); z-index: 100;
  width: auto; height: auto; margin: 0; clip: auto;
  padding: var(--s-3) var(--s-6); background: var(--bg-elev);
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
}

/* ---------- typography helpers ---------- */

.eyebrow {
  font-family: var(--f-mono);
  font-size: var(--t-eyebrow);
  font-weight: 500;
  letter-spacing: var(--tr-eyebrow);
  text-transform: uppercase;
  color: var(--accent-text);
}
.eyebrow-muted { color: var(--ink-3); }

.page-title {
  font-size: var(--t-display);
  letter-spacing: var(--tr-display);
  line-height: 1.15;
}
.h2 { font-size: var(--t-h2); letter-spacing: var(--tr-h2); }
.h3 { font-size: var(--t-h3); letter-spacing: var(--tr-h3); }

.muted { color: var(--ink-3); }
.faint { color: var(--ink-4); }
.small { font-size: var(--t-sm); }
.micro { font-size: var(--t-micro); }
.mono { font-family: var(--f-mono); }
.num { font-variant-numeric: tabular-nums; }

.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* An id/ULID rendered inline: mono, dimmed, never wrapping mid-token. */
.id {
  font-family: var(--f-mono);
  font-size: var(--t-micro);
  color: var(--ink-3);
  letter-spacing: 0;
}

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

.shell { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); min-height: 100vh; }

.sidebar {
  background: var(--bg-sunk);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh;
  /* Console v3's grouped nav (M4-0377) can be taller than a short window. */
  overflow-y: auto; overscroll-behavior: contain;
}

.brand {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-6) var(--s-6) var(--s-7);
}
.brand svg { width: 26px; height: 26px; flex: none; }
.brand-name {
  font-family: var(--f-display); font-size: 17px; font-weight: 600;
  letter-spacing: -0.022em; line-height: 1;
}
.brand-sub {
  font-family: var(--f-mono); font-size: 9.5px; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--accent-text); margin-top: 3px;
}

.nav { display: flex; flex-direction: column; gap: var(--s-6); padding: 0 var(--s-4) var(--s-5); flex: 1; }
/* Console v3's groups (Sidebar.dc.html, M4-0377): a mono eyebrow over each. */
.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-group-label {
  display: block; padding: 0 var(--s-4) var(--s-2);
  font-family: var(--f-mono); font-size: 10px; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.nav-item {
  display: flex; align-items: center; gap: var(--s-4);
  min-height: 36px;
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-md);
  color: var(--ink-2);
  font-size: var(--t-sm);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.nav-item:hover { background: color-mix(in oklch, var(--ink) 5%, transparent); text-decoration: none; color: var(--ink); }
.nav-item[aria-current="page"] {
  background: color-mix(in oklch, var(--honey) 14%, transparent);
  color: var(--accent-text);
  font-weight: 500;
}
.nav-item svg { width: 15px; height: 15px; flex: none; opacity: 0.85; }

.sidebar-foot { padding: var(--s-5) var(--s-6); border-top: 1px solid var(--line); }
.sidebar-docs {
  display: flex; align-items: center; gap: var(--s-3);
  margin-top: var(--s-4); font-size: var(--t-sm); color: var(--ink-2);
}
.sidebar-docs svg { width: 15px; height: 15px; flex: none; }

.topbar {
  height: var(--topbar-h);
  border-bottom: 1px solid var(--line);
  background: var(--bg-elev);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5);
  padding: 0 var(--s-8);
  position: sticky; top: 0; z-index: 20;
}
.topbar-right { display: flex; align-items: center; gap: var(--s-5); }

/* The top bar's breadcrumb (Topbar.dc.html, M4-0377): scope / page. It
   shrinks before anything else in the bar. */
.crumbs { display: flex; align-items: center; gap: var(--s-3); min-width: 0; flex: 1 1 200px; font-size: var(--t-sm); }
.crumb-scope { color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 0 1 auto; }
.crumb-sep { color: var(--ink-4, var(--ink-3)); }
.crumb-page { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.crumbs [hidden] { display: none; }

/* The account menu (Topbar.dc.html): initials, then a menu under them. */
.account { position: relative; }
.account-btn {
  display: inline-flex; align-items: center; gap: var(--s-3);
  height: 38px; padding: 0 10px 0 4px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg-elev); color: var(--ink);
  font: inherit; cursor: pointer;
}
.account-avatar {
  width: 30px; height: 30px; border-radius: 999px;
  background: color-mix(in oklch, var(--honey) 22%, transparent); color: var(--accent-text);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 12px;
}
.account-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 30;
  width: 280px; max-width: calc(100vw - 32px); box-sizing: border-box; padding: var(--s-3);
  border-radius: var(--r-lg, 14px); border: 1px solid var(--line); background: var(--bg-elev);
  box-shadow: 0 12px 32px color-mix(in oklch, oklch(20% 0.03 60) 16%, transparent);
  display: flex; flex-direction: column; gap: 2px;
}
.account-menu[hidden] { display: none; }
.account-menu-head { padding: var(--s-3) var(--s-4) var(--s-4); border-bottom: 1px solid var(--line); margin-bottom: var(--s-2); }
.account-menu-email { font-weight: 600; }
.account-menu-item, .account-menu-foot .btn {
  display: flex; align-items: center; width: 100%; min-height: 38px; box-sizing: border-box;
  padding: 0 var(--s-4); border-radius: var(--r-md); border: 0; background: transparent;
  color: var(--ink); font: inherit; font-size: var(--t-sm); text-align: left; justify-content: flex-start; cursor: pointer;
}
.account-menu-item:hover, .account-menu-item:focus-visible,
.account-menu-foot .btn:hover, .account-menu-foot .btn:focus-visible {
  background: color-mix(in oklch, var(--ink) 5%, transparent); text-decoration: none;
}
.account-menu-foot { border-top: 1px solid var(--line); margin-top: var(--s-2); padding-top: var(--s-2); }

/* The project switcher (M4-0180), in the sidebar since Console v3 (M4-0377):
   a "Project" eyebrow over a full-width select, above the project groups. */
.switcher { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; }
.switcher .select {
  width: 100%; min-width: 0; max-width: none;
  padding-top: 8px; padding-bottom: 8px;
  font-size: var(--t-sm); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The Organisation page's tabs (Organisation.dc.html, M4-0377): links. */
.org-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin-bottom: var(--s-7); overflow-x: auto; }
.org-tab {
  padding: 10px 14px; color: var(--ink-3); font-weight: 500; white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.org-tab:hover { color: var(--ink); text-decoration: none; }
.org-tab[aria-current="page"] { color: var(--ink); border-bottom-color: var(--honey); }

/* Every page fills the main column; long prose keeps its own ch-based measure. */
.content { padding: var(--s-9) var(--s-8) var(--s-10); }
.content-wide { padding-left: var(--s-7); padding-right: var(--s-7); }
.page-head { margin-bottom: var(--s-8); }
.page-head .page-title { margin-top: var(--s-2); }
.page-head-row { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--s-6); flex-wrap: wrap; }
/* The view's one-sentence subtitle (Design v2's .v2-sub). */
.page-sub { color: var(--ink-3); font-size: var(--t-sm); margin-top: var(--s-2); max-width: 80ch; }
/* The project and its region, under the subtitle (M4-0281). */
.page-meta { display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap; margin-top: var(--s-3); font-size: var(--t-xs); color: var(--ink-3); }
/* A note under a table (Design v2's Devices footnote). */
.footnote { margin-top: var(--s-5); max-width: 80ch; }

section + section { margin-top: var(--s-9); }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-5); margin-bottom: var(--s-5); }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-3);
  font-family: var(--f-body); font-size: var(--t-sm); font-weight: 500;
  letter-spacing: var(--tr-body);
  padding: 8px 14px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: transparent; color: var(--ink);
  cursor: pointer; white-space: nowrap;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.btn:focus-visible { box-shadow: var(--focus-ring); outline-offset: 2px; }
.btn:disabled { opacity: 0.55; cursor: default; }
.btn:not(:disabled):active { transform: translateY(0.5px); }

.btn-primary { background: var(--accent-solid); color: var(--accent-solid-ink); }
.btn-primary:not(:disabled):hover { background: color-mix(in oklch, var(--accent-solid) 88%, var(--honey)); transform: translateY(-1px); }

.btn-ghost { border-color: var(--line-strong); color: var(--ink); }
.btn-ghost:not(:disabled):hover { background: var(--bg-elev); border-color: var(--ink-4); }

.btn-danger { border-color: var(--line-strong); color: var(--red); }
.btn-danger:not(:disabled):hover { background: color-mix(in oklch, var(--red) 10%, transparent); border-color: var(--red); }

.btn-sm { padding: 5px 10px; font-size: var(--t-xs); }
.btn-icon { padding: 6px; border-radius: var(--r-md); border-color: transparent; color: var(--ink-3); }
.btn-icon:hover { background: color-mix(in oklch, var(--ink) 6%, transparent); color: var(--ink); }
.btn-icon svg { width: 16px; height: 16px; display: block; }

.btn-row { display: flex; gap: var(--s-3); flex-wrap: wrap; }

/* ---------- fields ---------- */

.field { display: block; margin-bottom: var(--s-5); }
.field-label {
  display: block; font-size: var(--t-xs); font-weight: 500;
  color: var(--ink-2); margin-bottom: var(--s-2);
}
.field-req { color: var(--ink-4); font-weight: 400; }

.input, .select, textarea.input {
  width: 100%;
  font-family: var(--f-body); font-size: var(--t-body); color: var(--ink);
  background: var(--bg-elev);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  padding: 8px 11px;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.input::placeholder { color: var(--ink-4); }
.input:focus-visible, .select:focus-visible, textarea.input:focus-visible {
  outline: none; border-color: var(--accent-text); box-shadow: var(--focus-ring);
}
.input:disabled, .select:disabled { background: var(--bg-sunk); color: var(--ink-3); }
.input.mono { font-family: var(--f-mono); font-size: var(--t-sm); }

.select {
  appearance: none;
  padding-right: 30px;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 16px) 52%, calc(100% - 11px) 52%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.field-hint { font-size: var(--t-micro); color: var(--ink-3); margin-top: var(--s-2); }
.field-error { font-size: var(--t-micro); color: var(--red); margin-top: var(--s-2); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); }

/* ---------- region picker (M4-0173) ----------
   A permanent, unrepairable choice, so it reads as a decision rather than a
   form control: full-width rows, the human name leading, the cell id and its
   region as secondary metadata in mono because the id is what the operator
   will recognise inside their SDK key. */

/* The region picker is a fieldset (M4-0272): no browser frame around it. */
fieldset.region-field { border: 0; padding: 0; margin-inline: 0; min-width: 0; }
fieldset.region-field > legend { padding: 0; }
.region-options { display: grid; gap: var(--s-2); margin-top: var(--s-3); }
.region-option {
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--bg-elev);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.region-option:hover { border-color: var(--accent-text); }
.region-option:has(input:checked) { border-color: var(--accent-text); background: var(--bg-sunk); }
.region-option:has(input:focus-visible) { box-shadow: var(--focus-ring); }
.region-option input { margin-top: 3px; accent-color: var(--accent-text); flex: none; }
.region-text { display: grid; gap: 2px; }
.region-name { font-size: var(--t-body); color: var(--ink); }
.region-meta { font-size: var(--t-micro); color: var(--ink-3); }

/* ---------- cards + the 1px-gap grid motif ---------- */

.card {
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-7);
}
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-5); margin-bottom: var(--s-5); }
.card-foot {
  margin-top: var(--s-6); padding-top: var(--s-5);
  border-top: 1px dashed var(--line);
  display: flex; justify-content: space-between; gap: var(--s-5);
  font-family: var(--f-mono); font-size: var(--t-micro); color: var(--ink-3);
}

/* Seamless bordered grid: one hairline between cells, none doubled. */
.grid-panel {
  display: grid; gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.grid-panel > * { background: var(--bg-elev); padding: var(--s-6); }
.cols-2 { grid-template-columns: 1fr 1fr; }
.cols-3 { grid-template-columns: repeat(3, 1fr); }
.cols-4 { grid-template-columns: repeat(4, 1fr); }

/* ---------- table ---------- */

.table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.table th {
  text-align: left; font-weight: 500;
  font-family: var(--f-mono); font-size: var(--t-eyebrow);
  letter-spacing: var(--tr-eyebrow); text-transform: uppercase;
  color: var(--ink-3);
  padding: var(--s-4) var(--s-6);
  border-bottom: 1px solid var(--line);
  background: var(--bg-sunk);
  white-space: nowrap;
}
.table td { padding: var(--s-5) var(--s-6); border-bottom: 1px solid var(--line); vertical-align: middle; }
.table tr:last-child td { border-bottom: none; }
.table tbody tr { transition: background var(--dur-fast) var(--ease); }
.table tbody tr:hover { background: color-mix(in oklch, var(--ink) 3%, transparent); }
.table .cell-actions { text-align: right; white-space: nowrap; }
.table .cell-num { text-align: right; font-variant-numeric: tabular-nums; }

.table-wrap {
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg-elev);
}

/* The Activity table (M4-0181): fourteen columns, so it scrolls inside its own
   wrap rather than clipping (.table-wrap is overflow:hidden) or pushing the page. */
.table-scroll {
  overflow-x: auto;
  max-width: 100%;
  /* Its columns never size the page: on a phone the shell's single column is a
     plain 1fr, which a wide table's min-content would otherwise stretch. */
  contain: inline-size;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-elev);
}
/* v2's compact table (Activity.dc.html, M4-0275): 9px cells and xs text, so
   all fourteen columns fit a 1440 px screen without the wrap scrolling. v2 drew
   13 columns at 9px 14px; the Flags column (0216) leaves 8px a side. */
.table-scroll .table td, .table-scroll .table th { white-space: nowrap; padding: 9px 8px; }
.table-scroll .table td { font-size: var(--t-xs); line-height: 1.4; }
.table-scroll .table th { letter-spacing: 0.02em; }
.table-scroll .table .mono, .table-scroll .table .num, .table-scroll .table .id { font-size: var(--t-micro); }
.table-scroll .table .pos { font-size: 11px; }
/* Pills in the compact table read as words, not eyebrows: the same tones,
   without the uppercase and the tracking that cost a column its width. */
.table-scroll .table .pill { font-family: var(--f-body); font-size: var(--t-eyebrow); text-transform: none; letter-spacing: 0; padding: 1px 5px; }
.table-scroll .table .wrap-gap { gap: 4px; }
.table-foot { display: flex; justify-content: space-between; gap: var(--s-6); padding: var(--s-5) var(--s-2) 0; font-size: var(--t-xs); color: var(--ink-3); }
.table tr.gated td { background: color-mix(in oklch, var(--red) 4%, transparent); }
/* A session boundary (M4-0338): one cell across the table, not a point. */
.table tr.session-break td {
  padding: 5px 8px; white-space: normal;
  font-size: var(--t-xs); color: var(--ink-2);
  background: var(--bg-sunk);
  border-top: 1px dashed var(--line-strong); border-bottom: 1px dashed var(--line-strong);
}
.table tbody tr.session-break:hover { background: none; }
.table tr.session-break .mono { font-size: var(--t-micro); }

/* A segmented choice (0216's v2 kit, ported without the prefix): one pressed. */
.seg {
  display: inline-flex; gap: 2px;
  background: var(--bg-sunk);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 3px;
}
.seg-btn {
  font-family: var(--f-body); font-size: var(--t-xs);
  padding: 5px 10px; border-radius: var(--r-sm);
  border: 0; background: transparent; color: var(--ink-2); cursor: pointer;
  white-space: nowrap;
}
.seg-btn[aria-pressed="true"] { background: var(--accent-solid); color: var(--accent-solid-ink); }

.activity-controls {
  display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: var(--s-4) var(--s-5);
  margin-bottom: var(--s-6);
}
.activity-ctl { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; max-width: 100%; }
.activity-ctl .field-label { margin-bottom: 0; }
.activity-custom { display: flex; flex-wrap: wrap; gap: var(--s-4); min-width: 0; max-width: 100%; }
.activity-custom[hidden] { display: none; }
.activity-apply { flex-direction: row; gap: var(--s-3); }
.activity-controls[hidden], .page-head-row > .row[hidden], .page-sub[hidden] { display: none; }
/* The filter toolbar (v2's toolbar card) and its note. */
.activity-controls {
  padding: var(--s-5) var(--s-6);
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--bg-elev);
}
.activity-hint { flex-basis: 100%; margin: 0; font-size: var(--t-micro); color: var(--ink-3); }
.page-sub { color: var(--ink-3); font-size: var(--t-sm); margin: var(--s-2) 0 0; }
.activity-footnote { text-align: center; margin-top: var(--s-5); }
.activity-cap { margin-bottom: var(--s-5); }
.activity-cap[hidden] { display: none; }

/* ---------- status ---------- */

.pill {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-family: var(--f-mono); font-size: var(--t-eyebrow); font-weight: 500;
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 4px;
  background: color-mix(in oklch, var(--ink) 8%, transparent);
  color: var(--ink-2);
}
.pill-ok { background: color-mix(in oklch, var(--green) 14%, transparent); color: var(--green); }
.pill-warn { background: color-mix(in oklch, var(--amber) 18%, transparent); color: var(--honey-ink); }
.pill-bad { background: color-mix(in oklch, var(--red) 13%, transparent); color: var(--red); }
:root[data-theme="dark"] .pill-warn { color: var(--honey); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .pill-warn { color: var(--honey); } }

.dot { width: 6px; height: 6px; border-radius: 50%; background: var(--green); flex: none; }
.dot-live { animation: pulse 1.8s infinite; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--green) 55%, transparent); }
  70% { box-shadow: 0 0 0 6px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .dot-live { animation: none; } }

/* A status: a coloured dot and its words, never colour alone (Design v2's
   v2-status; M4-0277 ports the same piece for the Map's "Data as of"). */
.status { display: inline-flex; align-items: center; gap: 7px; font-size: var(--t-xs); color: var(--ink-2); white-space: nowrap; }
.status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--ink-4); flex: none; }
.status.ok::before { background: var(--green); }
.status.warn::before { background: var(--amber); }
.status.bad::before { background: var(--red); }
.status.quiet::before { background: transparent; border: 1.5px solid var(--ink-4); width: 6px; height: 6px; }

/* Health chips (Design v2's v2-chip): one fact each. */
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { font-family: var(--f-mono); font-size: 11px; padding: 2px 7px; border-radius: var(--r-sm); background: var(--bg-sunk); border: 1px solid var(--line); color: var(--ink-2); white-space: nowrap; }
.chip.bad { color: var(--red); border-color: color-mix(in oklch, var(--red) 35%, var(--line)); }

/* ---------- stat tile ---------- */

.stat-label {
  font-family: var(--f-mono); font-size: var(--t-eyebrow); font-weight: 500;
  letter-spacing: var(--tr-eyebrow); text-transform: uppercase; color: var(--ink-3);
}
.stat-value {
  font-family: var(--f-display); font-size: 28px; font-weight: 500;
  letter-spacing: -0.025em; line-height: 1.1; margin-top: var(--s-3);
  font-variant-numeric: tabular-nums;
}
.stat-note { font-size: var(--t-micro); color: var(--ink-3); margin-top: var(--s-2); }

/* ---------- empty vs error: deliberately different ---------- */

.empty {
  text-align: center;
  padding: var(--s-10) var(--s-7);
  color: var(--ink-3);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--bg-sunk);
}
.empty-title { font-family: var(--f-display); font-size: var(--t-h2); letter-spacing: var(--tr-h2); color: var(--ink); }
.empty-body { margin-top: var(--s-3); font-size: var(--t-sm); max-width: 46ch; margin-left: auto; margin-right: auto; }
.empty-action { margin-top: var(--s-6); }

.errorbox {
  display: flex; gap: var(--s-4); align-items: flex-start;
  padding: var(--s-5) var(--s-6);
  border: 1px solid color-mix(in oklch, var(--red) 40%, var(--line));
  border-left: 3px solid var(--red);
  border-radius: var(--r-md);
  background: color-mix(in oklch, var(--red) 7%, var(--bg-elev));
  color: var(--ink);
  font-size: var(--t-sm);
}
.errorbox-title { font-weight: 500; color: var(--red); }
.errorbox-body { color: var(--ink-2); margin-top: 2px; }
.errorbox-actions { margin-left: auto; display: flex; gap: var(--s-3); flex-wrap: wrap; }

/* The read-only banner (D129 States §5): one note at the top of a page a member
   may view but not change. A member's edit controls are hidden, so this is the
   single acknowledgement, not a row of disabled buttons. */
.readonly-banner { margin-bottom: var(--s-5); }

/* A shortened id with a Copy button (D129 States §8). */
.id-chip { display: inline-flex; align-items: center; gap: var(--s-3); min-width: 0; }
.id-chip .id { color: var(--ink-3); }

/* An "unavailable / not measured" state — neither empty nor error. This is the
   ingest-health honesty case: we could not ask, which is not the same as zero. */
.notice {
  padding: var(--s-5) var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-sunk);
  color: var(--ink-3);
  font-size: var(--t-sm);
}

/* ---------- skeleton ---------- */

.skel {
  background: linear-gradient(90deg,
    color-mix(in oklch, var(--ink) 6%, transparent) 25%,
    color-mix(in oklch, var(--ink) 11%, transparent) 37%,
    color-mix(in oklch, var(--ink) 6%, transparent) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s infinite linear;
  border-radius: var(--r-sm);
  height: 1em;
}
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }
.skel-row { height: 44px; border-radius: var(--r-md); margin-bottom: var(--s-3); }

/* ---------- modal ---------- */

.overlay {
  position: fixed; inset: 0; z-index: 60;
  background: color-mix(in oklch, oklch(15% 0.02 60) 55%, transparent);
  display: flex; align-items: center; justify-content: center;
  padding: var(--s-7);
  backdrop-filter: blur(3px);
}
.modal {
  background: var(--bg-elev);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  padding: var(--s-8);
  width: 100%; max-width: 460px;
  max-height: calc(100vh - 2 * var(--s-7));
  overflow-y: auto;
  box-shadow: 0 24px 60px -28px color-mix(in oklch, oklch(15% 0.02 60) 60%, transparent);
}
.modal-wide { max-width: 620px; }
.modal-title { font-size: var(--t-h2); letter-spacing: var(--tr-h2); }
.modal-body { margin-top: var(--s-4); color: var(--ink-2); font-size: var(--t-sm); }
.modal-actions { margin-top: var(--s-8); display: flex; justify-content: flex-end; gap: var(--s-3); }

/* ---------- secret reveal ---------- */

.secret {
  display: flex; align-items: center; gap: var(--s-4);
  font-family: var(--f-mono); font-size: var(--t-sm);
  background: var(--bg-sunk);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  padding: var(--s-4) var(--s-5);
  word-break: break-all;
}
.secret-value { flex: 1; min-width: 0; }
.secret-masked { letter-spacing: 0.08em; color: var(--ink-3); }
.warn-band {
  display: flex; gap: var(--s-4); align-items: flex-start;
  padding: var(--s-5) var(--s-6);
  border: 1px solid color-mix(in oklch, var(--amber) 45%, var(--line));
  border-left: 3px solid var(--amber);
  border-radius: var(--r-md);
  background: color-mix(in oklch, var(--amber) 10%, var(--bg-elev));
  font-size: var(--t-sm);
}

/* ---------- first-data onboarding + SDK setup code (M4-0183) ---------- */

.onboard {
  border: 1px solid var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--bg-elev);
  padding: var(--s-6) var(--s-7);
  margin-bottom: var(--s-7);
}
.onboard > * + * { margin-top: var(--s-4); }
.onboard-head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-4); }
.onboard-ok { border-color: color-mix(in oklch, var(--green) 40%, var(--line)); }
.onboard-link { margin-left: auto; }
/* Design v2's onboarding row (Keys.dc.html): a mark, the words, the actions. */
.onboard-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--s-6); align-items: center; }
.onboard-title { font-weight: 600; margin-top: 2px; }
.onboard-text { margin-top: 4px; max-width: 70ch; }
.onboard-pulse { width: 38px; height: 38px; border-radius: 50%; border: 2px solid var(--honey); display: grid; place-items: center; }
.onboard-pulse::after { content: ""; width: 12px; height: 12px; border-radius: 50%; background: var(--honey); }
.onboard-pulse-off { border-color: var(--ink-4); }
.onboard-pulse-off::after { background: var(--ink-4); }
.onboard-check { width: 38px; height: 38px; border-radius: 50%; border: 2px solid var(--green); position: relative; }
.onboard-check::after { content: ""; position: absolute; left: 13px; top: 8px; width: 8px; height: 14px; border: solid var(--green); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.onboard-setup[hidden] { display: none; }
@media (max-width: 640px) { .onboard-row { grid-template-columns: minmax(0, 1fr); } .onboard-pulse, .onboard-check { display: none; } }

/* Keys on the v3 board (M4-0383, D129): each list is a card with a one-sentence
   head, its table flush inside, and its revoked keys collapsed under it. */
.keys-top { display: flex; justify-content: flex-end; margin-bottom: var(--s-4); }
.keys-ref::after { content: "\2009\2197" / ""; }
.keys-card { padding: 0; overflow: hidden; }
.keys-card + .keys-card { margin-top: var(--s-7); }
.keys-card-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--s-5); padding: var(--s-6) var(--s-6) var(--s-5);
}
.keys-card-head p { margin-top: 2px; }
.keys-card-note { padding: 0 var(--s-6) var(--s-5); }
.keys-card .table-wrap { border: 0; border-top: 1px solid var(--line); border-radius: 0; }
.keys-card > div > .empty, .keys-card > div > .errorbox { margin: 0 var(--s-6) var(--s-6); }
.keys-card > div > .notice { margin: 0 var(--s-6) var(--s-5); }
.keys-card .footnote { margin: 0; padding: var(--s-4) var(--s-6) var(--s-5); border-top: 1px solid var(--line); max-width: none; }
.key-prefix { display: inline-flex; align-items: center; gap: var(--s-2); }
.key-prefix .key-copy-btn { padding: 4px; }
.key-prefix .key-copy-btn svg { width: 13px; height: 13px; }
.table tbody.keys-revoked[hidden] { display: none; }
.keys-revoked-foot { border-top: 1px solid var(--line); padding: var(--s-4) var(--s-6); }
.keys-revoked-toggle {
  display: inline-flex; align-items: center; gap: var(--s-3);
  border: 0; background: none; padding: 2px 0; cursor: pointer;
  font: inherit; font-size: var(--t-sm); color: var(--ink-3);
}
.keys-revoked-toggle:hover { color: var(--ink); }
.keys-revoked-chev { width: 0; height: 0; border-left: 5px solid currentColor; border-top: 4px solid transparent; border-bottom: 4px solid transparent; transition: transform var(--dur-fast) var(--ease); }
.keys-revoked-toggle[aria-expanded="true"] .keys-revoked-chev { transform: rotate(90deg); }
.keys-revoked tr td { color: var(--ink-3); }
/* v3 Keys (D133): a revoked key's mark in its Key cell, and the row ⋯ menu. */
.key-cell { display: inline-flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.key-revoked-tag { color: var(--red); white-space: nowrap; }
.row-menu { display: inline-flex; justify-content: flex-end; }
.row-menu-btn { font-size: 16px; line-height: 1; padding: 4px 8px; }
.row-menu-btn[aria-expanded="true"] { background: color-mix(in oklch, var(--ink) 8%, transparent); color: var(--ink); }
.row-menu-list {
  position: fixed; z-index: 40; min-width: 168px;
  display: flex; flex-direction: column; padding: var(--s-1);
  background: var(--bg-elev); border: 1px solid var(--line-strong); border-radius: var(--r-md);
  box-shadow: 0 8px 24px color-mix(in oklch, var(--ink) 14%, transparent);
}
.row-menu-list[hidden] { display: none; }
.row-menu-item {
  text-align: left; background: none; border: 0; border-radius: var(--r-sm);
  padding: var(--s-2) var(--s-3); font: inherit; font-size: var(--t-sm); color: var(--ink); cursor: pointer;
}
.row-menu-item:hover, .row-menu-item:focus-visible { background: color-mix(in oklch, var(--ink) 6%, transparent); outline: none; }
.row-menu-item:focus-visible { box-shadow: var(--focus-ring); }
.row-menu-item.danger { color: var(--red); }
/* M4-0256: the name beside Issue key. */
.keys-issue { display: flex; flex-direction: column; align-items: flex-end; }
.keys-name-input { width: 16rem; max-width: 100%; }
.key-name { overflow-wrap: anywhere; }
/* M4-0365: server keys with scopes; the picker is the region picker's pattern (M4-0272). */
fieldset.scope-field { border: 0; padding: 0; margin-inline: 0; min-width: 0; }
fieldset.scope-field > legend { padding: 0; }
.scope-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
.scope-option {
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--bg-elev);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.scope-option:hover { border-color: var(--accent-text); }
.scope-option:has(input:checked) { border-color: var(--accent-text); background: var(--bg-sunk); }
.scope-option:has(input:focus-visible) { box-shadow: var(--focus-ring); }
.scope-option input { margin-top: 3px; accent-color: var(--accent-text); flex: none; }
.scope-option > span { display: grid; gap: 2px; min-width: 0; }
.scope-name { font-size: var(--t-sm); color: var(--ink); }
@media (max-width: 640px) { .scope-grid { grid-template-columns: minmax(0, 1fr); } }
/* M4-0257: platform, model and SDK under a device's install id. */
.device-meta { margin-top: 2px; overflow-wrap: anywhere; }

.code-switch { min-width: 0; }
.code-switch > * + * { margin-top: var(--s-3); }
.code-switch-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--s-4); }
.lang-tabs {
  display: inline-flex; flex-wrap: wrap; gap: var(--s-2);
  padding: var(--s-2); border-radius: var(--r-md); background: var(--bg-sunk);
}
.lang-tab {
  font: inherit; font-size: var(--t-sm); color: var(--ink-3);
  background: transparent; border: 0; border-radius: var(--r-sm);
  padding: var(--s-2) var(--s-4); cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.lang-tab:hover { color: var(--ink); }
.lang-tab:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.lang-tab-on { background: var(--bg-elev); color: var(--ink); box-shadow: 0 0 0 1px var(--line); }
.code-block {
  display: block; margin: 0;
  white-space: pre; overflow-x: auto; line-height: 1.6;
  font-family: var(--f-mono); font-size: var(--t-sm);
  background: var(--bg-sunk);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  padding: var(--s-4) var(--s-5);
}

/* ---------- toast ---------- */

.toasts {
  position: fixed; bottom: var(--s-7); right: var(--s-7); z-index: 80;
  display: flex; flex-direction: column; gap: var(--s-3);
  max-width: min(380px, calc(100vw - 2 * var(--s-7)));
}
.toast {
  display: flex; gap: var(--s-4); align-items: flex-start;
  background: var(--bg-elev);
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--ink-3);
  border-radius: var(--r-md);
  padding: var(--s-5) var(--s-6);
  font-size: var(--t-sm);
  box-shadow: 0 12px 32px -18px color-mix(in oklch, oklch(15% 0.02 60) 70%, transparent);
}
.toast-ok { border-left-color: var(--green); }
.toast-bad { border-left-color: var(--red); }

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

.auth-wrap { min-height: 100vh; display: grid; place-items: center; padding: var(--s-7); }
.auth-card { width: 100%; max-width: 380px; }
.auth-brand { display: flex; align-items: center; gap: var(--s-4); margin-bottom: var(--s-8); }
.auth-brand svg { width: 30px; height: 30px; }
.auth-sep {
  display: flex; align-items: center; gap: var(--s-4);
  margin: var(--s-6) 0;
  color: var(--ink-4); font-size: var(--t-micro);
  font-family: var(--f-mono); letter-spacing: 0.08em; text-transform: uppercase;
}
.auth-sep::before, .auth-sep::after { content: ""; height: 1px; background: var(--line); flex: 1; }
/* Why Login is showing, when the console knows (views/login.js). */
.auth-message { margin-top: var(--s-6); }
/* Design v2's Login (M4-0272, Login.dc.html): the sign-in pane beside an
   illustrated one, which goes below 900 px. */
.auth-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); place-items: stretch; padding: 0; }
.auth-pane { display: flex; align-items: center; justify-content: center; padding: var(--s-8) var(--s-7); min-width: 0; }
.auth-body { margin-top: var(--s-8); }
.auth-google { justify-content: center; gap: 10px; }
.auth-google svg { flex: none; }
.auth-google-block .auth-sep { margin: var(--s-6) 0; text-transform: none; letter-spacing: 0; font-family: var(--f-body); }
.auth-art { position: relative; overflow: hidden; background: var(--bg-sunk); border-left: 1px solid var(--line); min-height: 100vh; }
.auth-art-map { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.auth-art-roads path { stroke: var(--bg-elev); stroke-width: 10; fill: none; }
.auth-art-water { fill: color-mix(in oklch, var(--map-track) 14%, var(--bg-sunk)); }
.auth-art-track { stroke: var(--map-fence); stroke-width: 4; fill: none; stroke-linecap: round; }
.auth-art-halo { fill: var(--map-fence); fill-opacity: 0.16; }
.auth-art-pin { fill: var(--map-fence); stroke: var(--bg-elev); stroke-width: 3; }
.auth-art-fence { fill: var(--map-track); fill-opacity: 0.08; stroke: var(--map-track); stroke-width: 2; stroke-dasharray: 6 5; }
.auth-art-copy { position: absolute; left: 40px; right: 40px; bottom: 40px; max-width: 420px; }
.auth-art-title { font-family: var(--f-display); font-size: 22px; letter-spacing: -0.02em; font-weight: 600; color: var(--ink); }
.auth-art-sub { color: var(--ink-2); margin-top: 6px; }
@media (max-width: 900px) {
  .auth-split { grid-template-columns: minmax(0, 1fr); }
  .auth-art { display: none; }
  .auth-pane { padding: var(--s-7) var(--s-5); }
}
.btn-block { width: 100%; }

/* ---------- map surface ---------- */

.map-wrap {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--bg-sunk);
  min-height: 420px;
}
/* The fence overlay only: an icon placed in the map keeps its own size (0208). */
.map-wrap svg.fence-canvas { display: block; width: 100%; height: 100%; position: absolute; inset: 0; }
.map-note {
  position: absolute; left: var(--s-4); bottom: var(--s-4);
  font-family: var(--f-mono); font-size: var(--t-eyebrow);
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-3);
  background: color-mix(in oklch, var(--bg-elev) 85%, transparent);
  padding: 3px 8px; border-radius: 4px;
}
.map-attr {
  position: absolute; right: var(--s-4); bottom: var(--s-4);
  font-size: 10.5px; color: var(--ink-3);
  background: color-mix(in oklch, var(--bg-elev) 85%, transparent);
  padding: 2px 7px; border-radius: 4px;
}
.map-toolbar {
  position: absolute; left: var(--s-4); top: var(--s-4);
  display: flex; gap: var(--s-2);
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 3px;
}
.map-tool {
  font-family: var(--f-body); font-size: var(--t-xs);
  padding: 5px 10px; border-radius: var(--r-sm);
  border: 0; background: transparent; color: var(--ink-2); cursor: pointer;
}
.map-tool[aria-pressed="true"] { background: var(--accent-solid); color: var(--accent-solid-ink); }
.editor-grid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--s-6); align-items: start; }
/* A fence list entry is a button styled as its card, so the keyboard reaches it. */
.fence-entry { display: block; width: 100%; padding: 12px 14px; font: inherit; color: inherit; text-align: left; cursor: pointer; }
.fence-entry[aria-current="true"] { border-color: var(--honey); }
/* Brought into view when a draft appears or a fence opens (0205): clear of the
   sticky topbar above and the viewport's edge below. */
.fence-form { scroll-margin-top: calc(var(--topbar-h) + var(--s-5)); scroll-margin-bottom: var(--s-5); }

/* The Geofences screen as Design v2 draws it (M4-0269): the list with its search
   on the left, the map beside it, and the tools, zoom, hint and edit card
   floating on the map. The map is sized to the screen, so nothing scrolls. */
.fence-editor {
  --fence-map-h: clamp(480px, calc(100dvh - 275px), 1100px);
  grid-template-columns: 340px minmax(0, 1fr); align-items: start;
}
.fence-top { display: grid; grid-template-columns: 340px minmax(0, 1fr); gap: var(--s-6); align-items: center; margin-bottom: var(--s-4); }
.fence-about { margin: 0; }
.fence-side { display: flex; flex-direction: column; gap: var(--s-4); min-width: 0; max-height: var(--fence-map-h); }
.fence-side .section-head { margin: 0; }
.fence-search {
  display: flex; align-items: center; gap: var(--s-3);
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg-elev);
  padding: 0 var(--s-4); color: var(--ink-3);
}
.fence-search:focus-within { border-color: var(--honey); }
.fence-search .input { border: 0; background: transparent; padding-left: 0; box-shadow: none; outline: none; min-width: 0; flex: 1; }
.fence-search:has(.input[hidden]) { visibility: hidden; }
.fence-list { overflow: auto; min-height: 0; flex: 1; }
.fence-entries { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-3); }
.fence-entry {
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg-elev);
}
.fence-entry:hover { border-color: color-mix(in oklch, var(--honey) 50%, var(--line)); }
.fence-stage { position: relative; min-width: 0; }
.fence-stage .map-wrap { height: var(--fence-map-h); min-height: 0; }
.fence-stage .map-note { bottom: calc(var(--s-4) + 30px); }
.fence-card-host[hidden] { display: none; }
/* D133: the edit card takes the list's place in the side panel, under a link
   back to the list; it scrolls inside the panel, its footer sticky. */
.fence-card-host { min-height: 0; display: flex; flex-direction: column; }
.fence-side .fence-form { margin: 0; overflow: auto; min-height: 0; max-height: calc(var(--fence-map-h) - 40px); }
.fence-back {
  align-self: flex-start; background: none; border: 0; padding: 2px 0; cursor: pointer;
  font: inherit; font-size: var(--t-sm); color: var(--ink-2);
}
.fence-back:hover { color: var(--ink); text-decoration: underline; }
.fence-back:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--r-sm); }
/* M4-0383 (the v3 board): the card's actions in a sticky footer, full bleed,
   so Create / Save and Cancel stay in view while the card scrolls; Delete
   sits on the left. A new fence's Circle / Polygon switch above its fields. */
.fence-form-foot {
  position: sticky; bottom: 0; z-index: 1;
  display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s-3);
  margin: var(--s-6) calc(-1 * var(--s-7)) calc(-1 * var(--s-7));
  padding: var(--s-5) var(--s-7);
  border-top: 1px solid var(--line); background: var(--bg-elev);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
.fence-form-foot .btn-danger { margin-right: auto; }
.fence-shape { align-self: flex-start; }
.map-wrap .fence-zoom { top: auto; transform: none; bottom: 60px; }
.fence-hint {
  position: absolute; z-index: 2; left: var(--s-4); bottom: var(--s-4); max-width: calc(100% - 200px);
  font-size: var(--t-xs); color: var(--ink-2);
  background: color-mix(in oklch, var(--bg-elev) 90%, transparent);
  border: 1px solid var(--line); border-radius: var(--r-md); padding: 5px 10px;
}
.fence-measure {
  position: absolute; z-index: 2; pointer-events: none;
  font-family: var(--f-mono); font-size: var(--t-xs); color: var(--ink);
  background: var(--bg-elev); border: 1px solid var(--honey-3); border-radius: var(--r-sm);
  padding: 2px 7px; white-space: nowrap;
}
.fence-measure[hidden] { display: none; }
.map-tool { display: inline-flex; align-items: center; gap: 6px; }
.map-wrap svg.fence-canvas[data-tool="circle"], .map-wrap svg.fence-canvas[data-tool="polygon"] { cursor: crosshair; }
.map-wrap svg.fence-canvas[data-tool="select"] { cursor: grab; }
.map-wrap svg.fence-canvas.panning { cursor: grabbing; }
/* On a basemap with Select armed, the empty map is Mapbox's; shapes stay live. */
.map-wrap svg.fence-canvas.passthrough { pointer-events: none; }
.map-wrap svg.fence-canvas.passthrough [data-fence], .map-wrap svg.fence-canvas.passthrough [data-handle] { pointer-events: auto; }

/* ---------- charts ---------- */

.chart { width: 100%; display: block; overflow: visible; }
.chart-baseline { stroke: var(--line-strong, var(--line)); stroke-width: 1; }
.chart-grid { stroke: var(--line); stroke-width: 1; stroke-dasharray: 2 3; }
.chart-label { font-family: var(--f-mono); font-size: 9px; fill: var(--ink-4); letter-spacing: 0.04em; }
/* 0373: Usage charts stretch a fixed viewBox, so their labels are counter-scaled to the micro size (views/tab-usage.js fitLabels). */
.usage .chart-label { font-size: calc(var(--t-micro) * var(--chart-k, 1)); }
.spark { width: 72px; height: 20px; display: block; }
.spark path { fill: none; stroke: var(--honey); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }

/* The Usage dashboard (M4-0294). Chart series slots are the design pass's
   validated pair (the v3 Usage board, D129/D133: #c27a1a/#2f62a8 light,
   #bf8024/#5b8fd6 dark, CVD-checked; was 0293-0295's);
   the raw --honey fails contrast on the light surface, so it is not slot 1.
   sRGB on purpose, like the map's paint colours. Failures use the reserved
   --red, always with a word beside it. */
:root { --series-1: #c27a1a; --series-2: #2f62a8; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --series-1: #bf8024; --series-2: #5b8fd6; }
}
:root[data-theme="dark"] { --series-1: #bf8024; --series-2: #5b8fd6; }

.usage { display: grid; gap: var(--s-6); }
.usage-filters { display: flex; flex-wrap: wrap; gap: var(--s-4); align-items: center; }
.usage-grid { display: grid; gap: var(--s-6); }
.usage-card-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s-5); margin-bottom: var(--s-4); }
.usage-card-summary { color: var(--ink-2); margin-bottom: var(--s-3); }
.usage-card-summary:empty { display: none; }
.usage-cap-row { display: flex; align-items: baseline; gap: var(--s-3); margin: var(--s-4) 0 var(--s-3); }
.usage-cap-note { margin-top: var(--s-3); color: var(--ink-2); }
.usage-cap-drops { margin-top: var(--s-2); color: var(--ink-2); }
.usage-foot { margin: 0; }
.usage-table { margin-top: var(--s-2); }
/* M4-0383 (the v3 Usage board): why points were filtered, beside the key table. */
.usage-pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); gap: var(--s-6); align-items: start; }
.usage-why { display: flex; flex-direction: column; gap: var(--s-5); }
.why-list { display: flex; flex-direction: column; gap: var(--s-5); }
.why-row { display: flex; flex-direction: column; gap: 6px; }
.why-head { display: flex; justify-content: space-between; gap: var(--s-4); font-size: var(--t-sm); }
.why-value { color: var(--ink-2); }
.why-track { height: 10px; border-radius: 4px; background: var(--bg-sunk); overflow: hidden; }
.why-fill { height: 100%; background: var(--series-2); border-radius: 0 4px 4px 0; }
.usage-why-link { align-self: flex-start; }
@media (max-width: 1000px) { .usage-pair { grid-template-columns: minmax(0, 1fr); } }
.usage-keys .spark path { stroke: var(--series-1); }
.chart .mark.s1 { fill: var(--series-1); }
.chart .mark.s2 { fill: var(--series-2); }
.chart .mark.bad { fill: var(--red); }
.chart .chart-dot { stroke: var(--bg-elev); stroke-width: 2; }
.chart-line { fill: none; stroke: var(--series-1); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-cap { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 4 3; }
.chart-hit { fill: transparent; }
.chart g.day { outline: none; }
.chart g.day:hover .chart-hit, .chart g.day:focus .chart-hit { fill: color-mix(in oklch, var(--ink-3) 10%, transparent); }
/* Today is partial: drawn faded, never hidden. */
.chart g.day.today { opacity: 0.45; }
.chart-tip { min-height: 1.4em; color: var(--ink-2); margin-top: var(--s-2); }
.chart-legend { display: flex; gap: var(--s-4); color: var(--ink-2); }
.chart-key { display: inline-flex; align-items: center; gap: 6px; }
.chart-swatch { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.chart-swatch.s1 { background: var(--series-1); }
.chart-swatch.s2 { background: var(--series-2); }

.meter { height: 8px; border-radius: var(--r-pill); background: var(--bg-sunk); overflow: hidden; border: 1px solid var(--line); }
.meter-fill { height: 100%; background: var(--honey); border-radius: var(--r-pill); }
.meter-fill.warn { background: var(--amber); }
.meter-fill.over { background: var(--red); }

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

.stack > * + * { margin-top: var(--s-5); }
.stack-lg > * + * { margin-top: var(--s-7); }
.row { display: flex; align-items: center; gap: var(--s-4); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--s-5); }
.spacer { flex: 1; }
.wrap-gap { display: flex; flex-wrap: wrap; gap: var(--s-3); }

.menu-btn { display: none; }
.nav-scrim { display: none; }

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

/* Console v3 (M4-0377) has no icon rail: the sidebar carries the project
   switcher and the group names, so it keeps its width down to the phone
   breakpoint, where it becomes the drawer. */
@media (max-width: 1200px) {
  .cols-4 { grid-template-columns: 1fr 1fr; }
  .cols-3 { grid-template-columns: 1fr 1fr; }
  .editor-grid { grid-template-columns: 1fr; }
  .fence-side { max-height: none; }
  .fence-top { grid-template-columns: minmax(0, 1fr); }
  .fence-list { max-height: 260px; }
}

/* A phone: the card leaves the map and sits below it. */
@media (max-width: 768px) {
  .fence-editor { --fence-map-h: 420px; }
  .fence-side .fence-form { max-height: none; }
  .fence-hint { max-width: calc(100% - 2 * var(--s-4)); bottom: calc(var(--s-4) + 30px); }
  .map-wrap .fence-zoom { bottom: calc(var(--s-4) + 72px); }
  .fence-stage .map-note { bottom: calc(var(--s-4) + 64px); }
}

@media (max-width: 768px) {
  /* minmax(0, 1fr), not a bare 1fr: a bare 1fr track is sized by its content's
     min-content, so a wide page body (the device page's Points table in its
     .table-scroll) would stretch the one column past the viewport and push the
     topbar sideways. minmax(0, …) lets the column shrink to the viewport and
     the body's own wrap/scroll take the overflow (M4-0381, Contract-change:
     D131 — the v3 device page is the first phone body wide enough to show it). */
  .shell { grid-template-columns: minmax(0, 1fr); }
  .sidebar {
    position: fixed; inset: 0 auto 0 0; z-index: 50;
    width: 260px; height: 100vh;
    transform: translateX(-100%);
    /* Closed, the drawer is hidden as well as off-screen, so its links leave the
       tab order; visibility flips only once the slide-out has finished. */
    visibility: hidden;
    transition: transform var(--dur) var(--ease), visibility 0s linear var(--dur);
    box-shadow: 0 0 60px -20px color-mix(in oklch, oklch(15% 0.02 60) 60%, transparent);
  }
  .shell[data-nav="open"] .sidebar {
    transform: translateX(0);
    visibility: visible;
    transition: transform var(--dur) var(--ease), visibility 0s;
  }
  :root { --sidebar-w: 0px; }
  .nav-item { padding: var(--s-3) var(--s-4); }
  .menu-btn { display: inline-flex; }
  .shell[data-nav="open"] .nav-scrim { display: block; position: fixed; inset: 0; z-index: 40; background: color-mix(in oklch, oklch(15% 0.02 60) 45%, transparent); }

  .topbar { padding: 0 var(--s-6); gap: var(--s-4); }
  /* The breadcrumb takes the free width; the page's name is enough. */
  .topbar > .spacer { display: none; }
  .crumb-scope, .crumb-sep { display: none; }
  .account-btn { height: 44px; }
  .content { padding: var(--s-7) var(--s-6) var(--s-9); }
  .cols-2, .cols-3, .cols-4 { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr; }
  .page-head-row { align-items: flex-start; }

  /* Tables reflow to stacked cards — the page body must never scroll sideways. */
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table thead { display: none; }
  .table tr { padding: var(--s-5) var(--s-6); border-bottom: 1px solid var(--line); }
  .table tr:last-child { border-bottom: none; }
  .table td { border: none; padding: var(--s-2) 0; text-align: left; }
  .table td::before {
    content: attr(data-label);
    display: block;
    font-family: var(--f-mono); font-size: var(--t-eyebrow);
    letter-spacing: var(--tr-eyebrow); text-transform: uppercase;
    color: var(--ink-3); margin-bottom: 2px;
  }
  .table td:empty { display: none; }
  .table .cell-actions, .table .cell-num { text-align: left; }
  .table .cell-actions { padding-top: var(--s-4); }
  /* The Activity table keeps its columns and scrolls inside its own wrap. */
  .table-scroll .table { display: table; width: 100%; }
  .table-scroll .table thead { display: table-header-group; }
  .table-scroll .table tbody { display: table-row-group; width: auto; }
  .table-scroll .table tr { display: table-row; width: auto; padding: 0; }
  .table-scroll .table td { display: table-cell; width: auto; padding: 9px 8px; border-bottom: 1px solid var(--line); }
  .table-scroll .table td::before { content: none; }
  .table-scroll .table .cell-num { text-align: right; }
  .activity-controls > .spacer { display: none; }

  .btn { min-height: 40px; }
  .btn-sm { min-height: 34px; }
  .toasts { left: var(--s-5); right: var(--s-5); bottom: var(--s-5); max-width: none; }
}

/* ---------- map view (M4-0182) ---------- */

/* The map's paint colours, in sRGB on purpose: mapbox-gl 3.9.4 cannot parse
   oklch() (its csscolorparser takes keywords, #rgb, #rrggbb and comma rgb/hsl
   only), and getComputedStyle returns a custom property exactly as written. The
   tokens stay the source of truth for everything around the map. Fence and track
   differ in lightness (0216): OKLab L 0.64 vs 0.46 light, 0.80 vs 0.62 dark. */
/* Chart series slots — the v3 board's validated pair (D133), as above:
   slot 1 honey, slot 2 blue. */
:root {
  --series-1: #c27a1a;
  --series-2: #2f62a8;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --series-1: #bf8024; --series-2: #5b8fd6; }
}
:root[data-theme="dark"] { --series-1: #bf8024; --series-2: #5b8fd6; }
:root {
  --map-track: #1f5f8b;
  --map-fence: #c97a12;
  --map-gated: #c4472f;
  /* Device colours past the first (M4-0277, Map.dc.html's swatches): OKLab L
     0.52 and 0.51 light, 0.64 and 0.60 dark, so every track stays at least 0.10
     from the fence (D73 5). */
  --map-track-2: #2e7a4f;
  --map-track-other: #6e655a;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --map-track: #4a90c2;
    --map-fence: #f0a53a;
    --map-gated: #ef7b63;
    --map-track-2: #48a07a;
    --map-track-other: #8a7f6c;
  }
}
:root[data-theme="dark"] {
  --map-track: #4a90c2;
  --map-fence: #f0a53a;
  --map-gated: #ef7b63;
  --map-track-2: #48a07a;
  --map-track-other: #8a7f6c;
}

/* Design v2's Map (M4-0277): the map is the page under the topbar, edge to
   edge, and its chrome floats over it (Map.dc.html; the kit's v2-float,
   v2-map-bar, v2-map-panel, v2-card, v2-zoom, v2-fresh, v2-legend). */
.content-bleed { padding: 0; }
.map-stage { position: relative; height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h)); min-height: 520px; overflow: hidden; }
.map-stage > .map-wrap { position: absolute; inset: 0; border: 0; border-radius: 0; min-height: 0; }
.map-float {
  position: absolute; z-index: 2;
  background: var(--bg-elev); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 6px 24px color-mix(in oklch, var(--ink) 10%, transparent);
}
.map-bar { top: 16px; left: 16px; right: 16px; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-5); padding: 8px 10px; }
.map-bar .seg { flex-wrap: wrap; max-width: 100%; }
.map-bar .spacer { flex: 1; }
.map-panel { top: 76px; left: 16px; bottom: 60px; width: 288px; display: flex; flex-direction: column; overflow: hidden; }
.map-panel-head { padding: 14px 16px 10px; border-bottom: 1px solid var(--line); }
.map-panel-head .h3 { font-weight: 600; margin: 0; }
.map-count { margin-top: 3px; }
.map-search { margin-top: 10px; padding-top: 6px; padding-bottom: 6px; font-size: var(--t-sm); width: 100%; }
.map-panel-filter { padding: 8px 16px; border-bottom: 1px solid var(--line); }
.map-panel-filter[hidden] { display: none; }
.map-cap { display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-3); padding: 10px 16px; border-bottom: 1px solid var(--line); }
.map-cap[hidden] { display: none; }
.map-dev-list { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow-y: auto; }
.map-dev {
  display: grid; grid-template-columns: 10px minmax(0, 1fr) auto; gap: 10px; align-items: center;
  padding: 11px 16px; border: 0; border-bottom: 1px solid var(--line); background: transparent;
  color: var(--ink); font: inherit; text-align: left; cursor: pointer; min-width: 0;
}
.map-dev:hover { background: color-mix(in oklch, var(--ink) 3%, transparent); }
.map-dev[aria-current="true"] { background: color-mix(in oklch, var(--honey) 12%, transparent); }
.map-dev-id { display: flex; flex-direction: column; min-width: 0; overflow-wrap: anywhere; }
.map-swatch { width: 10px; height: 10px; border-radius: 50%; }
.map-none { padding: 11px 16px; margin: 0; overflow-wrap: anywhere; }
.map-panel-foot { padding: 12px 16px; border-top: 1px solid var(--line); }
.map-card { top: 76px; right: 16px; width: 300px; padding: 16px; max-height: calc(100% - 76px - 168px); overflow-y: auto; min-width: 0; }
.map-card.is-empty { visibility: hidden; }
.map-card-id { font-size: 12.5px; overflow-wrap: anywhere; }
.map-card-filtered { color: var(--red); margin-top: var(--s-2); }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: var(--t-xs); margin-top: 12px; }
.kv dt { color: var(--ink-3); }
.kv dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
/* The no-basemap note and the empty state sit between the panel and the card. */
.map-basemap-note { top: 76px; left: 332px; right: 332px; margin-inline: auto; width: fit-content; max-width: 560px; padding: 12px 16px; display: flex; gap: 12px; align-items: flex-start; }
.map-basemap-note > svg { color: var(--ink-3); flex: none; margin-top: 1px; }
.map-empty { bottom: 60px; left: 332px; right: 332px; margin-inline: auto; width: fit-content; padding: 6px 12px; font-size: var(--t-sm); }
.map-empty[hidden] { display: none; }
.map-zoom { right: 16px; bottom: 84px; display: flex; flex-direction: column; overflow: hidden; }
.map-zoom button { width: 36px; height: 36px; border: 0; background: transparent; color: var(--ink-2); font: inherit; font-size: 18px; cursor: pointer; }
.map-zoom button + button { border-top: 1px solid var(--line); }
.map-fresh { left: 16px; bottom: 16px; padding: 7px 12px; font-size: var(--t-micro); color: var(--ink-2); display: flex; gap: 10px; align-items: center; border-radius: var(--r-pill); max-width: calc(100% - 32px - 400px); }
.map-fresh:has(.map-tiles-off) { flex-wrap: wrap; row-gap: 6px; border-radius: var(--r-lg); }
.map-fresh .map-tiles-off { flex-basis: 100%; }
/* The two-line chip is taller: the panel above it gives way. */
.map-stage:has(.map-tiles-off) > .map-panel { bottom: 84px; }
.map-legend { right: 16px; bottom: 16px; margin: 0; padding: 9px 14px; list-style: none; font-size: var(--t-micro); color: var(--ink-2); display: flex; gap: 14px; align-items: center; border-radius: var(--r-pill); }
.map-legend li { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
/* On a basemap Mapbox's own logo and attribution stay visible above the
   floating chips; the view's duplicate attribution line is not needed here. */
.map-stage .map-attr { display: none; }
.map-stage .mapboxgl-ctrl-bottom-left, .map-stage .mapboxgl-ctrl-bottom-right { bottom: 50px; }
.map-stage .mapboxgl-ctrl-bottom-left { left: 312px; }
/* A phone stacks the chrome under the map instead of over it. */
@media (max-width: 900px) {
  .map-stage { height: auto; min-height: 0; overflow: visible; display: flex; flex-direction: column; gap: var(--s-4); padding: var(--s-5); }
  .map-stage > .map-wrap { position: relative; inset: auto; height: 420px; border: 1px solid var(--line); border-radius: var(--r-lg); order: 2; }
  .map-stage > .map-float { position: static; width: auto; max-width: none; max-height: none; box-shadow: none; }
  .map-stage > .map-bar { order: 1; }
  .map-stage > .map-fresh { order: 3; border-radius: var(--r-lg); flex-wrap: wrap; }
  .map-stage > .map-legend { order: 4; flex-wrap: wrap; border-radius: var(--r-lg); }
  .map-stage > .map-card { order: 5; }
  .map-stage > .map-card.is-empty { display: none; }
  .map-stage > .map-panel { order: 6; }
  .map-basemap-note, .map-empty { left: var(--s-4); right: var(--s-4); }
  .map-basemap-note { top: var(--s-4); }
  .map-empty { bottom: var(--s-4); }
  .map-zoom { bottom: var(--s-4); }
  .map-stage .mapboxgl-ctrl-bottom-left, .map-stage .mapboxgl-ctrl-bottom-right { bottom: 0; }
  .map-stage .mapboxgl-ctrl-bottom-left { left: 0; }
}

/* ---------- one device's page (M4-0293) ---------- */

/* The install id is the title: device-made and up to 128 bytes, so it breaks
   anywhere rather than widening the page. */
.device-page .device-title { min-width: 0; flex: 1 1 320px; }
.device-page .device-id { font-size: clamp(18px, 2.4vw, 26px); overflow-wrap: anywhere; word-break: break-word; }
.device-page .device-links { flex-wrap: wrap; }
/* The head's actions (Open on map · Upload queued points now · Request logs)
   wrap rather than running past a narrow viewport (M4-0381; the three buttons
   are ~450 px in a row, wider than a 390 px phone). */
.device-page .device-actions { flex-wrap: wrap; }
.device-tiles { margin-bottom: var(--s-8); }
.device-tiles .stat-value { overflow-wrap: anywhere; }
.device-card .set-aside { margin-bottom: var(--s-4); }
.device-grid { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--s-7); margin-bottom: var(--s-7); }
.device-grid > section.device-card + section.device-card { margin-top: 0; }
.device-page > div > section.device-card { margin-top: var(--s-7); }
.device-card { min-width: 0; }
.device-card .card-head { flex-wrap: wrap; }

/* Last 24 hours: the track drawn from the points (no basemap). */
.minimap-wrap { background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.minimap { display: block; width: 100%; height: auto; max-height: 300px; }
.minimap .mm-track { fill: none; stroke: var(--ink-3); stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.minimap .mm-point { fill: var(--ink-2); }
.minimap .mm-gated { fill: none; stroke: var(--red); stroke-width: 1.5; }
.minimap .mm-halo { fill: color-mix(in oklch, var(--honey) 22%, transparent); stroke: color-mix(in oklch, var(--honey) 60%, transparent); stroke-width: 1; }
.minimap .mm-newest { fill: var(--honey); stroke: var(--bg-elev); stroke-width: 2; }
.minimap-legend { display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-6); margin-top: var(--s-4); }
.minimap-legend > span { display: inline-flex; align-items: center; gap: 6px; }
.mm-key { display: inline-block; width: 10px; height: 10px; border-radius: 50%; }
.mm-key-track { height: 2px; width: 14px; border-radius: 1px; background: var(--ink-3); }
.mm-key-gated { border: 1.5px solid var(--red); }
.mm-key-newest { background: var(--honey); }
.minimap-foot { margin-top: var(--s-3); }

/* Device's own report: one fact a line, the value right. */
.report-rows { display: grid; gap: var(--s-3); }
.report-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-5); font-size: var(--t-sm); border-bottom: 1px dashed var(--line); padding-bottom: var(--s-3); }
.report-row:last-child { border-bottom: none; }
.report-value { text-align: right; min-width: 0; overflow-wrap: anywhere; }
.report-value.bad, .log-summary .bad { color: var(--red); }
.report-error { font-size: var(--t-xs); }
.report-foot { margin-top: var(--s-5); }

/* Commands and their uploaded lines. */
.log-summary { flex-wrap: wrap; gap: var(--s-3); }
.device-logs:not(:empty) { margin-top: var(--s-6); }
.log-lines {
  font-family: var(--f-mono); font-size: var(--t-micro); line-height: 1.6;
  background: var(--bg-sunk); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: var(--s-4) var(--s-5); max-height: 420px; overflow: auto;
}
.log-line { white-space: pre-wrap; overflow-wrap: anywhere; }
.log-line .log-ts, .log-line .log-cat { color: var(--ink-3); }
.log-line .log-level { text-transform: uppercase; }
.log-error .log-level, .log-error .log-msg { color: var(--red); }

@media (max-width: 1000px) {
  .device-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Overview: setup checklist and foot (M4-0265, Overview.dc.html) ----------
   Ported from the canvas's v2-onboard / v2-steps, without the prefix (0216 §Styles). */
.setup { margin-bottom: var(--s-8); }
.setup-item {
  border: 1px solid color-mix(in oklch, var(--honey) 45%, var(--line));
  background: color-mix(in oklch, var(--honey) 7%, var(--bg-elev));
  border-radius: var(--r-lg);
  padding: 20px 22px;
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 18px; align-items: center;
}
.setup-item + .setup-item { margin-top: var(--s-4); }
.setup-steps { display: flex; gap: 6px; }
.setup-steps i { width: 26px; height: 4px; border-radius: 2px; background: var(--line-strong); display: block; }
.setup-steps i.done { background: var(--honey); }
.setup-title { font-weight: 600; }
.setup-text { margin-top: 3px; max-width: 70ch; }
.setup-more { margin-top: var(--s-4); }
.overview-dashboard[hidden] { display: none; }
/* M4-0340: when the rollup figures were computed, above the tiles. */
.overview-asof { margin: 0 0 var(--s-4); max-width: 80ch; }
.overview-asof[hidden] { display: none; }

/* ---------- Overview: org tiles and Open problems (M4-0295, design pass §0295) ---------- */
.overview-dashboard { display: grid; gap: var(--s-7); margin-bottom: var(--s-8); }
.overview-tiles .tile { display: flex; flex-direction: column; min-width: 0; }
.tile-partial { color: var(--ink-2); }
.problems .section-head { margin-bottom: var(--s-4); }
.problems-list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--bg-elev); }
.problem { display: grid; grid-template-columns: 84px minmax(0, 1fr) auto; gap: var(--s-4); align-items: center; padding: 12px 16px; }
.problem + .problem { border-top: 1px solid var(--line); }
.problems-more { margin-top: var(--s-3); }
@media (max-width: 640px) { .problem { grid-template-columns: minmax(0, 1fr); } }
/* M4-0382 (Main.dc.html): Needs attention as one card, its rows divided by
   lines, and Recent changes beside it; they stack when the row is narrow. */
.overview-split { display: flex; flex-wrap: wrap; gap: var(--s-6); align-items: flex-start; }
.overview-split > .problems { flex: 999 1 520px; min-width: 0; padding: 18px 18px 8px; }
.overview-split > .overview-recent { flex: 1 1 300px; min-width: 0; padding: 18px; }
.overview-split > section + section { margin-top: 0; }
.overview-split .section-head { margin-bottom: var(--s-3); }
.overview-split .problems-list { border: 0; border-radius: 0; background: none; }
.overview-split .problem { grid-template-columns: 110px minmax(0, 1fr) auto; padding: 12px 0; border-top: 1px solid var(--line); }
.overview-split .problems-none { margin: 0 0 var(--s-4); }
.problem-sub { margin-top: 2px; }
/* M4-0382 (D135): the KPI row's "of N", a failure count in red, the cap bar,
   and the region chip and count in the projects card. */
.stat-of { font-size: 16px; font-weight: 500; color: var(--ink-3); }
.stat-bad { color: var(--red); }
.tile-cap { margin: 4px 0 2px; }
.project-cell { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.region-chip { font-size: 11px; }
.overview-projects .section-head { align-items: baseline; }
.recent-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.recent-item { display: flex; flex-direction: column; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 640px) { .overview-split .problem { grid-template-columns: minmax(0, 1fr); } }
.overview-foot {
  display: flex; flex-wrap: wrap; gap: var(--s-4) 32px;
  margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--line);
  font-size: var(--t-xs); color: var(--ink-3);
}
@media (max-width: 640px) { .setup-item { grid-template-columns: minmax(0, 1fr); } }
.strong { font-weight: 500; }

/* Settings (M4-0271, Settings.dc.html): cards with an h2 head, left-aligned
   key/value rows (v2's .v2-kv as Settings sets it), the danger row at a card's
   foot, and Organisation beside Appearance. */
.settings-card { padding: 20px; }
.kv.kv-left { grid-template-columns: 160px 1fr; margin-top: 0; font-size: var(--t-sm); }
.kv.kv-left dd { text-align: left; color: var(--ink); }
.settings-note { margin: 10px 0 0; max-width: 72ch; }
.settings-foot {
  display: flex; justify-content: space-between; align-items: center; gap: 20px;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line);
}
.settings-foot > p { margin: 0; max-width: 60ch; }
.settings-pair { display: grid; grid-template-columns: 1.5fr 1fr; gap: 18px; }
/* M4-0367: the Account link under Settings, the Account form, the cap control. */
.account-form { margin-top: 18px; max-width: 480px; }
.usage-cap-control:empty { display: none; }
@media (max-width: 760px) {
  .settings-pair { grid-template-columns: 1fr; }
  .settings-foot { flex-direction: column; align-items: flex-start; }
  .kv.kv-left { grid-template-columns: 1fr; }
}

/* ---------- phone layouts (M4-0268; Design v2's PhoneNav, PhoneActivity, PhoneMap) ----------
   The shell's phone breakpoint (768 px) and nothing else: below it the drawer is
   already the navigation (0180); this block makes the v2 phone frame's touch
   targets, Activity's cards and the full-bleed Map. CSS only, no new control:
   every action stays where the desktop has it. */
@media (max-width: 768px) {
  /* v2's phone frame: 44 px targets for the menu, the drawer's links and the
     buttons; a small button keeps 36 px (v2's "Layers", "Filters"). */
  .menu-btn { min-width: 44px; min-height: 44px; align-items: center; justify-content: center; }
  .nav-item { min-height: 44px; }
  .btn { min-height: 44px; }
  .btn-sm { min-height: 36px; }
  /* v2's phone body keeps a 16 px gutter; Login's pane (0272) too. */
  .auth-pane { padding-left: var(--s-6); padding-right: var(--s-6); }

  /* Activity, and a device's recent points: one card per point (v2-pcard), its
     cells a two-column grid of captioned values; the time and the row's link
     take the whole width. Nothing scrolls sideways, not even inside the wrap. */
  .table-scroll { border: 0; border-radius: 0; background: transparent; }
  .table-scroll .table, .table-scroll .table tbody { display: block; width: 100%; }
  .table-scroll .table thead { display: none; }
  .table-scroll .table tr {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px;
    width: 100%; padding: 12px 14px; margin-bottom: 10px;
    border: 1px solid var(--line); border-radius: var(--r-md); background: var(--bg-elev);
  }
  .table-scroll .table tr:last-child { margin-bottom: 0; border-bottom: 1px solid var(--line); }
  .table-scroll .table tr.gated { border-color: color-mix(in oklch, var(--red) 30%, var(--line)); }
  .table-scroll .table tr.gated td { background: transparent; }
  .table-scroll .table td {
    display: block; width: auto; min-width: 0; padding: 0; border: 0;
    white-space: normal; overflow-wrap: anywhere; text-align: left;
  }
  .table-scroll .table td::before {
    content: attr(data-label); display: block;
    font-family: var(--f-mono); font-size: var(--t-eyebrow);
    letter-spacing: var(--tr-eyebrow); text-transform: uppercase;
    color: var(--ink-3); margin-bottom: 2px;
  }
  .table-scroll .table td.cell-actions::before { content: none; }
  .table-scroll .table td:first-child, .table-scroll .table td.cell-actions { grid-column: 1 / -1; }
  .table-scroll .table td:empty { display: none; }
  .table-scroll .table .cell-num { text-align: left; }
  /* A session divider between the cards (M4-0338): a captionless line, not a card. */
  .table-scroll .table tr.session-break { display: block; padding: 0; border: 0; background: transparent; }
  .table-scroll .table tr.session-break td { display: block; padding: 6px 4px; border-left: 0; border-right: 0; border-radius: 0; overflow-wrap: anywhere; }
  .table-scroll .table tr.session-break td::before { content: none; }

  /* Map (PhoneMap): the map is the screen under the topbar, edge to edge; the
     window and layers bar floats on its top, the chosen device's card is a
     bottom sheet on its bottom edge, and the freshness line, the legend and the
     device list follow below it. One grid cell holds the map and its floats. */
  .map-stage { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; padding: 0; height: auto; min-height: 0; overflow: visible; }
  .map-stage > .map-wrap {
    grid-area: 1 / 1; position: relative; inset: auto;
    height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h)); min-height: 420px;
    border: 0; border-radius: 0;
  }
  .map-stage > .map-bar {
    grid-area: 1 / 1; align-self: start; position: relative; inset: auto; z-index: 2; margin: 12px;
    box-shadow: 0 6px 24px color-mix(in oklch, var(--ink) 10%, transparent);
  }
  .map-stage > .map-card {
    grid-area: 1 / 1; align-self: end; position: relative; inset: auto; z-index: 3;
    width: auto; max-height: 45vh; max-height: 45dvh; overflow-y: auto; margin: 0;
    border-width: 1px 0 0; border-radius: 18px 18px 0 0; padding: 10px 18px 22px;
    box-shadow: 0 -6px 24px color-mix(in oklch, var(--ink) 12%, transparent);
  }
  .map-stage > .map-card::before { content: ""; display: block; width: 36px; height: 4px; border-radius: 2px; background: var(--line-strong); margin: 0 auto 12px; }
  .map-stage > .map-fresh, .map-stage > .map-legend, .map-stage > .map-panel { margin: 12px 12px 0; }
  .map-stage > .map-panel { margin-bottom: 12px; }
  /* The zoom and the no-basemap note sit at the map's middle, clear of the bar
     above and the sheet below. */
  .map-stage .map-zoom { top: 50%; bottom: auto; right: 12px; transform: translateY(-50%); }
  .map-stage .map-basemap-note { top: 50%; bottom: auto; left: 12px; right: 60px; margin: 0; width: auto; max-width: none; transform: translateY(-100%); }
}

/* Settings' server reads (M4-0320/0321/0322, views/settings-data.js). */
.settings-retention { margin-top: 14px; }
.settings-retention > p.small { margin: 0; }
/* ---------- Project settings (M4-0383; ProjectSettings.dc.html) ----------
   A sticky section index beside the cards (Remote config's, 0379), and each
   card a list of rows: what the row is on the left, its one control on the
   right, a hairline between rows. */
.settings-layout { display: flex; align-items: flex-start; gap: 24px; }
.settings-index {
  flex: 0 0 200px; position: sticky; top: calc(var(--topbar-h) + 16px);
  display: flex; flex-direction: column; gap: 2px;
}
.settings-index a {
  display: flex; align-items: center; min-height: 36px; padding: 0 10px; border-radius: 10px;
  color: var(--ink-2); text-decoration: none; font-size: var(--t-sm);
}
.settings-index a:hover { background: var(--bg-sunk); }
.settings-index a[aria-current="true"] { background: var(--bg-sunk); color: var(--ink); font-weight: 600; }
.settings-form { flex: 1 1 auto; min-width: 0; max-width: 820px; padding-bottom: 24px; }
.settings-form .readonly-banner { margin-bottom: 0; }
.ps-card { padding: 20px 0 4px; scroll-margin-top: calc(var(--topbar-h) + 16px); }
.ps-card > .card-head { padding: 0 20px 6px; }
.ps-card > .settings-retention { margin: 8px 20px 16px; }
.settings-retention-line { margin: 0; font-weight: 500; }
.ps-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px;
  padding: 16px 20px; border-top: 1px solid var(--line);
}
.ps-card > .card-head + .ps-row { border-top: 0; }
.ps-row-main { display: flex; flex-direction: column; gap: 4px; flex: 1 1 320px; min-width: 0; }
.ps-row-aside { flex: none; }
.ps-label { font-weight: 500; font-size: var(--t-sm); }
.ps-value { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ps-help { margin: 0; max-width: 60ch; }
.ps-id { word-break: break-all; }
.ps-chip { font-family: var(--f-body); font-size: 12px; border-radius: var(--r-pill); padding: 2px 9px; }
.ps-row-name .field { margin: 0; max-width: 360px; }
.ps-row-name { align-items: flex-end; }
.dialog-message > p { margin: 0 0 10px; }
.erase-list { margin: 0 0 12px; padding-left: 20px; font-size: var(--t-sm); }
.erase-list li { margin: 4px 0; }
@media (max-width: 760px) {
  .settings-layout { flex-direction: column; align-items: stretch; }
  .settings-index { position: static; flex: none; flex-direction: row; flex-wrap: wrap; }
  .ps-row-name { align-items: stretch; }
}
.settings-hook-url { word-break: break-all; }

/* The Members tab (M4-0267, M4-0323; v3 board M4-0389, D129): the inline
   invite form, a compact role select per row, the member cell's initials and
   chips, the three-role legend, and the invite link shown once in its dialog. */
.select.select-sm { width: auto; min-width: 0; padding-top: 4px; padding-bottom: 4px; font-size: var(--t-sm); }
.members-status { margin-top: 12px; }
.invite-form { padding: var(--s-5); }
.invite-fields { display: flex; flex-wrap: wrap; gap: var(--s-4); align-items: flex-end; }
.invite-fields > .field { margin-bottom: 0; flex: 1 1 260px; }
.invite-fields > .field + .field { flex: 0 1 220px; }
.invite-note { margin: var(--s-3) 0 0; }
.invite-error { margin-top: var(--s-3); }
.member-who { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.member-av {
  width: 30px; height: 30px; border-radius: 999px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in oklch, var(--honey) 22%, transparent); color: var(--accent-text);
  font-weight: 600; font-size: 12px;
}
.member-chip {
  display: inline-flex; align-items: center; padding: 2px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 500; white-space: nowrap;
  background: var(--bg-sunk); color: var(--ink-2);
}
.member-chip.warn { background: color-mix(in oklch, var(--amber) 18%, transparent); color: var(--honey-ink); }
:root[data-theme="dark"] .member-chip.warn { color: var(--honey); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .member-chip.warn { color: var(--honey); } }
.members-legend {
  display: flex; flex-wrap: wrap; gap: 6px 20px;
  margin-top: var(--s-4); padding-top: var(--s-4); border-top: 1px solid var(--line);
}
.members-legend strong { color: var(--ink); font-weight: 600; }
.invite-link {
  display: block; padding: 10px 12px; border: 1px solid var(--line); border-radius: 6px;
  word-break: break-all; user-select: all; font-size: var(--t-sm);
}

/* Phone: Sign out in the drawer's foot, and Activity's "Filters · N" collapse
   (M4-0329; Design v2's PhoneNav and PhoneActivity). Above 768 px the filters'
   group lays out as if it were not there and the button is not shown. */
.activity-filters { display: contents; }
.activity-filters-btn { display: none; }
@media (max-width: 768px) {
  .sidebar-foot > .btn { margin-top: var(--s-3); }
  .activity-filters-btn { display: inline-flex; align-self: flex-end; }
  .activity-controls:not([data-filters="open"]) .activity-filters { display: none; }
  .activity-controls[data-filters="open"] .activity-filters {
    display: flex; flex-wrap: wrap; align-items: flex-end;
    gap: var(--s-4) var(--s-5); flex-basis: 100%; min-width: 0;
  }
}

/* ---------- Sidebar foot: the org switcher (M4-0336) ---------- */
.sidebar-foot .org-switcher { width: 100%; max-width: 100%; margin-top: 2px; }

/* ---------- The Webhooks page (M4-0364) ---------- */
.wh-types { border: 0; padding: 0; margin: 0; min-width: 0; display: flex; flex-wrap: wrap; gap: 8px 18px; }
.wh-types > legend { padding: 0; margin-bottom: 6px; width: 100%; }
.wh-check { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-sm); cursor: pointer; }
.wh-check input { margin: 0; }
/* Webhooks & events as one screen (M4-0378, D129; Webhooks.dc.html): tabs, the
   endpoints table with its side panel BESIDE it (it wraps under the table only
   when the two cannot share the row), and the deliveries and events tables. */
.wh-screen .readonly-banner { margin-bottom: 0; }
/* The board's state chips are sentence case in the body face, not the kit's
   uppercase mono pill. */
.wh-screen .chip { font-family: var(--f-body); font-size: 12px; border-radius: var(--r-pill); padding: 2px 9px; }
.wh-screen .pill {
  font-family: var(--f-body); font-size: var(--t-xs); letter-spacing: 0;
  text-transform: none; border-radius: var(--r-pill); padding: 2px 9px;
}
.wh-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); overflow-x: auto; }
.wh-tabs [role="tab"] {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; cursor: pointer;
  padding: 10px 14px; border: 0; border-bottom: 2px solid transparent; background: none;
  font: inherit; font-weight: 500; color: var(--ink-3);
}
.wh-tabs [role="tab"][aria-selected="true"] { color: var(--ink); border-bottom-color: var(--honey); }
.wh-tabs [role="tab"]:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.wh-screen > .wh-tabs + [role="tabpanel"] { margin-top: var(--s-6); }
.wh-screen [role="tabpanel"][hidden] { display: none; }
.wh-split { display: flex; flex-wrap: wrap; gap: var(--s-6); align-items: flex-start; }
.wh-split > .wh-table-card { flex: 999 1 480px; min-width: 0; }
.wh-panel-host { flex: 1 1 360px; min-width: 0; }
.wh-panel-host:empty { display: none; }
.wh-table-card { padding: 0; overflow: hidden; }
.wh-table-card > .empty, .wh-table-card > .errorbox, .wh-table-card > .skel,
.wh-table-card > div > .skel { margin: var(--s-6); }
.wh-table-card .table-wrap { border: 0; border-radius: 0; }
.wh-row { cursor: pointer; }
.table tbody tr.sel td { background: color-mix(in oklch, var(--honey) 14%, transparent); }
.wh-host { display: block; font-weight: 600; }
.wh-path, .wh-line { display: block; font-size: var(--t-xs); }
.wh-line { margin-top: 3px; }
.wh-note { margin: 0; padding: var(--s-4) var(--s-6); border-top: 1px solid var(--line); }
.wh-bar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 14px; border-bottom: 1px solid var(--line);
}
.wh-scope { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-sm); }
.wh-uid { font-size: var(--t-xs); }
.wh-panel { display: flex; flex-direction: column; gap: var(--s-6); padding: var(--s-6); min-width: 0; }
.wh-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.wh-panel-title { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-width: 0; }
.wh-panel-title .h2 { overflow-wrap: anywhere; }
.wh-url-row {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  padding: 8px 10px; border-radius: var(--r-md); background: var(--bg-sunk);
}
.wh-url-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-xs); }
.wh-kv.kv-left { grid-template-columns: 120px 1fr; }
.wh-kv dd { text-align: left; }
.wh-eyebrow { margin-bottom: calc(-1 * var(--s-3)); }
.wh-queue { display: flex; flex-direction: column; gap: var(--s-5); align-items: flex-start; }
.wh-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; width: 100%; }
.wh-tile { display: flex; flex-direction: column; gap: 2px; padding: 12px; border-radius: var(--r-md); background: var(--bg-sunk); }
.wh-tile-label { font-size: var(--t-xs); color: var(--ink-3); }
.wh-tile strong { font-family: var(--f-display); font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; }
.wh-tile-bad { background: color-mix(in oklch, var(--red) 12%, transparent); }
.wh-tile-bad .wh-tile-label, .wh-tile-bad strong { color: var(--red); }
.wh-latest { list-style: none; margin: 0; padding: 0; width: 100%; }
.wh-latest li { display: flex; gap: 10px; align-items: center; padding: 8px 0; border-top: 1px solid var(--line); font-size: var(--t-sm); }
.wh-latest-what { flex: 1; min-width: 0; }
.wh-latest-when { font-size: var(--t-xs); white-space: nowrap; }
.wh-panel-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap;
  padding-top: var(--s-5); border-top: 1px solid var(--line);
}
/* ---------- Trips (M4-0366) ---------- */
/* A trip's map is the Map's surface in a card: the note at the top and the
   zoom at the right, inside the map, at every width. */
.trip-map { min-height: 0; height: clamp(300px, 52vh, 520px); }
.trip-map .map-basemap-note { top: 12px; left: 12px; right: 60px; margin: 0; width: auto; max-width: 560px; transform: none; }
.trip-map .map-zoom { top: 12px; bottom: auto; right: 12px; transform: none; }
.trip-key-start { background: var(--map-track-2); }
.trip-key-end { background: var(--map-fence); }
.trip-key-track { height: 3px; width: 14px; border-radius: 1px; background: var(--map-track); }
/* ---------- The remote config editor (M4-0363; views/config.js) ----------
   Settings' cards, one per section of the document, each a two-column grid of
   v2 fields (one column on a phone); checkboxes as a label row with the hint
   under its text; the below-900 s note in the accent ink; and the save bar,
   which stays in view at the bottom of the page. */
.settings-config { margin: 14px 0 0; }
.config-sub { margin: -6px 0 16px; max-width: 72ch; }
.config-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 24px; align-items: start; }
.config-grid > .field { min-width: 0; }
.config-check { padding-top: 22px; }
.config-check-label { display: flex; align-items: flex-start; gap: 10px; font-size: var(--t-sm); color: var(--ink); cursor: pointer; }
.config-check-label input { margin-top: 2px; accent-color: var(--accent-text); flex: none; width: 16px; height: 16px; }
.config-check-label input:disabled + span { color: var(--ink-3); cursor: default; }
.config-check > .field-hint, .config-check > .field-error { margin-left: 26px; }
/* Console v3 (M4-0379, RemoteConfig.dc.html): the sticky section index beside
   the cards, the tags (the head's revision and devices, the index's badges, a
   field's "Changed · was …"), each unit after its input, the upload-floor
   warning as an amber block under the interval's input, and the bar's count
   and blocker line. */
.config-floor {
  display: block; margin-top: var(--s-2); padding: 10px 12px; border-radius: var(--r-md, 10px);
  background: color-mix(in oklch, var(--amber) 16%, var(--bg-elev)); font-size: var(--t-xs); color: var(--ink);
}
.config-floor strong { font-weight: 600; color: var(--honey-ink); }
:root[data-theme="dark"] .config-floor strong { color: var(--honey); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .config-floor strong { color: var(--honey); } }
.config-floor[hidden] { display: none; }
.config-rev { font-variant-numeric: tabular-nums; }
.config-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.config-tag {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 999px;
  font-size: var(--t-xs); font-weight: 500; line-height: 1.5; white-space: nowrap;
  background: var(--bg-sunk); color: var(--ink-2); text-decoration: none;
}
a.config-tag:hover { text-decoration: underline; }
.config-tag[hidden] { display: none; }
.config-tag-edit { background: color-mix(in oklch, var(--honey) 18%, transparent); color: var(--honey-ink); }
.config-tag-warn { background: color-mix(in oklch, var(--amber) 18%, transparent); color: var(--honey-ink); }
.config-tag-ok { background: color-mix(in oklch, var(--green) 14%, transparent); color: var(--green); }
.config-tag-bad { background: color-mix(in oklch, var(--red) 13%, transparent); color: var(--red); }
:root[data-theme="dark"] .config-tag-edit, :root[data-theme="dark"] .config-tag-warn { color: var(--honey); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .config-tag-edit, :root:not([data-theme="light"]) .config-tag-warn { color: var(--honey); } }
.config-rev-note { color: var(--ink-3); }
.config-layout { display: flex; align-items: flex-start; gap: 24px; }
.config-index {
  flex: 0 0 200px; position: sticky; top: calc(var(--topbar-h) + 16px);
  display: flex; flex-direction: column; gap: 2px;
}
.config-index a {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  min-height: 36px; padding: 0 10px; border-radius: 10px;
  color: var(--ink-2); text-decoration: none; font-size: var(--t-sm);
}
.config-index a:hover { background: var(--bg-sunk); }
.config-index a[aria-current="true"] { background: var(--bg-sunk); color: var(--ink); font-weight: 600; }
.config-index .config-badge { font-weight: 500; }
.config-form { flex: 1 1 auto; min-width: 0; padding-bottom: 24px; }
.config-card { scroll-margin-top: calc(var(--topbar-h) + 16px); }
.config-input-row { display: flex; align-items: center; gap: 8px; }
.config-input-row .input { flex: 1 1 auto; min-width: 0; }
.config-unit { font-size: var(--t-sm); white-space: nowrap; }
.config-was { font-weight: 500; }
.input.config-changed, .select.config-changed { border-color: var(--honey); }
.config-count { display: block; font-weight: 600; }
.config-blocker { margin: 2px 0 0; font-size: var(--t-xs); color: var(--red); }
.config-blocker[hidden], .config-status[hidden] { display: none; }
.config-blocker a { color: var(--red); text-decoration: underline; }
.config-bar {
  position: sticky; bottom: 0; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-top: 18px; padding: 14px 20px;
  background: var(--bg-elev); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 -6px 24px color-mix(in oklch, var(--ink) 6%, transparent);
}
.config-bar-text { min-width: 0; }
.config-status { margin: 0; }
.config-problem { margin-top: 6px; font-size: var(--t-xs); color: var(--red); display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.config-problem[hidden] { display: none; }
@media (max-width: 760px) {
  .config-grid { grid-template-columns: minmax(0, 1fr); }
  .config-check { padding-top: 0; }
  .config-layout { flex-direction: column; align-items: stretch; }
  .config-index { position: static; flex: none; flex-direction: row; flex-wrap: wrap; }
  .config-bar { flex-direction: column; align-items: stretch; padding: 12px 16px; }
  .config-bar .btn-row { justify-content: flex-end; }
}
/* ---------- The audit log (M4-0376; views/audit.js) ----------
   Console v3's Organisation › Audit log: one card, the filter row on top, the
   When / Who / What table flush to the card's edges, and a footer with the
   order note and "Load older". */
.audit-card { padding: 0; overflow: hidden; }
.audit-filters { display: flex; flex-wrap: wrap; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); }
.audit-filters .select { flex: 0 1 220px; width: auto; min-width: 0; }
.audit-card .table-wrap { border: 0; border-radius: 0; }
.audit-body > .skel-row, .audit-body > div > .skel-row { margin: 12px 14px; }
.audit-body > .empty, .audit-body > .errorbox, .audit-body > .notice { margin: 16px 14px; }
.audit-foot { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px 14px; border-top: 1px solid var(--line); }
.audit-foot:empty { display: none; }
@media (max-width: 760px) {
  .audit-filters .select { flex: 1 1 100%; }
}

/* ---------- Activity and Trips side panels (M4-0380; D129, Activity.dc.html,
   Trips.dc.html) ----------
   Selecting a row opens its panel BESIDE the table; the two share the row while
   they fit (the table first, the panel up to 400 px) and the panel wraps under
   the table only when they cannot. The reason chips sit above the table. */
.ac-split { display: flex; flex-wrap: wrap; gap: var(--s-6); align-items: flex-start; }
.ac-main { flex: 999 1 520px; min-width: 0; }
.ac-panel-host { flex: 1 1 320px; min-width: 0; max-width: 400px; }
.ac-panel-host:empty { display: none; }
.ac-row, .tp-row { cursor: pointer; }
.ac-row:focus-visible, .tp-row:focus-visible { outline: none; box-shadow: inset var(--focus-ring); }
.ac-reasons { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-bottom: var(--s-5); }
.ac-reasons[hidden] { display: none; }
.ac-reason {
  display: inline-flex; align-items: center; padding: 2px 9px; border-radius: var(--r-pill);
  font-size: var(--t-xs); font-weight: 500; white-space: nowrap; font-variant-numeric: tabular-nums;
  background: var(--bg-sunk); color: var(--ink-2);
}
.ac-reason-implausible_speed { background: color-mix(in oklch, var(--red) 12%, transparent); color: var(--red); }
.ac-reason-low_accuracy { background: color-mix(in oklch, var(--amber) 14%, transparent); color: var(--amber); }
.ac-reason-mock { background: color-mix(in oklch, var(--map-track) 12%, transparent); color: var(--map-track); }
.ac-panel, .tp-panel { display: flex; flex-direction: column; gap: var(--s-5); padding: var(--s-6); min-width: 0; }
.ac-panel-head, .tp-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.tp-panel-title { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 0; }
.tp-panel-title .h3, .ac-panel-head .h3 { margin: 0; overflow-wrap: anywhere; }
.ac-held {
  display: flex; flex-direction: column; gap: 4px; padding: 12px; border-radius: var(--r-md);
  background: color-mix(in oklch, var(--red) 10%, transparent); font-size: var(--t-sm);
}
.ac-held strong { color: var(--red); font-weight: 600; }
.ac-mini-wrap { display: flex; flex-direction: column; gap: 6px; }
.ac-mini, .tp-route {
  display: block; width: 100%; height: auto; border-radius: var(--r-md);
  border: 1px solid var(--line); background: var(--bg-sunk);
}
.ac-mini-note { margin: 0; }
.ac-kv.kv-left { grid-template-columns: 96px minmax(0, 1fr); }
.ac-kv .id-chip { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ac-panel-links, .tp-panel-links { flex-wrap: wrap; gap: 8px; }
.tp-route-wrap { display: flex; flex-direction: column; gap: 6px; }
.tp-route-wrap > p { margin: 0; }
.tp-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.tp-stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tp-stat-value { font-family: var(--f-display); font-size: 18px; font-weight: 600; font-variant-numeric: tabular-nums; }

/* D133: an opened fence's name heads the side panel, under the link back. */
.fence-editor-title { margin: 0; min-width: 0; }
/* v3's line above the Activity table (the zone, the chips) and its foot (how
   far the shown rows reach, Load older), D137. */
.ac-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; margin-bottom: var(--s-5); }
.ac-bar[hidden] { display: none; }
.ac-bar .ac-reasons { margin-bottom: 0; }
.ac-zone { margin: 0; }
.ac-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin-top: var(--s-4); }
.ac-foot .ac-cap { margin: 0; }
.ac-foot .ac-cap p { margin: 0; }
.ac-more { margin-left: auto; }
.ac-more:empty { display: none; }
.tp-who { display: block; font-size: var(--t-xs); }
.tp-chip { display: inline-flex; align-items: center; gap: 5px; padding: 2px 9px; border-radius: var(--r-pill); font-size: var(--t-xs); font-weight: 500; white-space: nowrap; background: var(--bg-sunk); color: var(--ink-2); }
.tp-chip-live { background: color-mix(in oklch, var(--green) 14%, transparent); color: var(--green); }
.tp-chip-live::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.ac-actions { flex-wrap: wrap; justify-content: flex-end; }
