/* Status page styling. No framework, no build step, no external requests. */

:root {
  color-scheme: light dark;

  --bg: #f7f8fa;
  --surface: #ffffff;
  --surface-2: #f1f3f6;
  --border: #e2e5ea;
  --border-strong: #cdd2da;
  --text: #14181f;
  --text-muted: #5c6674;
  --text-faint: #8c95a3;

  --operational: #16a34a;
  --degraded: #d97706;
  --down: #dc2626;
  --maintenance: #2563eb;
  --unknown: #9aa2ae;

  --operational-soft: #dcfce7;
  --degraded-soft: #fef3c7;
  --down-soft: #fee2e2;
  --maintenance-soft: #dbeafe;
  --unknown-soft: #eef0f3;

  --radius: 10px;
  --radius-sm: 6px;
  --shadow: 0 1px 2px rgba(15, 23, 42, 0.05), 0 1px 3px rgba(15, 23, 42, 0.04);
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

/* Dark palette. Applied by the system scheme unless the viewer chose light,
   and always when the viewer chose dark (public/theme.js sets data-theme).
   The two selectors carry the same declarations so a token is never defined
   in only one of them. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0d1117;
    --surface: #161b22;
    --surface-2: #1c2230;
    --border: #262d38;
    --border-strong: #384252;
    --text: #e6edf3;
    --text-muted: #9aa5b1;
    --text-faint: #6e7681;

    --operational: #2ea043;
    --degraded: #d29922;
    --down: #f85149;
    --maintenance: #388bfd;
    --unknown: #6e7681;

    --operational-soft: #10281a;
    --degraded-soft: #2b2110;
    --down-soft: #2d1618;
    --maintenance-soft: #0f2038;
    --unknown-soft: #1c222c;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  }
}

:root[data-theme="dark"] {
    --bg: #0d1117;
    --surface: #161b22;
    --surface-2: #1c2230;
    --border: #262d38;
    --border-strong: #384252;
    --text: #e6edf3;
    --text-muted: #9aa5b1;
    --text-faint: #6e7681;

    --operational: #2ea043;
    --degraded: #d29922;
    --down: #f85149;
    --maintenance: #388bfd;
    --unknown: #6e7681;

    --operational-soft: #10281a;
    --degraded-soft: #2b2110;
    --down-soft: #2d1618;
    --maintenance-soft: #0f2038;
    --unknown-soft: #1c222c;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}

:root[data-theme="dark"] { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }

* {
  box-sizing: border-box;
}

html {
  background: var(--bg);
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
}

/* One measure for the whole page: the bands span the full viewport while
   their contents and the main column share the same centred, fluid width.
   Gutters scale with the screen instead of being a fixed number that is too
   tight on a phone and too loose on a monitor. */
:root {
  --content-width: 1080px;
  --gutter: clamp(1rem, 4vw, 2.5rem);
}

body.admin {
  --content-width: 1320px;
}

.wrap,
.band-inner {
  width: min(100% - var(--gutter) * 2, var(--content-width));
  margin-inline: auto;
}

.wrap {
  padding-block: clamp(20px, 4vw, 36px) clamp(32px, 6vw, 64px);
}

.band {
  background: var(--surface);
}

.band-top {
  border-bottom: 1px solid var(--border);
}

.band-bottom {
  border-top: 1px solid var(--border);
  background: transparent;
}

.band-inner {
  padding-block: clamp(14px, 2.5vw, 20px);
}

/* ------------------------------------------------------------------ header */

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  flex-wrap: wrap;
}

.site-header .brand {
  display: flex;
  align-items: center;
  gap: 18px;
  text-decoration: none;
  min-width: 0;
}

.site-header img {
  height: 32px;
  width: auto;
}

.site-header .brand-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.site-header .brand-title,
.site-header h1 {
  font-size: clamp(1rem, 2.4vw, 1.2rem);
  font-weight: 600;
  margin: 0;
  letter-spacing: -0.01em;
}

