/* Alfa Verify — operator instrument panel.
   Calm by design: flat surfaces, hairline borders, generous spacing, two font
   weights (400, 500). Colour is meaning, never decoration:
     navy  = chrome            gold = brand / action / active
     green = GOOD NEWS ONLY    amber = strained / paused / catch-all
     red   = invalid / error   grey  = unknown, and unknown is not a verdict
   Cache hits read as a quiet neutral, deliberately not a verdict colour: the
   difference between a cache hit and a fresh probe is the economics of the
   whole system, so it must never be mistaken for a result.
   Every colour is paired with a text label — colour alone never carries
   meaning here. */

/* ============================================================ tokens ==== */
:root {
  /* chrome */
  --navy:        #0B1727;
  --navy-soft:   #17293F;   /* nav hover */
  --navy-line:   #26394F;   /* decorative hairlines on navy */
  --navy-edge:   #55697F;   /* control borders on navy — 3.2:1 against navy */
  --on-navy:     #FFFFFF;
  --on-navy-dim: #C4CEDA;   /* inactive nav text */

  /* brand */
  --gold:        #C8A02A;   /* logo tile, active underline, 2px header rule */
  --gold-dark:   #9A7A14;   /* large figures on white — 4.06:1, large text only */
  --gold-link:   #856710;   /* same family, dark enough for body-size text */
  --gold-soft:   #F7F1DE;

  /* meaning */
  --green:       #2E9E68;   /* good news only */
  --green-ink:   #14663D;
  --green-soft:  #E7F4EE;
  --green-line:  #2E7C55;   /* the same green, darkened to read on navy */
  --amber:       #D97706;
  --amber-ink:   #8A4B04;
  --amber-soft:  #FBF0E1;
  --red:         #DC2626;
  --red-ink:     #B3201F;
  --red-soft:    #FCEAEA;
  --grey:        #6B7684;   /* unknown — deliberately not a colour */
  --grey-ink:    #4E5866;
  --grey-soft:   #EDEFF2;

  /* surfaces & text */
  --ink:         #16202C;
  --ink-soft:    #58636F;
  --line:        #DEE3E8;   /* decorative hairlines */
  --line-strong: #8B939C;   /* control borders — 3.1:1 against white */
  --line-soft:   #EDEFF2;
  --bg:          #F6F7F9;
  --panel:       #FFFFFF;

  /* focus */
  --focus:       #9A7A14;   /* on light surfaces */
  --focus-navy:  #E3C763;   /* on navy chrome */

  /* spacing scale */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px;
  --r:  4px;
  --tap: 44px;              /* minimum touch target */

  --font: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --mono: "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
}

* { box-sizing: border-box; }

html {
  font-size: 100%; -webkit-text-size-adjust: 100%;
  /* The header is sticky above 768px, so an in-page jump (#health, #logs,
     #jobs) landed its target under the chrome: you arrived at a table's header
     row with the heading that explains it hidden behind the navy. Reserve the
     header's height. Below 768px the header is static and scrolls away, so the
     reservation is dropped in that media query. */
  scroll-padding-top: 116px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 0.9375rem;      /* 15px */
  font-weight: 400;
  line-height: 1.5;
}

h1, h2, h3, th, strong, b, .figure-value, .chip, .btn, button {
  font-weight: 500;          /* the only weight above 400 anywhere */
}

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

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 2px;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0);
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: var(--s3); top: -3rem; z-index: 100;
  background: var(--panel); color: var(--ink);
  padding: var(--s2) var(--s3); border: 1px solid var(--line);
  border-radius: var(--r); transition: top .15s ease;
  /* The skip link is the first thing a keyboard or switch user lands on, so
     it is the last place to be stingy with the target. */
  min-height: var(--tap); display: inline-flex; align-items: center;
}
.skip-link:focus { top: var(--s2); }

/* Blocklist alarm, directly under the header on every page. Red because it is
   a failure, not a caution: while our IP is listed, verdicts are degrading and
   the rest of the dashboard still looks fine. It is `hidden` unless there is
   genuinely something to say, so it never becomes wallpaper. */
.alertbar {
  font-size: .875rem;
  line-height: 1.5;
}
.alertbar[hidden] { display: none; }
.alertbar strong { font-weight: 500; }
/* One line per condition, each painted by its own severity: red is a failure,
   amber is strained-but-working. A bar painted red for an amber condition
   would be colour carrying the wrong meaning. */
