/* Steward — minimal monitoring UI. Light/dark via tokens; dark follows the
   OS unless the toggle stamps data-theme on <html>. */
:root {
  /* Sticky offset for the sub-header. Measured from the navbar in JS because
     the navbar wraps to two rows on narrow screens. Nothing the navbar's own
     size depends on may read this, or the measurement feeds back into itself. */
  --navh: 53px;
  color-scheme: light;
  --page: #f9f9f7;
  --surface: #fcfcfb;
  --ink: #0b0b0b;
  --ink-2: #52514e;
  --muted: #898781;
  --grid: #e1e0d9;
  --axis: #c3c2b7;
  --ring: rgba(11, 11, 11, 0.1);
  --hover: rgba(11, 11, 11, 0.04);

  --s-blue: #2a78d6;
  --s-orange: #eb6834;
  --s-aqua: #1baf7a;
  --s-yellow: #eda100;
  --s-magenta: #e87ba4;
  --s-violet: #4a3aa7;
  --s-red: #e34948;

  --good: #0ca30c;
  --warning: #fab219;
  --serious: #ec835a;
  --critical: #d03b3b;
}
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme='light'])) {
    color-scheme: dark;
    --page: #0d0d0d;
    --surface: #1a1a19;
    --ink: #ffffff;
    --ink-2: #c3c2b7;
    --muted: #898781;
    --grid: #2c2c2a;
    --axis: #383835;
    --ring: rgba(255, 255, 255, 0.1);
    --hover: rgba(255, 255, 255, 0.05);
    --s-blue: #3987e5;
    --s-orange: #d95926;
    --s-aqua: #199e70;
    --s-yellow: #c98500;
    --s-magenta: #d55181;
    --s-violet: #9085e9;
    --s-red: #e34948;
  }
}
:root[data-theme='dark'] {
  color-scheme: dark;
  --page: #0d0d0d;
  --surface: #1a1a19;
  --ink: #ffffff;
  --ink-2: #c3c2b7;
  --muted: #898781;
  --grid: #2c2c2a;
  --axis: #383835;
  --ring: rgba(255, 255, 255, 0.1);
  --hover: rgba(255, 255, 255, 0.05);
  --s-blue: #3987e5;
  --s-orange: #d95926;
  --s-aqua: #199e70;
  --s-yellow: #c98500;
  --s-magenta: #d55181;
  --s-violet: #9085e9;
  --s-red: #e34948;
}

* {
  box-sizing: border-box;
  margin: 0;
}
html {
  height: 100%;
}
/* min-height, not height: a fixed-height body would cap the sticky navbar's
   containing block at one viewport, so it would scroll away after the fold */
body {
  min-height: 100%;
}
body {
  background: var(--page);
  color: var(--ink);
  font: 14px/1.45 system-ui, -apple-system, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
}
.wrap {
  max-width: 1240px;
  margin: 0 auto;
  padding: 16px 24px 48px;
}

/* ---------- navbar: identity and navigation ---------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 30; /* below the drawer scrim (40) */
  background: var(--surface);
  border-bottom: 1px solid var(--ring);
}
.nav-inner {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 24px;
  height: 52px; /* literal on purpose — see --navh note below */
  display: flex;
  align-items: center;
  gap: 24px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 15.5px;
  font-weight: 650;
  letter-spacing: -0.01em;
  flex: none;
}
.brand .mark {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  background: var(--s-blue);
}

.nav-links {
  display: flex;
  align-items: stretch;
  gap: 20px;
  height: 100%;
}
.nav-links button {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13.5px;
  color: var(--ink-2);
  padding: 0 1px;
  cursor: pointer;
  position: relative;
}
.nav-links button:hover {
  color: var(--ink);
}
.nav-links button[aria-current='page'] {
  color: var(--ink);
  font-weight: 600;
}
/* the active marker sits on the navbar's own border */
.nav-links button[aria-current='page']::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--s-blue);
  border-radius: 1px 1px 0 0;
}