.site-header .subtitle {
  margin: 2px 0 0;
  color: var(--text-muted);
  font-size: 0.85rem;
  /* A long description must not crowd out the navigation. */
  max-width: 64ch;
}

.header-links {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.8rem;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Button groups: one pill, buttons separated by hairlines. An item is a
   link, a <details> summary or a <label> — all wear .btn and look the same. */
.btn-group {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface-2);
}

.btn-group > * + * {
  border-left: 1px solid var(--border-strong);
}

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 13px;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.8rem;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.btn:hover,
.theme-menu[open] > .btn {
  color: var(--text);
  text-decoration: none;
}

.btn:focus-visible,
.tz-picker:focus-within {
  outline: 2px solid var(--maintenance);
  outline-offset: -2px;
  border-radius: 999px;
}

.btn-label {
  font-weight: 500;
}

.btn .icon {
  display: inline-block;
  flex: none;
}

/* Time zone: the visible part is a button with a globe and the zone; the
   native select lies invisibly on top so a click opens the real list. */
.tz-picker {
  max-width: 15rem;
}

.tz-picker .btn-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

.tz-picker select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  font: inherit;
}

/* Logo: both variants are in the markup; show the one for the scheme. */
.brand .logo-dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand .logo-light { display: none; }
  :root:not([data-theme="light"]) .brand .logo-dark { display: inline; }
}
:root[data-theme="dark"] .brand .logo-light { display: none; }
:root[data-theme="dark"] .brand .logo-dark { display: inline; }

/* A card header's call to action ("Full history"): a small pill, visibly a
   control, set apart from the quiet window hint beside it. */
.card > header .hint {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}

.card > header .hint-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.card > header .hint-link:hover {
  border-color: var(--text-faint);
  color: var(--text);
  text-decoration: none;
}

.card > header .hint-link:focus-visible {
  outline: 2px solid var(--maintenance);
  outline-offset: 1px;
}

/* Colour theme: a group button that opens a small menu. The button shows
   the icon and the name of the theme in effect; the panel lists the three
   choices. */
.theme-menu {
  position: relative;
  display: inline-flex;
}

.theme-menu > summary::-webkit-details-marker {
  display: none;
}

/* Only the icon of the theme in effect is visible on the button. */
.theme-menu > summary .icon-dark,
.theme-menu > summary .icon-light { display: none; }
:root[data-theme="dark"] .theme-menu > summary .icon-auto,
:root[data-theme="light"] .theme-menu > summary .icon-auto { display: none; }
:root[data-theme="dark"] .theme-menu > summary .icon-dark { display: inline-block; }
:root[data-theme="light"] .theme-menu > summary .icon-light { display: inline-block; }

.theme-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 30;
  min-width: 9.5rem;
  padding: 4px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* A small caret on the panel pointing at the button it belongs to, the way a
   tooltip points at its target. Two layers: the border-coloured square
   underneath, the surface-coloured one a pixel lower on top, so the caret
   shows a hairline edge that meets the panel's own border. */
.theme-menu-panel::before,
.theme-menu-panel::after {
  content: '';
  position: absolute;
  right: 18px;
  width: 10px;
  height: 10px;
  transform: rotate(45deg);
}

.theme-menu-panel::before {
  top: -6px;
  background: var(--border);
}

.theme-menu-panel::after {
  top: -5px;
  background: var(--surface);
}

.theme-menu-panel button {
  position: relative;
  z-index: 1;
  appearance: none;
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.85rem;
  text-align: left;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
}

.theme-menu-panel button:hover {
  background: var(--surface-2);
  color: var(--text);
}

.theme-menu-panel button[aria-pressed="true"] {
  color: var(--text);
  background: var(--surface-2);
  font-weight: 600;
}

.theme-menu-panel button:focus-visible {
  outline: 2px solid var(--maintenance);
  outline-offset: -2px;
}

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

.banner {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow);
  margin-bottom: 24px;
}

