/*
 * status.gpt.nexus — design tokens and the [2a] overview.
 *
 * Values are the design handoff's, verbatim. Nothing here is rounded to a
 * "nicer" number and nothing is a system default standing in for a specified
 * value.
 *
 * Two rules that hold everywhere and are easy to break by habit:
 *   - RADIUS IS 0. The only curves on the page are glyph circles, the live dot,
 *     the progress ring and the radial glow — all of which are shapes, not
 *     surfaces. No card, button, chip, input or strip cell is ever rounded.
 *   - NO SHADOWS. Elevation is carried by `--card` against `--bg` and by
 *     hairline `--line` borders.
 */

/* ------------------------------------------------------------------ tokens */

/*
 * Light is the BASE and dark is an override, in both directions:
 *   [data-theme="dark"]                          -> explicit dark
 *   prefers-color-scheme:dark + [data-theme=system] -> follow the OS
 * The document ships with data-theme="system", so the OS is honoured with no
 * JavaScript at all and a stored override only has to change one attribute.
 */
:root {
  --bg: #f4f3f0;
  --fg: #111110;
  --mute: #6b6a66;
  --dim: rgba(17, 17, 16, 0.38);
  --faint: rgba(17, 17, 16, 0.06);
  --line: rgba(17, 17, 16, 0.13);
  --card: #fbfaf8;
  --acc: #f04e23;
  --grid: rgba(17, 17, 16, 0.055);
  --up: oklch(58% 0.14 152);
  --deg: oklch(66% 0.15 68);
  --down: oklch(55% 0.19 26);
  --upbg: oklch(58% 0.14 152 / 0.12);
  --degbg: oklch(66% 0.15 68 / 0.14);
  --downbg: oklch(55% 0.19 26 / 0.12);
  --hatch: repeating-linear-gradient(135deg, rgba(23, 23, 15, 0.14) 0 1px, transparent 1px 5px);
  color-scheme: light;
}

:root[data-theme="dark"] {
  --bg: #0f0f0e;
  --fg: #f1efe8;
  --mute: rgba(241, 239, 232, 0.6);
  --dim: rgba(241, 239, 232, 0.36);
  --faint: rgba(241, 239, 232, 0.07);
  --line: rgba(241, 239, 232, 0.14);
  --card: #161615;
  --acc: #ff6a3d;
  --grid: rgba(241, 239, 232, 0.045);
  --up: oklch(76% 0.15 152);
  --deg: oklch(80% 0.14 72);
  --down: oklch(70% 0.18 26);
  --upbg: oklch(76% 0.15 152 / 0.13);
  --degbg: oklch(80% 0.14 72 / 0.14);
  --downbg: oklch(70% 0.18 26 / 0.14);
  --hatch: repeating-linear-gradient(135deg, rgba(241, 239, 232, 0.16) 0 1px, transparent 1px 5px);
  color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
  :root[data-theme="system"] {
    --bg: #0f0f0e;
    --fg: #f1efe8;
    --mute: rgba(241, 239, 232, 0.6);
    --dim: rgba(241, 239, 232, 0.36);
    --faint: rgba(241, 239, 232, 0.07);
    --line: rgba(241, 239, 232, 0.14);
    --card: #161615;
    --acc: #ff6a3d;
    --grid: rgba(241, 239, 232, 0.045);
    --up: oklch(76% 0.15 152);
    --deg: oklch(80% 0.14 72);
    --down: oklch(70% 0.18 26);
    --upbg: oklch(76% 0.15 152 / 0.13);
    --degbg: oklch(80% 0.14 72 / 0.14);
    --downbg: oklch(70% 0.18 26 / 0.14);
    --hatch: repeating-linear-gradient(135deg, rgba(241, 239, 232, 0.16) 0 1px, transparent 1px 5px);
    color-scheme: dark;
  }
}

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

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  min-height: 100%;
}

body {
  margin: 0;
  color: var(--fg);
  background-color: var(--bg);
  /* 40px grid: two 1px gradients, drawn under everything. */
  background-image: linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 40px 40px;
  font-family: Inter, system-ui, sans-serif;
  font-size: 14px;
  letter-spacing: -0.005em;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
}

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

.mono {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
}