.nav-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 12px;
}
.hostchip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--ink-2);
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hostchip i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--good);
  flex: none;
}
.hostchip.down i {
  background: var(--critical);
}


/* ---------- sub-header: filters and refresh controls ---------- */
.subhead {
  --ctl-h: 30px;
  --ctl-r: 8px;
  --ctl-fs: 12.5px;
  position: sticky;
  top: var(--navh);
  z-index: 25; /* under the navbar (30), under the drawer scrim (40) */
  background: var(--page);
  border-bottom: 1px solid var(--ring);
}
/* One row, always. When the controls do not fit they scroll sideways rather
   than stacking, so the bar keeps a predictable height and the sticky offset
   below it stays correct. */
.subhead-inner {
  max-width: 1240px;
  margin: 0 auto;
  padding: 8px 24px;
  min-height: 46px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: nowrap;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.subhead-inner::-webkit-scrollbar {
  display: none;
}
.subhead-inner > * {
  flex: none;
}
.filters,
.fgroup {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}
/* views without filters must not leave the row's leading gap behind */
.filters:not(:has(.fgroup:not([hidden]))) {
  display: none;
}
.subhead-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 7px;
  flex: none;
}
/* One control family: every select, input, segmented group and icon button in
   the sub-header shares a height, radius, border and type size, so the row
   reads as a single set of controls rather than four different widgets. */
.subhead select,
.subhead input,
.subhead .seg,
.subhead .iconbtn {
  height: var(--ctl-h);
  box-sizing: border-box;
  border: 1px solid var(--ring);
  border-radius: var(--ctl-r);
  background-color: var(--surface);
  font: inherit;
  font-size: var(--ctl-fs);
  color: var(--ink);
}
.subhead select,
.subhead input {
  appearance: none;
  padding: 0 9px;
  cursor: pointer;
  outline-offset: 2px;
  max-width: 170px;
  text-overflow: ellipsis;
}
/* the native arrow goes with appearance:none, so draw one. --muted is the same
   hex in both themes, so a single inline SVG serves light and dark. */
.subhead select {
  padding-right: 25px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23898781' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
}
.subhead input {
  cursor: text;
  width: 170px;
}
.subhead select:hover,
.subhead input:hover,
.subhead .iconbtn:hover {
  background-color: var(--hover);
}
.subhead .seg {
  padding: 2px;
  display: inline-flex;
  align-items: stretch;
}
.subhead .seg button {
  display: inline-flex;
  align-items: center;
  padding: 0 10px;
  font-size: var(--ctl-fs);
  border-radius: calc(var(--ctl-r) - 3px);
}
.subhead .iconbtn {
  width: var(--ctl-h);
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-2);
}
/* The sub-header carries no text, so freshness is signalled on the refresh
   button itself: amber when the data has gone stale, red when the last fetch
   failed. Both also say so in the tooltip. */
.subhead .iconbtn.stale {
  color: var(--serious);
  border-color: var(--serious);
}
.subhead .iconbtn.failed {
  color: var(--critical);
  border-color: var(--critical);
}
.refreshnow svg {
  display: block;
}
.refreshnow.spin svg {
  animation: spin 0.5s linear;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .refreshnow.spin svg {
    animation: none;
  }
}

/* ---------- mobile menu ---------- */
.menubtn {
  display: none; /* desktop shows the inline nav instead */
  appearance: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: none;
  border: 1px solid var(--ring);
  border-radius: 8px;
  background: var(--surface);
  cursor: pointer;
  padding: 0;
}
.menubtn:hover {
  background: var(--hover);
}
/* three bars drawn from one element so there is no icon font to load */
.menubtn .bars,
.menubtn .bars::before,
.menubtn .bars::after {
  display: block;
  width: 15px;
  height: 1.5px;
  border-radius: 1px;
  background: var(--ink-2);
}
.menubtn .bars {
  position: relative;
}
.menubtn .bars::before,
.menubtn .bars::after {
  content: '';
  position: absolute;
  left: 0;
}
.menubtn .bars::before {
  top: -5px;
}
.menubtn .bars::after {
  top: 5px;
}
.menubtn[aria-expanded='true'] {
  background: var(--hover);
}