.banner .dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  flex: none;
}

.banner h2 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
}

.banner .meta {
  margin: 0;
  font-size: 0.82rem;
  color: var(--text-muted);
}

.banner.operational {
  background: var(--operational-soft);
  border-color: color-mix(in srgb, var(--operational) 35%, transparent);
}
.banner.degraded {
  background: var(--degraded-soft);
  border-color: color-mix(in srgb, var(--degraded) 35%, transparent);
}
.banner.down {
  background: var(--down-soft);
  border-color: color-mix(in srgb, var(--down) 35%, transparent);
}
.banner.maintenance {
  background: var(--maintenance-soft);
  border-color: color-mix(in srgb, var(--maintenance) 35%, transparent);
}
.banner.unknown {
  background: var(--unknown-soft);
}

.dot.operational { background: var(--operational); }
.dot.degraded { background: var(--degraded); }
.dot.down { background: var(--down); }
.dot.maintenance { background: var(--maintenance); }
.dot.unknown { background: var(--unknown); }

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

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 20px;
  overflow: hidden;
}

.card > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

.card > header h3 {
  margin: 0;
  font-size: 0.92rem;
  font-weight: 600;
}

.card > header .hint {
  font-size: 0.78rem;
  color: var(--text-muted);
}

/* ----------------------------------------------------------------- sensors */

.sensor {
  padding: 16px 18px;
  border-bottom: 1px solid var(--border);
}

.sensor:last-child {
  border-bottom: none;
}

/* A row whose sensor is not operational is tinted — lightly: a few percent
   of the status colour behind it and a hairline of it on the left. Enough
   to find the affected line in a long list, not enough to shout. */
.sensor.is-down,
.sensor.is-degraded,
.sensor.is-maintenance,
.sensor.is-unknown {
  box-shadow: inset 3px 0 0 var(--row-accent);
  background: color-mix(in srgb, var(--row-accent) 7%, transparent);
}

.sensor.is-down { --row-accent: var(--down); }
.sensor.is-degraded { --row-accent: var(--degraded); }
.sensor.is-maintenance { --row-accent: var(--maintenance); }
.sensor.is-unknown { --row-accent: var(--unknown); }

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

.sensor-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 550;
  min-width: 0;
}

.sensor-name .description {
  font-weight: 400;
  color: var(--text-muted);
  font-size: 0.82rem;
}

.sensor-status {
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}

.sensor-status.operational { color: var(--operational); }
.sensor-status.degraded { color: var(--degraded); }
.sensor-status.down { color: var(--down); }
.sensor-status.maintenance { color: var(--maintenance); }
.sensor-status.unknown { color: var(--unknown); }

/* Uptime bar strip. Bars shrink on narrow screens instead of wrapping. */
.bars {
  display: flex;
  gap: 2px;
  height: 34px;
  align-items: stretch;
}

.bars .bar {
  flex: 1 1 0;
  min-width: 2px;
  border-radius: 2px;
  background: var(--unknown);
  opacity: 0.85;
  transition: opacity 0.12s ease;
}

.bars .bar:hover {
  opacity: 1;
}

.bar.operational { background: var(--operational); }
.bar.degraded { background: var(--degraded); }
.bar.down { background: var(--down); }
.bar.maintenance { background: var(--maintenance); }
.bar.unknown { background: var(--unknown); opacity: 0.35; }

.bars-legend {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-top: 6px;
  font-size: 0.75rem;
  color: var(--text-faint);
}