/* The mono uppercase label with the 6px orange square. */
.lbl {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--mute);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.lbl::before {
  content: "";
  width: 6px;
  height: 6px;
  background: var(--acc);
  flex: none;
}

.page {
  max-width: 1120px;
  margin: 0 auto;
  padding-bottom: 32px;
}

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

/* --------------------------------------------------------------- keyframes */

@keyframes nxIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes nxPulse {
  0% {
    box-shadow: 0 0 0 0 var(--up);
  }
  100% {
    box-shadow: 0 0 0 9px transparent;
  }
}
@keyframes nxBreathe {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}
@keyframes nxBlink {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

/* --------------------------------------------------------------- top bar */

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 36px;
  border-bottom: 1px solid var(--line);
}

.topbar__brand {
  display: flex;
  align-items: center;
  gap: 12px;
}

/*
 * Sized by HEIGHT with an automatic width: the mark's viewBox is 246x342, so a
 * 22x22 box would squash it. No filter — the paths are `currentColor`.
 */
.topbar__mark {
  height: 22px;
  width: auto;
  color: var(--fg);
  display: block;
}

.topbar__host {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 13px;
  color: var(--mute);
}

.topbar__meta {
  display: flex;
  align-items: center;
  gap: 20px;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 12px;
  color: var(--mute);
}

.topbar__group {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* The 390 top bar is the mark and a dot + age. No ring, no Subscribe, no host. */
.topbar__meta--mobile {
  display: none;
}

.live-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--up);
  flex: none;
  /* steps(1): a hard on/off, never a fade. It reads as a heartbeat, not a glow. */
  animation: nxBlink 2s steps(1) infinite;
}

/*
 * STALE: nothing on this page may read as a live signal.
 *
 * The reference's own [2d] top bar is a dashed, static, --mute dot reading
 * "not live · checked 47 min ago", with no ring and no countdown — because a
 * blinking green dot beside "this page stopped updating" is the exact false
 * green this product exists to detect. This is the honesty-critical half of
 * that screen, in the one component it belongs to; the rest of [2d] (dashed
 * card borders, hatched-forward strips, the banner's spinner and meta) is not
 * implemented here.
 */
.is-stale .live-dot {
  background: transparent;
  border: 1.5px dashed var(--mute);
  animation: none;
}

.is-stale #next-group {
  display: none;
}

.is-stale .word {
  color: var(--mute);
}