.mobilemenu {
  position: absolute; /* overlays the page rather than resizing the navbar */
  top: 100%;
  left: 0;
  right: 0;
  z-index: 31;
  background: var(--surface);
  border-bottom: 1px solid var(--ring);
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.12);
  padding: 6px;
  display: flex;
  flex-direction: column;
}
.mobilemenu[hidden] {
  display: none;
}
.mobilemenu button {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  font-size: 14.5px;
  color: var(--ink-2);
  text-align: left;
  padding: 11px 14px;
  border-radius: 8px;
  cursor: pointer;
}
.mobilemenu button:hover {
  background: var(--hover);
}
.mobilemenu button[aria-current='page'] {
  color: var(--ink);
  font-weight: 600;
  background: var(--hover);
}

/* Below this the inline nav no longer fits beside the controls, so it becomes
   a menu and the bar stays a single row. */
@media (max-width: 760px) {
  .nav-links {
    display: none;
  }
  .menubtn {
    display: inline-flex;
  }
  .nav-inner {
    gap: 12px;
  }
  .subhead {
    --ctl-h: 32px; /* touch target */
  }
  /* everything runs left-to-right from the start edge instead of splitting */
  .subhead-right {
    margin-left: 0;
  }
  .subhead select {
    max-width: 140px;
  }
  .subhead input {
    width: 140px;
  }
  .subhead-inner {
    gap: 7px;
    padding: 8px 16px;
  }
}
/* phone widths: trade some of the selects' text for one fewer swipe */
@media (max-width: 430px) {
  .subhead select {
    max-width: 124px;
  }
  .subhead input {
    width: 124px;
  }
}
@media (max-width: 640px) {
  .hostchip {
    max-width: 120px;
  }
  .subhead-inner,
  .wrap {
    padding-left: 16px;
    padding-right: 16px;
  }
  .wrap {
    padding-bottom: 40px;
  }
}

.seg {
  display: inline-flex;
  background: var(--surface);
  border: 1px solid var(--ring);
  border-radius: 8px;
  padding: 2px;
}
.seg button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 12.5px;
  padding: 4px 11px;
  border-radius: 6px;
  cursor: pointer;
}
.seg button:hover {
  background: var(--hover);
}
.seg button[aria-pressed='true'] {
  background: var(--hover);
  color: var(--ink);
  font-weight: 600;
}
.iconbtn {
  appearance: none;
  border: 1px solid var(--ring);
  background: var(--surface);
  color: var(--ink-2);
  border-radius: 8px;
  width: 30px;
  height: 30px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}
.iconbtn:hover {
  background: var(--hover);
}
/* icon buttons centre their glyph, drawn or otherwise */
.iconbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.iconbtn svg {
  display: block;
}

/* ---------- cards & sections ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--ring);
  border-radius: 10px;
  padding: 14px 16px;
  min-width: 0;
}
.card h2 {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-2);
  letter-spacing: 0.01em;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.legend {
  display: flex;
  gap: 12px;
  margin-left: auto;
  font-weight: 400;
  color: var(--ink-2);
  font-size: 12px;
  flex-wrap: wrap;
}
.legend .key {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.legend .key i {
  width: 12px;
  height: 2px;
  border-radius: 1px;
  display: inline-block;
}

/* ---------- stat tiles ---------- */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}
.tile .label {
  font-size: 12px;
  color: var(--ink-2);
}
.tile .value {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-top: 2px;
}
.tile .sub {
  font-size: 12px;
  color: var(--muted);
  margin-top: 1px;
}
.tile .value .unit {
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-2);
  margin-left: 1px;
}
.tile.alert .value {
  color: var(--critical);
}