.bars-legend .uptime {
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.uptime-windows {
  display: flex;
  gap: 14px;
  font-size: 0.75rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

/* -------------------------------------------------------------- incidents */

.entry {
  padding: 16px 18px;
  border-bottom: 1px solid var(--border);
}

.entry:last-child {
  border-bottom: none;
}

.entry h4 {
  margin: 0 0 4px;
  font-size: 0.95rem;
  font-weight: 600;
}

.entry h4 a {
  text-decoration: none;
}

.entry h4 a:hover {
  text-decoration: underline;
}

/* Collapsible rows (history page). The summary is the row; a chevron on the
   right says it opens, and turns when it has. Native <details>, no script. */
.entry-collapsible {
  padding: 0;
}

.entry-collapsible > summary {
  list-style: none;
  cursor: pointer;
  padding: 16px 44px 16px 18px;
  position: relative;
}

.entry-collapsible > summary::-webkit-details-marker {
  display: none;
}

.entry-collapsible > summary::after {
  content: '';
  position: absolute;
  right: 20px;
  top: 22px;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg);
  transition: transform 0.15s ease;
}

.entry-collapsible[open] > summary::after {
  transform: rotate(-135deg);
  top: 26px;
}

.entry-collapsible > summary:hover {
  background: var(--surface-hover, rgba(127, 127, 127, 0.06));
}

.entry-collapsible > summary:focus-visible {
  outline: 2px solid var(--maintenance);
  outline-offset: -2px;
}

.entry-collapsible > .entry-body {
  padding: 0 18px 16px 18px;
}

.entry-collapsible > .entry-body > .timeline {
  margin-top: 4px;
}

/* "Open incident page" inside an unfolded row: the same pill as every other
   secondary control on the page. */
.entry-link {
  margin: 14px 0 0;
  font-size: 0.8rem;
}

.entry-link a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text-muted);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}

.entry-link a:hover {
  border-color: var(--text-faint);
  color: var(--text);
  text-decoration: none;
}

.entry-link a:focus-visible {
  outline: 2px solid var(--maintenance);
  outline-offset: 1px;
}

.entry .entry-meta {
  font-size: 0.78rem;
  color: var(--text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.badge {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  border: 1px solid transparent;
}

.badge.investigating, .badge.identified { background: var(--down-soft); color: var(--down); }
.badge.monitoring { background: var(--degraded-soft); color: var(--degraded); }
.badge.resolved, .badge.completed { background: var(--operational-soft); color: var(--operational); }
.badge.scheduled, .badge.in_progress { background: var(--maintenance-soft); color: var(--maintenance); }
.badge.cancelled { background: var(--unknown-soft); color: var(--text-muted); }
.badge.critical, .badge.major { background: var(--down-soft); color: var(--down); }
.badge.minor { background: var(--degraded-soft); color: var(--degraded); }
.badge.none { background: var(--unknown-soft); color: var(--text-muted); }
/* Facts without a colour of their own: dates, durations. */
.badge.neutral {
  background: var(--unknown-soft);
  color: var(--text-muted);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* Timeline of updates: a vertical line with one coloured marker per state.
   Oldest at the top, so it reads as the course of events. The marker colours
   are the solid variants of the badge palette, so a glance down the line
   shows red → amber → green without reading a word. */
.timeline {
  list-style: none;
  position: relative;
  margin: 14px 0 0;
  padding: 0 0 0 30px;
}

.timeline::before {
  content: '';
  position: absolute;
  left: 8px;
  top: 10px;
  bottom: 10px;
  width: 2px;
  border-radius: 2px;
  background: var(--border-strong);
}

.tl-item {
  position: relative;
  padding-bottom: 16px;
}

.tl-item:last-child {
  padding-bottom: 0;
}

.tl-dot {
  position: absolute;
  left: -27px;
  top: 4px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--unknown);
  box-shadow: 0 0 0 3px var(--surface);
}

.tl-item.investigating .tl-dot,
.tl-item.identified .tl-dot { background: var(--down); }
.tl-item.monitoring .tl-dot { background: var(--degraded); }
.tl-item.resolved .tl-dot,
.tl-item.completed .tl-dot { background: var(--operational); }
.tl-item.scheduled .tl-dot,
.tl-item.in_progress .tl-dot { background: var(--maintenance); }
.tl-item.cancelled .tl-dot { background: var(--unknown); }

/* The current state of something still open: the latest marker sends out a
   ring, sonar-style, so an unresolved incident is visibly alive. The ring is
   the marker's own colour, expanding and fading, twice a second is too
   nervous — one pulse every two seconds reads as "ongoing", not "alarm". */
.tl-item.tl-last:not(.resolved):not(.completed):not(.cancelled):not(.scheduled) .tl-dot {
  box-shadow: 0 0 0 3px var(--surface);
}

.tl-item.tl-last:not(.resolved):not(.completed):not(.cancelled):not(.scheduled) .tl-dot::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: inherit;
  opacity: 0.6;
  animation: tl-pulse 2s cubic-bezier(0.2, 0.6, 0.4, 1) infinite;
}

@keyframes tl-pulse {
  0% { transform: scale(1); opacity: 0.6; }
  70% { transform: scale(3); opacity: 0; }
  100% { transform: scale(3); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .tl-item.tl-last:not(.resolved):not(.completed):not(.cancelled):not(.scheduled) .tl-dot::after {
    animation: none;
    transform: scale(1.8);
    opacity: 0.25;
  }
}

.tl-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 4px;
  line-height: 1.6;
}

.tl-delta {
  font-variant-numeric: tabular-nums;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--unknown-soft);
  font-size: 0.7rem;
}