.alertline { padding: var(--s3) var(--s4); border-bottom: 1px solid; }
.alertline--error {
  background: var(--red-soft); color: var(--red-ink); border-bottom-color: var(--red);
}
.alertline--warn {
  background: var(--amber-soft); color: var(--amber-ink);
  border-bottom-color: var(--amber);
}
.alertline--warn a { color: var(--amber-ink); }
.alertbar a {
  color: var(--red-ink);
  /* 44px tall so it is a real touch target on a phone, where this banner is
     most likely to be the first thing the owner sees. */
  display: inline-block; min-height: 44px; line-height: 44px;
  margin-left: var(--s2);
}

/* ============================================================ chrome ==== */
header.topbar {
  background: var(--navy);
  color: var(--on-navy);
  border-bottom: 2px solid var(--gold);
  position: sticky; top: 0; z-index: 40;
}

.topbar-main {
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s2) var(--s4);
  min-height: 56px;
}

.brand {
  display: flex; align-items: center; gap: var(--s2);
  color: var(--on-navy); text-decoration: none;
  font-size: 0.9375rem; letter-spacing: .2px; flex: 0 0 auto;
  /* The 26px logo tile set the link's height; it is a real navigation target
     back to Live, so it gets a real target height without growing the tile. */
  min-height: var(--tap);
}
.brand:hover { text-decoration: none; }
.logo {
  width: 26px; height: 26px; border-radius: 3px;
  background: var(--gold); color: var(--navy);
  display: flex; align-items: center; justify-content: center;
  font-weight: 500; font-size: 0.875rem;
}
.brand-name { font-weight: 500; }
.brand-name span { color: var(--on-navy-dim); font-weight: 400; }

/* --- header live strip: filled by the live page; never a placeholder ---- */
.headerstrip {
  display: flex; align-items: center; gap: var(--s4);
  flex: 1 1 auto; min-width: 0;
}
.hstat { display: flex; align-items: baseline; gap: var(--s2); min-width: 0; }
.hstat-label {
  font-size: 0.75rem; color: var(--on-navy-dim); white-space: nowrap;
}
.hstat-value {
  font-size: 0.9375rem; color: var(--on-navy);
  font-variant-numeric: tabular-nums;
}
.hstat-unit { font-size: 0.75rem; color: var(--on-navy-dim); }

/* run-state pill: text always says the state, colour only reinforces it */
.runpill {
  display: inline-flex; align-items: center; gap: var(--s2);
  padding: 3px 10px; border-radius: 11px;
  border: 1px solid var(--navy-edge); background: transparent;
  color: var(--on-navy); font-size: 0.8125rem; white-space: nowrap;
}
.runpill-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--on-navy-dim); flex: 0 0 auto;
}
.runpill[data-run-state="running"] { border-color: var(--green-line); }
.runpill[data-run-state="running"] .runpill-dot { background: var(--green); }
.runpill[data-run-state="paused"]  { border-color: var(--amber); }
.runpill[data-run-state="paused"]  .runpill-dot { background: var(--amber); }
.runpill[data-run-state="stopped"] { border-color: var(--red); }
.runpill[data-run-state="stopped"] .runpill-dot { background: var(--red); }

/* --- run controls: state drives which buttons exist ------------------- */
.runctl { display: flex; align-items: center; gap: var(--s2); flex: 0 0 auto; }
/* Unknown state shows neither Pause nor Resume — we do not guess. */
.runctl .btn-pause, .runctl .btn-resume, .runctl .btn-stop { display: none; }
.runctl[data-run-state="running"] .btn-pause,
.runctl[data-run-state="running"] .btn-stop,
.runctl[data-run-state="paused"]  .btn-resume,
.runctl[data-run-state="paused"]  .btn-stop { display: inline-flex; }

/* Ghost buttons on the navy chrome. The .topbar prefix keeps these ahead of
   the generic button rules further down the file. */