/* ---------- charts ---------- */
.grid2 {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: 12px;
  margin-bottom: 12px;
}
.grid3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 12px;
  margin-bottom: 12px;
}
@media (max-width: 900px) {
  .grid2,
  .grid3 {
    grid-template-columns: 1fr;
  }
}
.chart {
  position: relative;
  min-height: 150px;
}
.chart svg {
  display: block;
  width: 100%;
}
.chart .axis-text {
  font-size: 11px;
  fill: var(--muted);
  font-variant-numeric: tabular-nums;
}
.chart .end-label {
  font-size: 11px;
  fill: var(--ink-2);
  font-weight: 600;
}
.chart .empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 12.5px;
}
.tooltip {
  position: absolute;
  pointer-events: none;
  background: var(--surface);
  border: 1px solid var(--ring);
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
  padding: 8px 10px;
  font-size: 12px;
  min-width: 130px;
  z-index: 10;
  display: none;
}
.tooltip .tt-time {
  color: var(--muted);
  margin-bottom: 5px;
  font-variant-numeric: tabular-nums;
}
.tooltip .tt-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 1px 0;
}
.tooltip .tt-row i {
  width: 10px;
  height: 2px;
  border-radius: 1px;
  flex: none;
}
.tooltip .tt-row .tt-val {
  font-weight: 600;
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}
.tooltip .tt-row .tt-name {
  color: var(--ink-2);
}
.refreshing .chart {
  opacity: 0.55;
  transition: opacity 0.15s;
}

/* ---------- containers table ---------- */
.tablewrap {
  overflow-x: auto;
}
/* Fixed layout is what keeps the columns still. With `auto`, the browser
   re-measures every cell on each render and a value going from "996 MB" to
   "1.1 GB" shifts the whole table sideways once a second. Widths are declared
   per column instead; anything too long is ellipsised, and the table scrolls
   horizontally inside .tablewrap when the viewport is narrower than its
   min-width. */
table.containers {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  min-width: 940px;
  table-layout: fixed;
}
table.containers td {
  overflow: hidden;
  text-overflow: ellipsis;
}
table.containers .k-state {
  width: 200px;
}
table.containers .k-cpu {
  width: 72px;
}
table.containers .k-trend {
  width: 112px;
}
table.containers .k-mem {
  width: 96px;
}
table.containers .k-req {
  width: 96px;
}
table.containers .k-5xx {
  width: 72px;
}
table.containers .k-err {
  width: 84px;
}
table.containers th {
  text-align: left;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted);
  padding: 6px 10px;
  border-bottom: 1px solid var(--grid);
  white-space: nowrap;
}
table.containers td {
  padding: 7px 10px;
  border-bottom: 1px solid var(--grid);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
table.containers tr:last-child td {
  border-bottom: 0;
}
table.containers tbody tr {
  cursor: pointer;
}
table.containers tbody tr:hover {
  background: var(--hover);
}
table.containers .num {
  text-align: right;
}
table.containers th.num {
  text-align: right;
}
.cname {
  font-weight: 600;
}
.cname,
.cimage {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cimage {
  color: var(--muted);
  font-size: 12px;
}
.state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-2);
}
.state i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: none;
}
.state.running i {
  background: var(--good);
}
.state.exited i,
.state.dead i {
  background: var(--critical);
}
.state.restarting i,
.state.paused i {
  background: var(--warning);
}
.bad {
  color: var(--critical);
  font-weight: 600;
}
.warnnum {
  color: var(--serious);
  font-weight: 600;
}
.zero {
  color: var(--muted);
}