.subscribe {
  text-decoration: none;
  color: var(--bg);
  background: var(--fg);
  padding: 8px 14px;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* ---------------------------------------------------------------- glyphs */

/*
 * Shape carries state; hue is secondary. `--g` is the size for the context.
 * The `unknown` glyph never animates — every other glyph moving is what says
 * "this is a live reading", and we do not have one.
 */
.glyph {
  --g: 8px;
  width: var(--g);
  height: var(--g);
  flex: none;
  display: inline-block;
}

.glyph[data-state="up"] {
  border-radius: 50%;
  background: var(--up);
}
.glyph[data-state="degraded"] {
  background: var(--deg);
  transform: rotate(45deg);
}
.glyph[data-state="down"] {
  background: var(--down);
}
.glyph[data-state="unknown"] {
  border-radius: 50%;
  background: transparent;
  border: 1.5px dashed var(--mute);
}

/* ----------------------------------------------------------- verdict cards */

.verdicts {
  display: grid;
  grid-template-columns: 1.25fr 1fr;
  gap: 12px;
  padding: 24px 36px 0;
}

.card {
  background: var(--card);
  border: 1px solid var(--line);
}

.card--verdict {
  padding: 30px 32px 28px;
  position: relative;
  overflow: hidden;
}

.glow {
  position: absolute;
  inset: auto auto -60px -40px;
  width: 260px;
  height: 260px;
  border-radius: 50%;
  pointer-events: none;
}

.verdict {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: 22px;
  position: relative;
}

.verdict .glyph {
  --g: 16px;
}
.verdict .glyph[data-state="degraded"] {
  --g: 14px;
}
.verdict .glyph[data-state="up"] {
  animation: nxPulse 2.4s ease-out infinite;
}
.verdict .glyph[data-state="degraded"] {
  animation: nxBreathe 2.4s ease-in-out infinite;
}
.verdict .glyph[data-state="down"] {
  animation: nxBreathe 1.6s ease-in-out infinite;
}

.word {
  font: 800 56px/1 "Playfair Display", Georgia, serif;
  letter-spacing: -0.02em;
}

.sub {
  margin: 16px 0 0;
  font: italic 700 20px/1.3 "Playfair Display", Georgia, serif;
  color: var(--mute);
  max-width: 440px;
  position: relative;
}

.facts {
  display: flex;
  flex-wrap: wrap;
  gap: 26px;
  margin-top: 22px;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 12px;
  color: var(--mute);
  position: relative;
}

.facts b {
  font-weight: inherit;
  color: var(--fg);
}

.facts i {
  font-style: normal;
  color: var(--dim);
}

/* ----------------------------------------------------------------- chips */

.chips {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 20px;
}

.chip {
  border: 1px solid var(--line);
  background: transparent;
  color: var(--fg);
  font-family: inherit;
  font-size: 12.5px;
  text-align: start;
  padding: 0;
  transition: border-color 120ms ease-out;
}

.chip__head {
  display: grid;
  grid-template-columns: 8px 90px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 7px 10px;
  width: 100%;
  background: transparent;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.chip__glyph {
  --g: 7px;
}

.chip__short {
  font-weight: 500;
}

.chip__impact {
  color: var(--mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip__dur {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  color: var(--dim);
  font-size: 11px;
  white-space: nowrap;
}

.chip:hover,
.chip:focus-within {
  border-color: var(--fg);
}

.chip:hover .chip__dur,
.chip:focus-within .chip__dur {
  color: var(--fg);
}

.chip__caret::before {
  content: " →";
}

.chip[aria-expanded="true"] .chip__caret::before,
.chip.is-open .chip__caret::before {
  content: " ↑";
}

.chip:not(:hover):not(:focus-within):not(.is-open) .chip__caret::before {
  content: "";
}

/* 0fr -> 1fr is the only height transition that works on content-sized rows. */
.chip__body {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 160ms ease-out;
}

.chip.is-open {
  border-color: var(--fg);
}

.chip.is-open .chip__body {
  grid-template-rows: 1fr;
}

.chip__bodyinner {
  overflow: hidden;
}

.chip__facts {
  border-top: 1px solid var(--line);
  padding: 10px 10px 12px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 16px;
  font-size: 12px;
  color: var(--mute);
}

.chip__facts b {
  font-weight: inherit;
  color: var(--fg);
}

.chip__links {
  grid-column: 1 / -1;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: var(--fg);
}

.chip__links span {
  color: var(--mute);
}

/* ----------------------------------------------------------- group cards */

.groups {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  padding: 12px 36px 0;
}

.group {
  padding: 18px 20px 10px;
}

.group__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 10px;
}

.group__name {
  font: 800 16px/1.2 "Playfair Display", Georgia, serif;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.group__summary {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: var(--mute);
  flex: none;
  white-space: nowrap;
}

.row {
  display: grid;
  grid-template-columns: 14px 1fr 80px 52px;
  gap: 10px;
  align-items: center;
  padding: 8px 0;
  border-top: 1px solid var(--line);
  font-size: 13px;
  text-decoration: none;
  color: var(--fg);
  transition: background-color 120ms ease-out;
}

/*
 * The hover fill bleeds to the card edge without the row itself being
 * full-bleed, so the hairline border stays inset. Two spread shadows rather
 * than negative margins, which would drag the border with them.
 */
.row:hover {
  background: var(--faint);
  box-shadow: -20px 0 0 var(--faint), 20px 0 0 var(--faint);
}

.row:hover .row__name {
  text-decoration: underline;
  text-decoration-color: var(--acc);
  text-underline-offset: 3px;
}

.row:hover .row__value::after {
  content: " →";
}

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

.row__value {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11px;
  text-align: right;
  white-space: nowrap;
}

.strip {
  display: flex;
  gap: 1.5px;
  height: 10px;
}

.cell {
  flex: 1;
}

/*
 * Observed: THAT HOUR's state colour, set inline per cell — a strip is a sequence
 * of hours that each had their own state, not one colour stretched across a row.
 * Not-yet-observed: hatched, never blank and never a gap.
 */
.cell--observed {
  background: var(--faint);
}

.cell--unobserved {
  background-image: var(--hatch);
}

.ruler {
  display: flex;
  justify-content: space-between;
  padding: 10px 0 2px;
  border-top: 1px solid var(--line);
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 10px;
  color: var(--dim);
}

/* ---------------------------------------------------------------- legend */

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  padding: 22px 36px 0;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11.5px;
  color: var(--mute);
}

.legend__item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.legend__note {
  margin-left: auto;
  color: var(--dim);
}

/* ---------------------------------------------------------- stale banner */

/*
 * Partial [2d]: the banner and the verdict copy only. The rest of the stale
 * treatment — hollow verdicts, dashed card borders, strips frozen and hatched
 * forward — belongs to that screen and is deliberately not implemented here.
 */
.stale-banner {
  background: var(--acc);
  color: #111;
  padding: 14px 36px;
  font-size: 13.5px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}

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

.skeleton-block {
  background: var(--faint);
}

.skeleton-block--headline {
  animation: nxBreathe 1.6s ease-in-out infinite;
}

/* ------------------------------------------------------------- entrance */

/*
 * Applied only on the FIRST paint of real data. A refetch patches text in
 * place, so values swap with no animation — a card that re-animates every 60s
 * would read as new information arriving when nothing changed.
 */
.is-entering .card,
.is-entering .verdicts > *,
.is-entering .groups > * {
  animation: nxIn 0.7s cubic-bezier(0.2, 0.8, 0.2, 1) both;
  animation-delay: var(--enter-delay, 0ms);
}

.is-entering .groups > * {
  animation-duration: 0.6s;
}

/* ---------------------------------------------------------- mobile / 390 */

.mobile-only {
  display: none;
}

@media (max-width: 899px) {
  .verdicts {
    grid-template-columns: 1fr;
  }
  .groups {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 480px) {
  .desktop-only {
    display: none;
  }
  .mobile-only {
    display: block;
  }

  .page {
    padding: 0 16px 24px;
  }

  .topbar {
    padding: 18px 4px 12px;
    border-bottom: 0;
  }
  .topbar__mark {
    height: 20px;
    width: auto;
  }
  .topbar__meta {
    font-size: 11px;
    gap: 6px;
  }
  .live-dot {
    width: 5px;
    height: 5px;
  }

  .topbar__meta--mobile {
    display: inline-flex;
  }

  .verdicts {
    display: block;
    padding: 0;
  }
  /* Adjacent VISIBLE cards only — the hidden desktop pair is still in the DOM. */
  .mobile-only + .mobile-only {
    margin-top: 8px;
  }

  .card--verdict {
    padding: 22px 20px;
  }
  .lbl {
    font-size: 10.5px;
  }
  .verdict {
    gap: 12px;
    margin-top: 12px;
  }
  .verdict .glyph {
    --g: 12px;
  }
  .verdict .glyph[data-state="degraded"] {
    --g: 10px;
    /* The mobile mock's diamond is static. */
    animation: none;
  }
  .word {
    font-size: 36px;
  }
  .sub {
    margin-top: 10px;
    font-size: 15px;
  }

  .chips {
    gap: 5px;
    margin-top: 14px;
  }
  .chip {
    font-size: 12px;
  }
  .chip__head {
    grid-template-columns: 7px 1fr auto;
    padding: 6px 9px;
  }
  .chip__glyph {
    --g: 6px;
  }
  /* The impact clause has no room at 390 and is dropped, per the mockup. */
  .chip__impact {
    display: none;
  }
  .chip__dur {
    font-size: 10.5px;
  }

  .mobile-heading {
    display: flex;
    justify-content: space-between;
    padding: 20px 4px 8px;
    font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
    font-size: 11px;
    color: var(--mute);
  }

  .mobile-rows .row {
    grid-template-columns: 14px 1fr 72px 46px;
    padding: 9px 4px;
  }
  .mobile-rows .row:hover {
    box-shadow: none;
  }
  .mobile-rows .strip {
    height: 9px;
  }
  .mobile-rows .row__value {
    color: var(--mute);
  }

  .mobile-groups {
    margin-top: 14px;
  }
  .mobile-group {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 4px;
    border-top: 1px solid var(--line);
    font-size: 13px;
    text-decoration: none;
    color: var(--fg);
  }
  .mobile-group__dots {
    display: flex;
    gap: 6px;
    align-items: center;
  }
  .mobile-group__dots .glyph {
    --g: 7px;
  }

  .stale-banner {
    padding: 12px 16px;
    font-size: 12.5px;
    margin: 0 -16px;
  }
}

/* --------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ==========================================================================
 * [2b] target detail and [2i] group page
 *
 * Both share the overview's tokens, cards, glyphs and verdict typography; what
 * follows is only what those two screens add. Same two rules hold: radius 0
 * everywhere but the glyph shapes, and no shadows.
 * ======================================================================== */

/* ------------------------------------------------------- breadcrumb top bar */

/*
 * The detail top bar carries a breadcrumb where the overview carries the mark
 * and the countdown ring. The ring is deliberately absent rather than hidden:
 * this page's charts refresh on the bucket, not on the tick, so a countdown to
 * the next tick would be a promise about the wrong thing.
 */
.topbar--crumb {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 12.5px;
}

.crumb {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.crumb__back,
.crumb__up {
  text-decoration: none;
  color: var(--mute);
}

.crumb__back:hover,
.crumb__up:hover {
  color: var(--fg);
  text-decoration: underline;
  text-decoration-color: var(--acc);
  text-underline-offset: 3px;
}

.crumb__sep {
  color: var(--dim);
}

.crumb__here {
  color: var(--fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A single card fills the row rather than sitting at 1.25fr with a hole beside it. */
.verdicts--single {
  grid-template-columns: 1fr;
}

/* ------------------------------------------------------------ detail layout */

.detail-grid {
  display: grid;
  grid-template-columns: 1fr 340px;
  gap: 12px;
  padding: 12px 36px 0;
}

.card--content {
  padding: 22px 24px 18px;
}

.card--uptime {
  padding: 22px 24px 6px;
  /* The blocks are separated by their own rules; the last must not double up
     with the card's own bottom edge. */
  align-self: start;
}

/* A card heading and its mono meta, sharing one baseline. */
.sect {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
}

.sect + .sect,
.chart + .sect,
.ruler--chart + .sect,
.spark + .sect {
  margin-top: 28px;
}

.sect__title {
  font: 800 16px/1.2 "Playfair Display", Georgia, serif;
}

.sect__meta {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: var(--mute);
  text-align: right;
}

/* The verdict card's clause: `Root` + italic `of 7 checks` on one line. */
.verdict--dep {
  gap: 16px;
  flex-wrap: wrap;
}

.verdict__clause {
  font: italic 700 20px/1.2 "Playfair Display", Georgia, serif;
  color: var(--mute);
}

/*
 * A verdict glyph that must NOT animate.
 *
 * Every animating glyph on this site is saying "this is a live reading". The
 * Effect-on-Nexus card states a conclusion read off the declared dependency
 * graph, so its glyph is static in the design and static here.
 */
.verdict--static .glyph {
  animation: none !important;
}

/* 13px body prose — distinct from `.sub`, which is the Playfair italic. */
.prose {
  margin: 16px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--mute);
  position: relative;
}

.deps {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 16px;
}

.dep {
  display: flex;
  gap: 6px;
  align-items: center;
  font-size: 12px;
  border: 1px solid var(--line);
  padding: 4px 9px 4px 7px;
  text-decoration: none;
  color: var(--fg);
  transition: border-color 120ms ease-out;
}

.dep:hover {
  border-color: var(--fg);
}

.dep__glyph {
  --g: 6px;
}

/* --------------------------------------------------- 96-bucket chart + tips */

.chart {
  position: relative;
  margin-top: 14px;
}

.bars {
  display: flex;
  gap: 2px;
  align-items: flex-end;
}

.bar {
  flex: 1;
  min-width: 0;
  transform-origin: bottom;
}

/* Not-yet-observed is hatched at FULL height, never a gap and never a short bar:
   a short bar would read as a small measurement rather than as none. */
.bar--unobserved {
  background-image: var(--hatch);
}

.bar:hover {
  outline: 1px solid var(--fg);
}

.is-entering .bars.is-sweeping .bar {
  animation: nxSweep 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) both;
  animation-delay: var(--sweep-delay, 0ms);
}

@keyframes nxSweep {
  from {
    transform: scaleY(0);
  }
  to {
    transform: scaleY(1);
  }
}

/*
 * The bucket tooltip. Solid --fg on --bg so it is never mistaken for part of the
 * chart, and it appears after 80ms with no fade — a tooltip that animates in is
 * a tooltip you have to wait for twice.
 */
.tip {
  position: absolute;
  bottom: calc(100% + 9px);
  left: var(--tip-x, 50%);
  transform: translateX(-50%);
  background: var(--fg);
  color: var(--bg);
  padding: 7px 10px;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11px;
  line-height: 1.5;
  white-space: nowrap;
  pointer-events: none;
  z-index: 2;
  /* Clamped inside the card so an edge bucket cannot push it off. */
  max-width: 100%;
}

.tip__what {
  opacity: 0.7;
}

.tip__arrow {
  position: absolute;
  left: 50%;
  bottom: -5px;
  width: 10px;
  height: 10px;
  background: var(--fg);
  transform: translateX(-50%) rotate(45deg);
}

.ruler--chart {
  border-top: 0;
  padding: 6px 0 0;
}

/* ------------------------------------------------------- latency sparkline */

/*
 * The sparkline. The SVG stretches to the box; the type over it does not.
 */
.spark {
  margin-top: 12px;
  position: relative;
  line-height: 0;
}

.spark svg {
  display: block;
  overflow: visible;
}

.spark__label {
  position: absolute;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 10px;
  line-height: 1;
  color: var(--dim);
  pointer-events: none;
}

.spark__label--gap {
  left: 8px;
  top: 5px;
}

/* Just above the dashed midline, right-aligned — as the design places it. */
.spark__label--scale {
  right: 8px;
  top: 34px;
}

/* The r3 end dot, positioned as a fraction of the box so `none` cannot squash it. */
.spark__dot {
  position: absolute;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 -3px;
  border-radius: 50%;
  background: var(--acc);
  pointer-events: none;
}

.is-entering .spark__line--drawing {
  animation: nxDraw 1.6s 0.4s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}

@keyframes nxDraw {
  to {
    stroke-dashoffset: 0;
  }
}

/* ------------------------------------------------------------ incident rows */

.irow {
  display: grid;
  grid-template-columns: 12px 1fr 110px 130px 1fr;
  gap: 12px;
  align-items: center;
  padding: 12px 0 4px;
  margin-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  text-decoration: none;
  color: var(--fg);
  transition: background-color 120ms ease-out;
}

.irow + .irow {
  margin-top: 0;
}

.irow:hover {
  background: var(--faint);
  box-shadow: -12px 0 0 var(--faint), 12px 0 0 var(--faint);
}

.irow:hover .irow__title {
  text-decoration: underline;
  text-decoration-color: var(--acc);
  text-underline-offset: 3px;
}

.irow__title {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.irow__state {
  font-size: 12px;
  font-weight: 500;
}

.irow__meta {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11.5px;
  color: var(--mute);
}

.irow__when {
  font-size: 12px;
  color: var(--mute);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --------------------------------------------------------- uptime windows */

.uw {
  padding: 16px 0 14px;
  border-bottom: 1px solid var(--line);
}

.uw__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.uw__label {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 12px;
  color: var(--mute);
}

/* Silkscreen, and only here: the handoff reserves it for uptime percentages. */
.uw__pct {
  font: 400 26px/1 Silkscreen, "JetBrains Mono", ui-monospace, monospace;
}

/* "no data" is not a number and must not be set as one. */
.uw__nodata {
  font: italic 700 20px/1 "Playfair Display", Georgia, serif;
  color: var(--mute);
}

/*
 * The coverage bar. Hatched track = the window; solid fill = the fraction we
 * actually observed.
 *
 * IT IS A METER, NOT A TIMELINE. The fill is anchored left because a bar has to
 * start somewhere, and it says HOW MUCH was observed, never WHEN — which is why
 * the basis line under it is mandatory and states the tick counts in words.
 */
.uw__track {
  margin-top: 10px;
  height: 6px;
  background-image: var(--hatch);
  position: relative;
  overflow: hidden;
}

.uw__fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  background: var(--fg);
  transform-origin: left;
}

.is-entering .uw__fill.is-growing {
  animation: nxGrow 1s cubic-bezier(0.2, 0.8, 0.2, 1) both;
  animation-delay: var(--grow-delay, 0ms);
}

@keyframes nxGrow {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

.uw__basis {
  margin-top: 8px;
  font-size: 12px;
  color: var(--mute);
  line-height: 1.45;
}

/* ------------------------------------------------------- [2i] group table */

.table-wrap {
  padding: 12px 36px 0;
}

.card--table {
  padding: 18px 24px 6px;
}

.thead,
.trow {
  display: grid;
  grid-template-columns: 14px 190px 1fr 190px 80px 90px;
  gap: 14px;
  align-items: center;
}

.thead {
  padding: 0 0 10px;
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--dim);
  text-transform: uppercase;
}

.thead > span:nth-child(5),
.thead > span:nth-child(6) {
  text-align: right;
}

.trow {
  padding: 11px 0;
  border-top: 1px solid var(--line);
  font-size: 13.5px;
  text-decoration: none;
  color: var(--fg);
  transition: background-color 120ms ease-out;
}

.trow:hover {
  background: var(--faint);
  box-shadow: -12px 0 0 var(--faint), 12px 0 0 var(--faint);
}

.trow:hover .trow__name {
  text-decoration: underline;
  text-decoration-color: var(--acc);
  text-underline-offset: 3px;
}

.trow__name {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.trow__vendor,
.trow__latency {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  color: var(--mute);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.trow__vendor {
  font-size: 11px;
}

.trow__latency {
  font-size: 12px;
  text-align: right;
}

.trow__state {
  font-size: 12px;
  text-align: right;
  font-weight: 500;
  /* The glyph character is part of the label, so a wrap breaks `◆ degraded`
     across two lines with the shape stranded above the word. */
  white-space: nowrap;
}

.strip--24 {
  height: 14px;
}

/*
 * A row with NO strip at all — a link-only target, which has no probe and so has
 * no observation history, ever. The design's own words go in the column;
 * 24 hatched cells would claim we looked and saw nothing, which is a different
 * and false statement.
 */
.strip-none {
  font-family: "JetBrains Mono", ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: var(--dim);
  white-space: nowrap;
}

/* ------------------------------------------------- detail / group at ≤ 899 */

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

/*
 * The 390 layout.
 *
 * The handoff draws no mobile mockup for [2b] or [2i] — every mobile artboard is
 * an overview. So this is NOT a recreation of a drawn screen: it is the minimum
 * that keeps both screens readable and horizontally scroll-free at 390, using
 * the same reductions the overview's own 390 rules already establish (smaller
 * verdict word, tighter gutters, dropped columns that have no room). Flagged as
 * a gap rather than presented as the design's.
 */
@media (max-width: 480px) {
  .topbar--crumb {
    font-size: 11px;
    padding: 18px 4px 12px;
    gap: 10px;
  }

  .crumb {
    gap: 8px;
  }

  .detail-grid,
  .table-wrap {
    padding: 8px 0 0;
  }

  .card--content,
  .card--uptime,
  .card--table {
    padding: 18px 16px 12px;
  }

  .verdict__clause {
    font-size: 15px;
  }

  .sect__title {
    font-size: 15px;
  }

  .sect__meta {
    font-size: 10px;
  }

  /* Five columns of mono do not fit; the row keeps its title, state and when. */
  .irow {
    grid-template-columns: 10px 1fr auto;
    gap: 8px;
    row-gap: 2px;
  }
  .irow__meta {
    grid-column: 2 / -1;
  }
  .irow__when {
    grid-column: 2 / -1;
    white-space: normal;
  }

  /* The vendor host has no room at 390 and is dropped; the row still links. */
  .thead,
  .trow {
    /* `◆ degraded` is the widest state label and must not wrap; 78px holds it
       at 12px mono-adjacent type. */
    grid-template-columns: 12px 1fr 66px 78px;
    gap: 8px;
  }
  .thead > span:nth-child(4),
  .trow__vendor {
    display: none;
  }
  .thead > span:nth-child(3) {
    display: none;
  }
  .strip--24,
  .strip-none {
    display: none;
  }
  .thead > span:nth-child(5),
  .thead > span:nth-child(6) {
    text-align: right;
  }
}