.tl-body {
  white-space: pre-wrap;
  font-size: 0.9rem;
}

.entry-duration {
  font-variant-numeric: tabular-nums;
}

/* Body text of a maintenance or incident: a readable measure, a little air
   above the badges, muted so the title stays the loudest thing. */
.entry-text {
  margin: 12px 0 0;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--text-muted);
}

/* The departments of a detail entry — description, affected, series,
   timeline — each set off by a hairline, with a small label where the
   content does not name itself. Inside a section the first block sits flush
   under the label. */
.entry-section {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.section-label {
  display: block;
  margin-bottom: 8px;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.entry-section > .entry-text,
.entry-section > .affected,
.entry-section > .entry-note,
.entry-section > .timeline {
  margin-top: 0;
}

.entry-section > .affected {
  display: block;
}

.entry-section > .affected > .affected-label {
  display: block;
  margin-bottom: 8px;
}

/* Affected components as chips with a small label in front. */
.affected {
  margin-top: 12px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
}

.affected-label {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.chips {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 10px 2px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.74rem;
  color: var(--text);
}

.chip-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-faint);
  flex: none;
}

.chip-dot.maintenance { background: var(--maintenance); }
.chip-dot.down { background: var(--down); }
.chip-dot.degraded { background: var(--degraded); }

/* A one-line note under the facts, e.g. the next date of a series. */
.entry-note {
  margin: 10px 0 0;
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* The plan next to what actually happened, in a synthesised timeline step. */
.tl-planned {
  color: var(--text-faint);
}

/* Badges with a tooltip are reachable by keyboard; the tooltip opens on focus. */
.badge[tabindex]:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

.empty {
  padding: 22px 18px;
  color: var(--text-muted);
  font-size: 0.88rem;
  text-align: center;
}

/* ------------------------------------------------------------------ footer */

/* Centred, two lines at most: the site's own footer text, then the metadata
   as "label value · label value". Labels are faint and values muted, so the
   line reads as one sentence rather than a row of numbers. */
.site-footer {
  font-size: 0.78rem;
  color: var(--text-faint);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
}

.site-footer a {
  color: var(--text-muted);
}

.site-footer p {
  margin: 0;
}

.footer-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 4px 0;
}

.footer-item {
  display: inline-flex;
  gap: 5px;
  align-items: baseline;
  white-space: nowrap;
}

/* The separator belongs to the item that follows, so a hidden clock takes
   its dot with it and nothing dangles. */
.footer-item + .footer-item::before {
  content: '\00b7';
  margin: 0 10px;
  color: var(--border-strong);
}

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

/* Tabular figures so the ticking seconds do not make the line jitter. */
.footer-clock {
  font-variant-numeric: tabular-nums;
}

.footer-clock-group[hidden] {
  display: none;
}

/* ------------------------------------------------------------------- admin */

/* The tab row scrolls sideways on a phone rather than wrapping into three
   ragged lines. */
.admin-nav {
  display: flex;
  gap: 2px;
  margin-top: 12px;
  margin-bottom: calc(-1 * clamp(14px, 2.5vw, 20px));
  overflow-x: auto;
  scrollbar-width: none;
}

.admin-nav::-webkit-scrollbar {
  display: none;
}

.admin-nav a {
  padding: 8px 14px;
  text-decoration: none;
  font-size: 0.88rem;
  color: var(--text-muted);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.admin-nav a.active {
  color: var(--text);
  border-bottom-color: var(--maintenance);
  font-weight: 550;
}

.admin-nav a:hover {
  color: var(--text);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}

th, td {
  text-align: left;
  padding: 9px 12px;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

th {
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  font-weight: 600;
  background: var(--surface-2);
}

tbody tr:last-child td {
  border-bottom: none;
}

.table-scroll {
  overflow-x: auto;
}

form.stack {
  display: grid;
  gap: 14px;
  padding: 18px;
}

.field {
  display: grid;
  gap: 5px;
}

.field label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-muted);
}

.field .help {
  font-size: 0.76rem;
  color: var(--text-faint);
}

input[type="text"],
input[type="url"],
input[type="password"],
input[type="number"],
input[type="datetime-local"],
select,
textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  font-size: 0.9rem;
}