.topbar .btn--ctl {
  background: transparent; color: var(--on-navy);
  border: 1px solid var(--navy-edge);
  min-height: 32px; padding: 4px var(--s3);
}
.topbar .btn--ctl:hover { background: var(--navy-soft); }
.topbar .btn--ctl:focus-visible { outline-color: var(--focus-navy); outline-offset: 1px; }
.topbar .btn--ctl[disabled] { opacity: .45; }
.topbar .btn-resume { border-color: var(--gold); color: #F3E3AE; }
.topbar .btn-stop:hover, .topbar .btn-restart:hover { border-color: #E06666; }

.topbar-right {
  display: flex; align-items: center; gap: var(--s3);
  font-size: 0.8125rem; color: var(--on-navy-dim); flex: 0 0 auto;
}
.topbar-right form { margin: 0; }
.whoami { white-space: nowrap; }
.topbar .btn--quiet {
  background: transparent; color: var(--on-navy-dim);
  border: 1px solid transparent; min-height: 32px; padding: 4px var(--s2);
}
.topbar .btn--quiet:hover { background: var(--navy-soft); color: var(--on-navy); }
.topbar .btn--quiet:focus-visible { outline-color: var(--focus-navy); }

/* --- nav -------------------------------------------------------------- */
nav.mainnav {
  display: flex; flex-wrap: wrap; gap: 0;
  padding: 0 var(--s4);
  border-top: 1px solid var(--navy-line);
}
.navlink {
  color: var(--on-navy-dim); text-decoration: none;
  padding: 0 var(--s3); min-height: 40px;
  display: inline-flex; align-items: center;
  font-size: 0.875rem;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.navlink:hover { color: var(--on-navy); text-decoration: none; }
.navlink.is-active, .navlink[aria-current="page"] {
  color: var(--on-navy); border-bottom-color: var(--gold);
}
.navlink:focus-visible { outline-color: var(--focus-navy); outline-offset: -3px; }

main {
  padding: var(--s5) var(--s4);
  max-width: 1440px; margin: 0 auto;
}

h1 { font-size: 1.25rem; margin: 0 0 var(--s1); letter-spacing: -.1px; }
h2 { font-size: 1rem; margin: 0 0 var(--s3); }
h3 { font-size: 0.875rem; margin: 0 0 var(--s2); }
.sub { color: var(--ink-soft); font-size: 0.875rem; margin: 0 0 var(--s5); }

/* ==================================================== shared: layout ==== */
.section { margin: 0 0 var(--s6); }
.section > h2 {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s3); flex-wrap: wrap;
}
.section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s3); flex-wrap: wrap; margin-bottom: var(--s3);
}
.section-note { color: var(--ink-soft); font-size: 0.8125rem; }

.card, .panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--s4);
}
.section > .card, .section > .panel { margin-bottom: var(--s3); }
.panel { margin-bottom: var(--s4); }
.card--flush { padding: 0; overflow: hidden; }
.card > h2:last-child, .card > *:last-child { margin-bottom: 0; }

/* A <summary> is the only control on a collapsed card, and a one-line one was
   coming out 23px tall — half a finger. Give it the 44px the rest of the
   controls get. Inline links inside a sentence are deliberately left alone:
   padding them out to 44px would break the line they sit in, and a link within
   a block of text is the one target size is not measured on. */
summary {
  /* Padding rather than flex: `display: flex` on a summary removes the
     disclosure triangle in Chrome, and trading the affordance for the target
     size is not a fix. */
  min-height: 44px;
  padding: 11px 0;
  cursor: pointer;
}

.grid { display: grid; gap: var(--s4); }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ==================================================== shared: figures === */
.figures {
  display: grid; gap: var(--s3);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.figure {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r); padding: var(--s4);
  min-width: 0;
}
.figure-value {
  display: block;
  font-size: 1.75rem; line-height: 1.15;
  color: var(--gold-dark);
  font-variant-numeric: tabular-nums; letter-spacing: -.4px;
  overflow-wrap: anywhere;
}
.figure-value.is-good    { color: var(--green-ink); }
.figure-value.is-warn    { color: var(--amber-ink); }
.figure-value.is-bad     { color: var(--red-ink); }
.figure-value.is-plain   { color: var(--ink); }
.figure-value.is-unknown { color: var(--grey-ink); font-size: 1.125rem; }
.figure-label {
  display: block; margin-top: var(--s2);
  font-size: 0.8125rem; color: var(--ink-soft);
}
.figure-note { display: block; margin-top: var(--s1); font-size: 0.75rem; color: var(--ink-soft); }

/* legacy tile figures, still used by pages not yet rebuilt */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--s3); }
.tile { border: 1px solid var(--line); border-radius: var(--r); padding: var(--s3) var(--s4); background: var(--panel); }
.unknown { color: var(--grey-ink); font-style: normal; }

/* ==================================================== shared: empty ===== */
.empty-state {
  border: 1px dashed var(--line);
  border-radius: var(--r);
  padding: var(--s6) var(--s4);
  text-align: center;
  color: var(--ink-soft);
  background: var(--panel);
}
.empty-state strong { display: block; color: var(--ink); margin-bottom: var(--s1); }
.empty-state p { margin: 0; font-size: 0.875rem; }