/* ---------- feeds ---------- */
.feeds {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: 12px;
  margin-top: 12px;
}
@media (max-width: 900px) {
  .feeds {
    grid-template-columns: 1fr;
  }
}
.feed {
  list-style: none;
  padding: 0;
  max-height: 320px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.feed li {
  display: flex;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--grid);
  font-size: 12.5px;
  align-items: baseline;
}
.feed li:last-child {
  border-bottom: 0;
}
.feed time {
  color: var(--muted);
  flex: none;
  font-variant-numeric: tabular-nums;
}
.feed .who {
  color: var(--ink-2);
  font-weight: 600;
  flex: none;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.feed .line {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  color: var(--ink-2);
  overflow-wrap: anywhere;
}
.badge {
  flex: none;
  font-size: 10.5px;
  font-weight: 600;
  border-radius: 5px;
  padding: 1px 6px;
  border: 1px solid var(--ring);
  color: var(--ink-2);
}
.badge.http5xx {
  color: var(--s-red);
  border-color: currentColor;
}
.badge.exception {
  color: var(--s-orange);
  border-color: currentColor;
}
.badge.database {
  color: var(--s-aqua);
  border-color: currentColor;
}
.badge.timeout {
  color: var(--s-yellow);
  border-color: currentColor;
}
.badge.connection {
  color: var(--s-magenta);
  border-color: currentColor;
}
.badge.alert {
  color: var(--critical);
  border-color: currentColor;
}
.badge.recovery {
  color: var(--good);
  border-color: currentColor;
}

/* ---------- system (htop) view ---------- */
.grid-sys {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 0.9fr);
  gap: 12px;
  margin-bottom: 12px;
  align-items: stretch; /* every card matches the tallest one in the row */
}
/* Cards become columns so their content can spread into the shared height
   instead of leaving a block of dead space at the bottom. */
.grid-sys > .card {
  display: flex;
  flex-direction: column;
}
@media (max-width: 1100px) {
  .grid-sys {
    grid-template-columns: 1fr 1fr;
  }
}
@media (max-width: 700px) {
  .grid-sys {
    grid-template-columns: 1fr;
  }
}

/* per-core CPU meters */
.cores {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 5px 16px;
  flex: 1;
  align-content: space-between; /* rows breathe into the extra height */
}
.meter {
  display: grid;
  grid-template-columns: 26px 1fr 46px;
  align-items: center;
  gap: 8px;
  font-size: 12px;
}
.meter .m-label {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.meter .m-track {
  display: flex;
  height: 12px;
  border-radius: 3px;
  background: var(--grid);
  overflow: hidden;
}
.meter .m-seg {
  height: 100%;
  transition: width 0.18s linear;
}
.meter .m-seg + .m-seg {
  border-left: 2px solid var(--surface); /* the 2px surface gap between fills */
}
.meter .m-val {
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  font-weight: 600;
  text-align: right;
}
.meter.hot .m-val {
  color: var(--critical);
}

/* memory / swap meters are the same mark, one per row with a wide label */
#memmeters .meter {
  grid-template-columns: 44px 1fr auto;
  margin-bottom: 8px;
  font-size: 12.5px;
}
#memmeters .meter .m-val {
  white-space: nowrap;
}
/* the numeric breakdown sits at the foot of the card, under the bars */
#memfacts {
  margin-top: auto;
  padding-top: 12px;
}
.kv.split {
  grid-template-columns: auto 1fr auto 1fr;
  column-gap: 10px;
}
@media (max-width: 1100px) {
  .kv.split {
    grid-template-columns: auto 1fr;
  }
}
#memmeters .meter .m-label {
  text-align: left;
  color: var(--ink-2);
}
#memmeters .meter .m-val {
  font-size: 12px;
}