textarea {
  min-height: 90px;
  resize: vertical;
}

select[multiple] {
  min-height: 120px;
}

input:focus, select:focus, textarea:focus {
  outline: 2px solid color-mix(in srgb, var(--maintenance) 55%, transparent);
  outline-offset: 1px;
  border-color: var(--maintenance);
}

.row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
}

.checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.88rem;
}

.checkbox input {
  width: 16px;
  height: 16px;
}

button, .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text);
  font-family: inherit;
  font-size: 0.86rem;
  font-weight: 550;
  cursor: pointer;
  text-decoration: none;
}

button:hover, .button:hover {
  border-color: var(--text-faint);
}

button.primary, .button.primary {
  background: var(--maintenance);
  border-color: var(--maintenance);
  color: #fff;
}

button.danger, .button.danger {
  background: transparent;
  border-color: color-mix(in srgb, var(--down) 45%, transparent);
  color: var(--down);
}

button.small, .button.small {
  padding: 4px 9px;
  font-size: 0.78rem;
}

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

.notice {
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  margin-bottom: 18px;
  font-size: 0.88rem;
  border: 1px solid transparent;
}

.notice.error {
  background: var(--down-soft);
  border-color: color-mix(in srgb, var(--down) 40%, transparent);
  color: var(--down);
}

.notice.success {
  background: var(--operational-soft);
  border-color: color-mix(in srgb, var(--operational) 40%, transparent);
  color: var(--operational);
}

.notice.info {
  background: var(--maintenance-soft);
  border-color: color-mix(in srgb, var(--maintenance) 40%, transparent);
  color: var(--maintenance);
}

/* inline-block, so the padded background counts towards the line box instead
   of spilling out of it. Baseline alignment then puts the chip's text on the
   same line as the plain text in the neighbouring cells — as an inline element
   its smaller font gave it a shorter line box and a visibly higher baseline. */
code, .mono {
  display: inline-block;
  vertical-align: baseline;
  font-family: var(--mono);
  font-size: 0.85em;
  line-height: 1.35;
  background: var(--surface-2);
  padding: 2px 6px;
  border-radius: 4px;
}

/* Identifiers stay on one line; the table scrolls instead of shredding them. */
td .mono, th .mono {
  white-space: nowrap;
}

.notice code {
  overflow-wrap: anywhere;
}