/* ==================================================== shared: chips ===== */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 9px; border-radius: 11px;
  font-size: 0.75rem; line-height: 1.5; white-space: nowrap;
  border: 1px solid transparent;
  background: var(--grey-soft); color: var(--grey-ink);
}
.chip--valid    { background: var(--green-soft); color: var(--green-ink); }
.chip--invalid  { background: var(--red-soft);   color: var(--red-ink); }
.chip--catchall { background: var(--amber-soft); color: var(--amber-ink); }
.chip--risky    { background: var(--amber-soft); color: var(--amber-ink); }
.chip--unknown  { background: var(--grey-soft);  color: var(--grey-ink); }
.chip--warn     { background: var(--amber-soft); color: var(--amber-ink); }
/* Quiet neutral, deliberately NOT a verdict colour: outlined, not filled. */
.chip--cache {
  background: transparent; color: var(--grey-ink);
  border-color: var(--line-strong); border-style: dashed;
}
.chip--cache::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--grey); flex: 0 0 auto;
}
/* work in progress, not a verdict */
.chip--checking { background: var(--panel); color: var(--ink-soft); border-color: var(--line-strong); }

/* The legacy `.pill` block lived here. Nothing served referenced it, and
   it painted `active` and `high` green -- a rule this design system does not
   have. Deleted rather than left as an invitation. */

/* ==================================================== shared: bar ======= */
.bar {
  display: flex; width: 100%; height: 20px; overflow: hidden;
  border: 1px solid var(--line); border-radius: 3px; background: var(--line-soft);
}
.bar-seg { display: block; height: 100%; min-width: 2px; }
.bar-seg--valid    { background: var(--green); }
.bar-seg--invalid  { background: var(--red); }
.bar-seg--catchall { background: var(--amber); }
.bar-seg--risky    { background: #B07C1E; }
.bar-seg--unknown  { background: #98A2AE; }
.bar-seg--cache    { background: var(--grey); }

.bar-legend {
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5);
  margin-top: var(--s3); font-size: 0.8125rem;
}
.bar-legend > * { display: inline-flex; align-items: baseline; gap: 6px; }
.bar-legend i {
  width: 9px; height: 9px; border-radius: 2px;
  display: inline-block; flex: 0 0 auto; align-self: center;
}
.bar-legend .num, .bar-legend strong { font-variant-numeric: tabular-nums; }

/* The legacy `.propbar` block lived here; the live verdict bar is `.bar`. */
.legend { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); margin-top: var(--s3); font-size: 0.8125rem; }
.legend i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; margin-right: 5px; }

/* ==================================================== shared: tables ==== */
table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
thead th {
  text-align: left; font-weight: 500; font-size: 0.75rem;
  color: var(--ink-soft); background: var(--panel);
  padding: var(--s2) var(--s3); white-space: nowrap;
  border-bottom: 1px solid var(--line);
}
tbody td {
  padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--line-soft);
  vertical-align: top;
}
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: #FAFBFC; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
td.mono, .mono { font-family: var(--mono); font-size: 0.8125rem; }

.datatable {
  width: 100%; border-collapse: collapse;
  background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r);
}
.datatable caption { caption-side: top; text-align: left; padding: 0 0 var(--s2); color: var(--ink-soft); font-size: 0.8125rem; }
.datatable thead th {
  background: var(--panel); color: var(--ink-soft);
  border-bottom: 1px solid var(--line);
}
.datatable td { overflow-wrap: anywhere; }
.datatable td.num, .datatable th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* ...but a figure must never break mid-digit: "100,000" was wrapping to
   "100,00 / 0" because break-anywhere also shrinks the column's min-content
   width. Numbers still wrap at spaces ("219 of 100,000"). */
.datatable td.num { overflow-wrap: normal; }

.tablewrap { overflow-x: auto; }
.expandable { cursor: pointer; }
.detail td { background: #FBFCFD; }
.detail dl { margin: 0; display: grid; grid-template-columns: 170px 1fr; gap: var(--s1) var(--s3); font-size: 0.8125rem; }
.detail dt { color: var(--ink-soft); }
.detail dd { margin: 0; font-family: var(--mono); word-break: break-all; }

/* =============================================== shared: activity ======= */
.activity { display: flex; flex-direction: column; }
.activity-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line-soft);
  min-height: var(--tap);
  animation: row-in 260ms ease-out both;
}
.activity-row:last-child { border-bottom: 0; }
/* Primed from the buffer when the page connected: real, but already over.
   No animation, because motion here means "this is happening now". */