/* key/value facts */
.kv {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 14px;
  font-size: 12.5px;
  margin: 0;
}
.kv dt {
  color: var(--muted);
}
.kv dd {
  margin: 0;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* process table */
table.procs {
  min-width: 1250px;
  font-size: 12.5px;
}
table.procs .c-pid {
  width: 78px;
}
table.procs .c-user {
  width: 88px;
}
table.procs .c-pri {
  width: 50px;
}
table.procs .c-ni {
  width: 46px;
}
table.procs .c-size {
  width: 82px;
}
table.procs .c-s {
  width: 34px;
}
table.procs .c-pct {
  width: 66px;
}
table.procs .c-time {
  width: 92px;
}
table.procs .c-ctr {
  width: 152px;
}
/* COMMAND is the only elastic column — it absorbs whatever is left over */
table.procs .c-cmd {
  width: auto;
}
table.procs td {
  padding: 4px 8px;
}
table.procs th {
  padding: 5px 8px;
}
/* sortable headers — applies to both the containers and process tables */
table.containers th[data-sort] {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
table.containers th[data-sort]:hover {
  color: var(--ink-2);
}
table.containers th[data-sort]:focus-visible {
  outline: 2px solid var(--s-blue);
  outline-offset: -2px;
  border-radius: 4px;
}
table.containers th[aria-sort] {
  color: var(--ink);
}
table.containers th[aria-sort='descending']::after {
  content: ' ↓';
  color: var(--muted);
}
table.containers th[aria-sort='ascending']::after {
  content: ' ↑';
  color: var(--muted);
}
table.procs tbody tr {
  cursor: default;
}
table.procs .cmd {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  color: var(--ink-2);
}
table.procs .pstate-R {
  color: var(--good);
  font-weight: 600;
}
table.procs .pstate-Z,
table.procs .pstate-D {
  color: var(--critical);
  font-weight: 600;
}
table.procs .ctag {
  font-size: 11.5px;
  color: var(--s-blue);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  display: inline-block;
  vertical-align: bottom;
}
.muted-count {
  color: var(--muted);
  font-weight: 400;
}

/* ---------- issues table & error detail ---------- */
.hint,
.muted-count {
  color: var(--muted);
  font-weight: 400;
  font-size: 12px;
}
.cardlink {
  margin-left: auto;
  font-size: 12px;
  font-weight: 500;
  color: var(--s-blue);
  text-decoration: none;
}
.cardlink:hover {
  text-decoration: underline;
}
.note {
  font-size: 12.5px;
  color: var(--ink-2);
  background: var(--page);
  border: 1px solid var(--ring);
  border-radius: 8px;
  padding: 8px 11px;
  margin-bottom: 10px;
}

table.issues {
  min-width: 900px;
}
table.issues .i-count {
  width: 78px;
}
table.issues .i-kind {
  width: 84px;
}
table.issues .i-ctr {
  width: 160px;
}
table.issues .i-when {
  width: 96px;
}
table.issues .i-title {
  width: auto;
}
table.reqtable .r-name {
  width: auto;
}
table.reqtable .r-num {
  width: 92px;
}
table.reqtable .r-rate {
  width: 96px;
}
.ellip {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nowrap {
  white-space: nowrap;
}
.count-pill {
  display: inline-block;
  min-width: 34px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: 12px;
  background: var(--hover);
  border-radius: 999px;
  padding: 1px 8px;
}
.issue-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
  overflow: hidden;
}
.issue-text {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.trace-tag {
  flex: none;
  font-size: 10px;
  color: var(--muted);
  border: 1px solid var(--ring);
  border-radius: 4px;
  padding: 0 5px;
}
.typebar.clickable {
  cursor: pointer;
  border-radius: 5px;
}
.typebar.clickable:hover {
  background: var(--hover);
}

/* error detail panel */
.dhead-sub {
  color: var(--muted);
  font-size: 12.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dmeta-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.issue-message {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--ring);
  border-radius: 8px;
  padding: 10px 12px;
  overflow-wrap: anywhere;
  margin-bottom: 12px;
}
.issue-stats {
  margin-bottom: 12px;
}
.trace-card h2 {
  align-items: center;
}
.copybtn {
  margin-left: auto;
  appearance: none;
  font: inherit;
  font-size: 11.5px;
  color: var(--ink-2);
  background: var(--page);
  border: 1px solid var(--ring);
  border-radius: 6px;
  padding: 2px 9px;
  cursor: pointer;
}
.copybtn:hover {
  background: var(--hover);
}
pre.trace {
  margin: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--ink-2);
  white-space: pre;
  overflow-x: auto;
  overscroll-behavior: contain;
  max-height: 420px;
  tab-size: 4;
}
.issue-list .issue-row,
.feed .issue-row {
  cursor: pointer;
}
.feed .issue-row:hover {
  background: var(--hover);
}
.issue-row .line {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- error-type breakdown bars ---------- */
.typebars {
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-height: 150px;
  justify-content: center;
  padding: 4px 0;
}
.typebar {
  display: grid;
  grid-template-columns: 110px 1fr 52px;
  align-items: center;
  gap: 10px;
  font-size: 12.5px;
}
.typebar .tb-label {
  color: var(--ink-2);
  display: flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
}
.typebar .tb-label i {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  flex: none;
}
.typebar .tb-track {
  height: 16px;
  display: flex;
  align-items: center;
}
.typebar .tb-fill {
  height: 16px;
  border-radius: 0 4px 4px 0;
  min-width: 3px;
}
.typebar .tb-val {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.typebars .emptyfeed {
  text-align: center;
}
.emptyfeed {
  color: var(--muted);
  font-size: 12.5px;
  padding: 12px 0;
}

/* ---------- container drawer ---------- */
/* The panel slides; the scrim fades. Both start in their closed state and are
   moved to `.open` one frame after `hidden` is removed, so the transition has
   a state to animate from. JS reads these durations off the computed style, so
   changing them here is enough. */
.scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.28);
  z-index: 40;
  overscroll-behavior: contain;
  touch-action: none; /* a touch drag on the scrim must not pan the page */
  opacity: 0;
  transition: opacity 240ms ease;
}
.scrim.open {
  opacity: 1;
}
.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(560px, 94vw);
  background: var(--page);
  border-left: 1px solid var(--ring);
  z-index: 50;
  overflow-y: auto;
  /* keep wheel/touch momentum inside the panel — never scroll the page behind */
  overscroll-behavior: contain;
  padding: 18px 20px 32px;
  transform: translateX(100%);
  /* decelerating curve — fast off the mark, settles softly */
  transition: transform 240ms cubic-bezier(0.32, 0.72, 0, 1);
}
.drawer.open {
  transform: translateX(0);
}
.drawer:focus {
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  .drawer,
  .scrim {
    transition-duration: 1ms;
  }
}
.drawer .dhead {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
}
.drawer .dhead h3 {
  font-size: 16px;
  font-weight: 650;
}
.drawer .dhead h3 {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* only the close button is pushed right; a Back button sits at the start */
.drawer .dhead > .iconbtn:last-child {
  margin-left: auto;
}
.drawer .dhead .backbtn {
  flex: none;
  gap: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-2);
}
.drawer .dhead .backbtn svg {
  display: block;
}
/* a panel covered by another is inert, so it takes no focus and no clicks */
.drawer[inert] {
  overflow: hidden;
}
.drawer .dmeta {
  color: var(--muted);
  font-size: 12.5px;
  margin-bottom: 14px;
  overflow-wrap: anywhere;
}
.drawer .card {
  margin-bottom: 12px;
}
[hidden] {
  display: none !important;
}

/* ---------- login ---------- */
.loginpage {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 24px;
}
.loginbox {
  width: 100%;
  max-width: 340px;
  background: var(--surface);
  border: 1px solid var(--ring);
  border-radius: 12px;
  padding: 28px 26px 22px;
}
.loginbox .brand {
  font-size: 17px;
  margin-bottom: 6px;
}
.loginhint {
  color: var(--ink-2);
  font-size: 13px;
  margin-bottom: 18px;
}
.loginbox form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.loginbox input {
  font: inherit;
  font-size: 14px;
  color: var(--ink);
  background: var(--page);
  border: 1px solid var(--ring);
  border-radius: 8px;
  padding: 10px 12px;
  outline-offset: 2px;
}
.loginbox button {
  appearance: none;
  border: 0;
  border-radius: 8px;
  background: var(--s-blue);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  padding: 10px 12px;
  cursor: pointer;
}
.loginbox button:hover {
  filter: brightness(1.06);
}
.loginbox button:disabled {
  opacity: 0.65;
  cursor: default;
}
.loginerr {
  color: var(--critical);
  font-size: 12.5px;
  margin: 0;
}
.loginnote {
  color: var(--muted);
  font-size: 12px;
  margin-top: 16px;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