/* Inline row-editing forms need usable input widths inside table cells. */
td .actions input[type="text"],
td .actions input[type="password"] {
  min-width: 150px;
}

td .actions select {
  min-width: 110px;
}

.login-shell {
  max-width: 380px;
  margin: 12vh auto;
  padding: 0 20px;
}

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

.faint {
  color: var(--text-faint);
}

.nowrap {
  white-space: nowrap;
}

/* Below roughly a tablet the uptime figures are dropped from the strip legend
   and shown under the sensor name instead, where there is room for them. */
@media (max-width: 860px) {
  .uptime-windows {
    gap: 10px;
    font-size: 0.72rem;
  }
}

@media (max-width: 700px) {
  .sensor-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
  }

  .sensor-name {
    flex-wrap: wrap;
    gap: 2px 8px;
  }

  .uptime-windows {
    display: none;
  }

  /* Ninety bars squeezed into a phone would be a pixel each. Give them a
     usable width and let the strip scroll; bar-detail.js parks it at the
     right so the most recent days are what you see first. */
  .bars {
    height: 30px;
    overflow-x: auto;
    scrollbar-width: none;
    overscroll-behavior-x: contain;
  }

  .bars::-webkit-scrollbar {
    display: none;
  }

  .bars .bar {
    flex: 0 0 6px;
  }

  .bars-legend {
    font-size: 0.72rem;
  }
}

/* On a phone the logo alone is about half the width, so the brand stacks and
   the long description steps aside — it still reaches search engines through
   the meta tag, where it belongs anyway. */
@media (max-width: 640px) {
  .site-header .brand {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .site-header img {
    height: 28px;
  }

  .site-header .subtitle {
    display: none;
  }
}

@media (max-width: 520px) {
  .site-header .header-links {
    width: 100%;
    gap: 16px;
  }

  .banner {
    padding: 14px 16px;
  }

  .card > header,
  .sensor,
  .entry {
    padding-inline: 14px;
  }

  form.stack {
    padding: 14px;
  }
}

/* --------------------------------------------------------------- branding */

/* Preview tiles render each logo against the background it is meant for, so
   a white-on-transparent logo is visibly wrong in the light slot. */
.logo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 72px;
  padding: 10px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
}

.logo-preview img {
  max-height: 48px;
  max-width: 100%;
}

.logo-preview.light {
  background: #ffffff;
}

.logo-preview.dark {
  background: #0d1117;
}

input[type="file"] {
  font-family: inherit;
  font-size: 0.82rem;
  color: var(--text-muted);
  max-width: 100%;
}

/* --------------------------------------------------------------- tooltips */

/* Positioned by tooltip.js and attached to <body>, so the card's
   `overflow: hidden` cannot clip it. */
.tooltip strong {
  font-weight: 700;
}

.tooltip {
  position: fixed;
  z-index: 50;
  max-width: 280px;
  padding: 7px 10px;
  border-radius: var(--radius-sm);
  background: var(--text);
  color: var(--bg);
  font-size: 0.78rem;
  line-height: 1.45;
  white-space: pre-line;
  pointer-events: none;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
  animation: tooltip-in 0.09s ease-out;
}

.tooltip[hidden] {
  display: none;
}

.tooltip::after {
  content: "";
  position: absolute;
  left: 50%;
  margin-left: -5px;
  border: 5px solid transparent;
  border-top-color: var(--text);
  top: 100%;
}

.tooltip.below::after {
  top: auto;
  bottom: 100%;
  border-top-color: transparent;
  border-bottom-color: var(--text);
}

.tooltip strong {
  font-weight: 600;
}

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

@media (prefers-reduced-motion: reduce) {
  .tooltip { animation: none; }
}

/* The bars are the main tooltip target, so make them reachable by keyboard. */
.bars .bar:focus-visible {
  outline: 2px solid var(--maintenance);
  outline-offset: 1px;
  opacity: 1;
}

/* ----------------------------------------------------------- detail dialog */