.activity-row--replayed { animation: none; }
.act-state { flex: 0 0 auto; width: 14px; display: flex; justify-content: center; }
.state-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--grey); display: block; }
.state-dot--valid    { background: var(--green); }
.state-dot--invalid  { background: var(--red); }
.state-dot--catchall,
.state-dot--risky    { background: var(--amber); }
.state-dot--unknown  { background: var(--grey); }
.state-dot--cache    { background: transparent; border: 1px solid var(--grey); }
.act-addr {
  font-family: var(--mono); font-size: 0.8125rem;
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.act-mx {
  color: var(--ink-soft); font-size: 0.75rem; font-family: var(--mono);
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.act-dur { color: var(--ink-soft); font-size: 0.75rem; font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.act-chip { flex: 0 0 auto; margin-left: auto; }

@keyframes row-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* ==================================================== controls ========== */
button, .btn {
  font-family: var(--font); font-size: 0.875rem; font-weight: 500;
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s2);
  padding: var(--s2) var(--s4); min-height: 36px;
  border-radius: var(--r); border: 1px solid var(--line-strong);
  background: var(--panel); color: var(--ink); cursor: pointer;
  text-decoration: none;
}
button:hover, .btn:hover { background: #F2F4F6; text-decoration: none; }
button.primary, .btn.primary {
  background: var(--gold); border-color: var(--gold); color: #1C1500;
}
button.primary:hover, .btn.primary:hover { background: #B8931F; }
button.danger, .btn.danger { border-color: var(--red); color: var(--red-ink); }
button.danger:hover { background: var(--red-soft); }
button:disabled, .btn:disabled, button[aria-disabled="true"] {
  opacity: .5; cursor: not-allowed;
}

input[type=text], input[type=password], input[type=number], input[type=search],
input[type=email], select, textarea {
  font-family: var(--font); font-size: 0.875rem;
  padding: var(--s2) var(--s3); min-height: 36px;
  border: 1px solid var(--line-strong); border-radius: var(--r);
  background: var(--panel); color: var(--ink); width: 100%;
}
textarea { font-family: var(--mono); font-size: 0.8125rem; resize: vertical; }
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 0; border-color: var(--gold-dark);
}
label { display: block; font-size: 0.8125rem; color: var(--ink-soft); margin-bottom: var(--s1); }
.field { margin-bottom: var(--s4); }
.hint {
  font-size: 0.8125rem; color: var(--ink-soft); margin-top: var(--s1);
  border-left: 2px solid var(--gold); padding-left: var(--s2);
}
.row { display: flex; gap: var(--s3); align-items: flex-end; flex-wrap: wrap; }
.row > * { flex: 1; min-width: 140px; }
.row > .shrink { flex: 0 0 auto; min-width: 0; }
.toolbar { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; margin-bottom: var(--s4); }

/* ==================================================== notices =========== */
.notice {
  padding: var(--s3) var(--s4); border-radius: var(--r);
  font-size: 0.875rem; margin-bottom: var(--s4);
  border: 1px solid var(--line); border-left: 3px solid var(--grey);
  background: var(--panel); color: var(--ink);
}
.notice.warn  { background: #FDF7EE; border-color: var(--line); border-left-color: var(--amber); color: var(--amber-ink); }
.notice.error { background: var(--red-soft); border-color: var(--line); border-left-color: var(--red); color: var(--red-ink); }
.notice.ok    { background: var(--green-soft); border-color: var(--line); border-left-color: var(--green); color: var(--green-ink); }
.notice.info  { background: var(--panel); border-left-color: var(--ink-soft); color: var(--ink); }

.keybox {
  font-family: var(--mono); font-size: 0.875rem;
  background: var(--navy); color: #F0E4B8;
  padding: var(--s3) var(--s4); border-radius: var(--r);
  word-break: break-all; margin: var(--s2) 0;
}

/* ==================================================== chart / login ===== */
.chart { width: 100%; height: 150px; display: block; }
.chart .axis { stroke: var(--line); stroke-width: 1; }
.chart text { font-size: 10px; fill: var(--ink-soft); }

.loginwrap { max-width: 380px; margin: 9vh auto; }
.loginwrap .panel, .loginwrap .card { padding: var(--s5); }
.loginwrap h1 { text-align: center; margin-bottom: var(--s5); }

/* ==================================================== misc ============== */
.muted { color: var(--ink-soft); }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.num { font-variant-numeric: tabular-nums; }
.spinner {
  display: inline-block; width: 11px; height: 11px;
  border: 2px solid var(--line-strong); border-top-color: var(--gold-dark);
  border-radius: 50%; animation: spin 1.1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.scrollbox { max-height: 460px; overflow-y: auto; }

/* ==================================================== responsive ======== */
/* 1440 and up: the layout is already capped at 1440; only the gutters grow. */
@media (min-width: 1440px) {
  main { padding: var(--s5) var(--s6); }
  .topbar-main, nav.mainnav { padding-left: var(--s6); padding-right: var(--s6); }
}

/* below 1100: dense grids relax */
@media (max-width: 1100px) {
  .g3, .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .headerstrip { gap: var(--s3); }
}

/* below 768: single column, tables become cards, chrome stacks */
@media (max-width: 768px) {
  main { padding: var(--s4) var(--s3); }
  .g2, .g3, .g4 { grid-template-columns: 1fr; }
  .figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* the stacked header is tall; it scrolls away instead of eating the screen */
  header.topbar { position: static; }
  html { scroll-padding-top: 0; }
  .topbar-main { flex-wrap: wrap; gap: var(--s2) var(--s3); padding: var(--s2) var(--s3); }
  .brand { order: 1; }
  .topbar-right { order: 2; margin-left: auto; }
  .headerstrip { order: 3; flex: 1 1 100%; justify-content: flex-start; }
  .runctl { order: 4; flex: 1 1 100%; justify-content: flex-start; }
  .runctl .btn { flex: 0 1 auto; min-width: 96px; }
  nav.mainnav { padding: 0 var(--s3); }
  .navlink { flex: 1 1 auto; justify-content: center; padding: 0 var(--s2); }

  /* tables stack into cards — never a horizontal scroll */
  .datatable, .datatable tbody, .datatable tr, .datatable td {
    display: block; width: 100%;
  }
  .datatable { border: 0; background: transparent; }
  .datatable thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
  .datatable tr {
    background: var(--panel); border: 1px solid var(--line);
    border-radius: var(--r); margin-bottom: var(--s3); padding: var(--s1) 0;
  }
  .datatable tbody tr:hover { background: var(--panel); }
  .datatable td {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: var(--s4); text-align: left; padding: var(--s2) var(--s3);
    border-bottom: 1px solid var(--line-soft); min-height: 36px;
  }
  .datatable tr td:last-child { border-bottom: 0; }
  .datatable td[data-label]::before {
    content: attr(data-label);
    color: var(--ink-soft); font-size: 0.75rem; flex: 0 0 auto;
  }
  .datatable td.num { text-align: right; }

  .detail dl { grid-template-columns: 1fr; }
}

/* below 640: the activity row drops the MX host first; the address stays whole
   and wraps rather than being truncated — it is the one thing that must read. */
@media (max-width: 640px) {
  .act-mx { display: none; }
  .act-dur { display: none; }
  .act-addr { white-space: normal; overflow: visible; overflow-wrap: anywhere; }
}

/* 375 and below: nothing shrinks below legibility, it reflows */
@media (max-width: 420px) {
  .figures { grid-template-columns: 1fr; }
  .runctl .btn { flex: 1 1 auto; min-width: 0; }
  .figure-value { font-size: 1.5rem; }
  .brand-name { font-size: 0.875rem; }
  .headerstrip { gap: var(--s3); flex-wrap: wrap; }
  .activity-row { padding: var(--s3); gap: var(--s2); }
}

/* touch: every interactive target reaches 44px */
@media (pointer: coarse), (max-width: 768px) {
  button, .btn, .topbar .btn--ctl, .topbar .btn--quiet,
  input[type=text], input[type=password], input[type=number],
  input[type=search], input[type=email], select {
    min-height: var(--tap);
  }
  .navlink { min-height: var(--tap); }
  /* inline prose links reach the same 44px target. The negative block margin
     cancels the padding in the line box, so the paragraph rhythm and the
     visual weight of the link are unchanged — only the hit area grows. */
  .sub a {
    display: inline-block;
    padding-block: 0.75rem;
    margin-block: -0.75rem;
  }
}

/* ==================================================== motion ============ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .spinner { border-top-color: var(--gold-dark); opacity: .7; }
}