.detail-dialog {
  width: min(680px, calc(100vw - 32px));
  max-height: min(86vh, 900px);
  padding: 22px 24px 26px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35);
  overflow: auto;
}

.detail-dialog::backdrop {
  background: rgba(10, 14, 20, 0.55);
  backdrop-filter: blur(2px);
}

.detail-close-form {
  float: right;
  margin: -6px -6px 0 0;
}

.detail-close {
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: 1.4rem;
  line-height: 1;
  padding: 4px 8px;
}

.detail-close:hover {
  color: var(--text);
}

.detail-title {
  margin: 0 0 4px;
  font-size: 1.05rem;
  font-weight: 600;
}

.detail-summary {
  margin: 0 0 18px;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.detail-chip {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
}

.detail-chip.down { background: var(--down-soft); color: var(--down); }
.detail-chip.degraded { background: var(--degraded-soft); color: var(--degraded); }
.detail-chip.maintenance { background: var(--maintenance-soft); color: var(--maintenance); }
.detail-chip.unknown { background: var(--unknown-soft); color: var(--text-muted); }

/* Segments are placed by their real start and duration, so a two-minute
   outage looks like two minutes instead of getting its own equal-width cell —
   and every segment lines up with the time grid drawn over it. */
.detail-strip {
  position: relative;
  height: 44px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface-2);
}

.detail-seg {
  position: absolute;
  top: 0;
  bottom: 0;
  min-width: 2px;
}

.detail-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.detail-tick {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: rgba(255, 255, 255, 0.28);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .detail-tick {
    background: rgba(0, 0, 0, 0.35);
  }
}

:root[data-theme="dark"] .detail-tick {
  background: rgba(0, 0, 0, 0.35);
}

.detail-seg.operational { background: var(--operational); }
.detail-seg.degraded { background: var(--degraded); }
.detail-seg.down { background: var(--down); }
.detail-seg.maintenance { background: var(--maintenance); }
.detail-seg.unknown { background: var(--unknown); opacity: 0.35; }

.detail-axis {
  position: relative;
  height: 18px;
  margin-top: 4px;
  font-size: 0.68rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.detail-axis span {
  position: absolute;
  transform: translateX(-50%);
}

.detail-axis span:first-child { transform: none; }
.detail-axis span:last-child { transform: translateX(-100%); }

.detail-heading {
  margin: 22px 0 8px;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  font-weight: 600;
}

.detail-list {
  margin: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 18px;
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

.detail-list dt {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.detail-list dd {
  margin: 0;
  color: var(--text-muted);
}

.detail-dot {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  flex: none;
}

.detail-dot.operational { background: var(--operational); }
.detail-dot.degraded { background: var(--degraded); }
.detail-dot.down { background: var(--down); }
.detail-dot.maintenance { background: var(--maintenance); }
.detail-dot.unknown { background: var(--unknown); }

.detail-related {
  display: grid;
  gap: 8px;
}

.detail-related-item {
  display: block;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  text-decoration: none;
  background: var(--surface-2);
}

.detail-related-item:hover {
  border-color: var(--border-strong);
}

.detail-related-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 550;
  font-size: 0.9rem;
}

.detail-related-meta {
  display: block;
  margin-top: 2px;
  font-size: 0.78rem;
  color: var(--text-muted);
}

.bars .bar {
  cursor: pointer;
}

@media (max-width: 620px) {
  .detail-list { grid-template-columns: 1fr; gap: 2px; }
  .detail-list dd { margin-bottom: 8px; }
}

/* Back links, public and admin: the same pill as the other controls. */
.back-link {
  margin: 0 0 16px;
  font-size: 0.8rem;
}

.back-link a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--surface-2);
  color: var(--text-muted);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}

.back-link a:hover {
  border-color: var(--text-faint);
  color: var(--text);
  text-decoration: none;
}

.back-link a:focus-visible {
  outline: 2px solid var(--maintenance);
  outline-offset: 1px;
}
