/* ============================================================
   status.polysimulator.com

   The PolySimulator "Meridian" (.psx) system, carried over from the
   marketing surface: dark ground, one true-emerald accent, Geist for
   text and Geist Mono for every figure, tabular numerals throughout.
   The system's hard rules hold here too — no gradient washes, no
   blinking dots, no decorative arrows.

   The one thing this page does that the marketing pages do not: the
   day strip is a MEASURING INSTRUMENT, not a row of tiles. A bar's
   HEIGHT is the share of the day we actually measured, and its
   segments are stacked by what those minutes contained. A day we
   watched all the way through and a day we half-watched cannot look
   the same, because they are not the same claim.
   ============================================================ */

:root {
  --bg: #080b12;
  --bg-deep: #04060b;
  --surface-1: #121927;
  --surface-2: #18212f;

  --line-1: rgba(255, 255, 255, 0.08);
  --line-2: rgba(255, 255, 255, 0.14);

  --text-1: #eef1f6;
  --text-2: #97a2b4;
  --text-3: #5e6b7e;

  --accent: #2dd6a0;
  --accent-dim: #1d8f6b;
  --accent-soft: rgba(45, 214, 160, 0.12);
  --accent-line: rgba(45, 214, 160, 0.36);

  --warn: #e3b75f;
  --warn-soft: rgba(227, 183, 95, 0.12);
  --warn-line: rgba(227, 183, 95, 0.36);

  --neg: #f4677b;
  --neg-soft: rgba(244, 103, 123, 0.12);
  --neg-line: rgba(244, 103, 123, 0.36);

  --unknown: rgba(255, 255, 255, 0.16);
  --unknown-soft: rgba(255, 255, 255, 0.05);

  /* Geist is the marketing surface's face. It is declared first and
     falls back cleanly: this page must never block on a font, and it
     serves no font files of its own so that it has no dependency to
     fail. Drop woff2 files into /fonts and add an @font-face block
     here to complete the identity. */
  --font-sans: 'Geist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, 'SF Mono', 'Cascadia Mono', 'Roboto Mono', monospace;

  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;

  --r-sm: 5px;
  --r-md: 9px;
  --r-lg: 13px;

  --strip-h: 30px;
  --page-w: 940px;
}

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

html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-1);
  background: var(--bg);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

h1,
h2 {
  margin: 0;
  font-weight: 600;
  letter-spacing: -0.02em;
}

a {
  color: var(--text-2);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}

a:hover {
  color: var(--text-1);
  border-bottom-color: var(--line-2);
}

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

.skip {
  position: absolute;
  left: -9999px;
}

.skip:focus {
  left: var(--sp-4);
  top: var(--sp-4);
  z-index: 10;
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--text-1);
}

.page {
  max-width: var(--page-w);
  margin: 0 auto;
  padding: var(--sp-6) var(--sp-5) var(--sp-7);
}

/* ============================================================ Masthead */

.masthead {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  padding-bottom: var(--sp-4);
  border-bottom: 1px solid var(--line-1);
}

.brand {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
  text-decoration: none;
  color: inherit;
}

.brand:hover .brand-name {
  color: var(--text-1);
}

/* The product mark itself, at text scale. It does not pulse or change
   colour with status: the platform's state is stated in words a few lines
   below, and a mark that also signalled state would be a second, quieter,
   less precise claim. */
.brand-mark {
  width: 15px;
  height: 22px;
  align-self: center;
  display: block;
  flex: none;
}

.brand-name {
  font-weight: 600;
  letter-spacing: -0.01em;
}

.brand-sep {
  color: var(--text-3);
}

.brand-page {
  font-size: 15px;
  font-weight: 500;
  color: var(--text-2);
}

.freshness {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 1px;
  font-size: 12px;
  color: var(--text-3);
  text-align: right;
}

.freshness-main {
  color: var(--text-2);
}

.freshness[data-stale='true'] .freshness-main {
  color: var(--warn);
}

.freshness-vantages {
  font-size: 11px;
  letter-spacing: 0.02em;
}

/* ============================================================ Banners */

.banner {
  margin-top: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--warn-line);
  border-left-width: 3px;
  border-radius: var(--r-sm);
  background: var(--warn-soft);
  font-size: 14px;
  color: var(--text-1);
}

.banner span {
  color: var(--text-2);
}

.banner-error {
  border-color: var(--neg-line);
  background: var(--neg-soft);
}

/* ============================================================ Verdict */

.verdict {
  padding: var(--sp-6) 0 var(--sp-5);
  border-bottom: 1px solid var(--line-1);
}

.verdict-line {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
}

.dot {
  flex: none;
  width: 10px;
  height: 10px;
  margin-top: 9px;
  border-radius: 50%;
  background: var(--unknown);
}

.dot[data-status='operational'] {
  background: var(--accent);
}
.dot[data-status='degraded'] {
  background: var(--warn);
}
.dot[data-status='outage'] {
  background: var(--neg);
}

.verdict-text {
  margin: 0;
  font-size: 24px;
  line-height: 1.25;
  font-weight: 600;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.method {
  margin: var(--sp-3) 0 0 22px;
  font-size: 13px;
  color: var(--text-3);
}

/* ============================================================ Components */

.components {
  padding-top: var(--sp-6);
}

.components-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.components-head h2 {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

.window-label {
  font-size: 12px;
  color: var(--text-3);
}

.rows {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line-1);
  border-radius: var(--r-lg);
  background: var(--surface-1);
  overflow: hidden;
}

.row {
  padding: var(--sp-4) var(--sp-5);
}

.row + .row {
  border-top: 1px solid var(--line-1);
}

.row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
}

.row-label {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.row-right {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
}

.latency {
  font-size: 12px;
  color: var(--text-3);
}

/* Restrained chips: a border and a tint, no glow, no fill that shouts. */
.chip {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--unknown-soft);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-2);
  white-space: nowrap;
}

.chip[data-status='operational'] {
  border-color: var(--accent-line);
  background: var(--accent-soft);
  color: var(--accent);
}
.chip[data-status='degraded'] {
  border-color: var(--warn-line);
  background: var(--warn-soft);
  color: var(--warn);
}
.chip[data-status='outage'] {
  border-color: var(--neg-line);
  background: var(--neg-soft);
  color: var(--neg);
}

.proves {
  margin: 2px 0 var(--sp-4);
  font-size: 13px;
  color: var(--text-3);
}

.strip-wrap {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-4);
}

/* ---- the instrument ---------------------------------------------------
   One slot per day, flush to a shared baseline. The bar inside a slot is
   as tall as the share of that day we measured, and is stacked bottom-up
   by what those minutes contained: failures first, then slow-but-served,
   then clean. A day nobody watched is an empty slot with only the
   baseline showing — which is a different statement from a day we
   watched and learned nothing, and it has to look different.
------------------------------------------------------------------------ */

.strip {
  flex: 1 1 auto;
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: var(--strip-h);
  min-width: 0;
  /* The baseline the bars stand on. It is what makes an empty slot read
     as "no bar here" rather than as a rendering failure. */
  border-bottom: 1px solid var(--line-1);
  padding-bottom: 2px;
}

.slot {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  border-radius: 1px;
  position: relative;
}

/* Where external monitoring began. Without this mark the empty run to its
   left reads as a broken chart instead of as "we were not watching yet". */
.slot[data-monitoring-start='true']::before {
  content: '';
  position: absolute;
  left: -2px;
  top: -2px;
  bottom: -3px;
  border-left: 1px solid var(--line-2);
}

.slot:hover .bar,
.slot:focus-visible .bar {
  filter: brightness(1.25);
}

/* Colour is the day's verdict; height is the share of the day we measured. */
.bar {
  width: 100%;
  border-radius: 1px;
  background: var(--unknown);
}

.bar[data-status='operational'] {
  background: var(--accent);
}
.bar[data-status='degraded'] {
  background: var(--warn);
}
.bar[data-status='outage'] {
  background: var(--neg);
}
.bar[data-status='no_data'] {
  background: var(--unknown);
}

.uptime {
  flex: none;
  text-align: right;
  min-width: 96px;
}

.uptime-figure {
  display: block;
  font-family: var(--font-mono);
  font-size: 14px;
  font-weight: 600;
  color: var(--text-1);
  line-height: 1.2;
}

.uptime-figure[data-null='true'] {
  color: var(--text-3);
  font-weight: 500;
}

.uptime-sub {
  display: block;
  font-size: 11px;
  color: var(--text-3);
}

/* ============================================================ Legend */

.legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-5);
  margin-top: var(--sp-4);
  font-size: 12px;
  color: var(--text-3);
}

.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.swatch {
  width: 9px;
  height: 9px;
  border-radius: 1px;
  background: var(--unknown);
}

.swatch[data-status='operational'] {
  background: var(--accent);
}
.swatch[data-status='degraded'] {
  background: var(--warn);
}
.swatch[data-status='outage'] {
  background: var(--neg);
}
.swatch[data-status='unmonitored'] {
  background: transparent;
  border-bottom: 1px solid var(--line-2);
  border-radius: 0;
  height: 9px;
}

.legend-note {
  margin-left: auto;
  color: var(--text-3);
}

/* ============================================================ Method */

.method-note {
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line-1);
}

.method-note h2 {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

.note-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--sp-3) var(--sp-6);
  margin-top: var(--sp-3);
}

.note-grid p {
  margin: 0;
  font-size: 14px;
  color: var(--text-2);
  text-wrap: pretty;
}

/* ============================================================ Foot */

.foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line-1);
  font-size: 12px;
  color: var(--text-3);
}

.foot-links {
  display: flex;
  gap: var(--sp-4);
}

/* ============================================================ Skeleton */

.sk {
  display: block;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.05);
}

.is-skeleton .sk {
  animation: sk-pulse 1.6s ease-in-out infinite;
}

/* Each placeholder occupies the exact box its real counterpart will, measured
   against a rendered row: label 23px, chip 21px, proves 20px, uptime block
   34px. The shimmer is painted into the CONTENT box and the rest is padding,
   so the placeholder can reserve full height without drawing a slab. Nothing
   moves when the data lands. */
.sk-label {
  width: 128px;
  height: 23px;
  padding: 4px 0;
  background-clip: content-box;
}
.sk-chip {
  width: 84px;
  height: 21px;
  border-radius: 999px;
}
.sk-proves {
  width: min(340px, 70%);
  height: 20px;
  padding: 4px 0;
  background-clip: content-box;
}
.sk-strip {
  flex: 1 1 auto;
  height: var(--strip-h);
}
.sk-figure {
  flex: none;
  width: 96px;
  height: 34px;
  padding: 9px 0;
  background-clip: content-box;
}

@keyframes sk-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}

/* ============================================================ Responsive */

@media (max-width: 640px) {
  .page {
    padding: var(--sp-5) var(--sp-4) var(--sp-6);
  }

  .masthead {
    align-items: flex-start;
  }

  .freshness {
    align-items: flex-start;
    text-align: left;
  }

  .verdict-text {
    font-size: 20px;
  }

  .row {
    padding: var(--sp-4);
  }

  /* Below this width a 90-slot strip cannot be read, so the script asks
     for fewer days and the window label says which. Stacking the figure
     under the strip keeps each slot wide enough to see. */
  .strip-wrap {
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-2);
  }

  .uptime {
    text-align: left;
    min-width: 0;
  }

  .legend-note {
    margin-left: 0;
    width: 100%;
  }
}

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


/* ============================================================ Methodology */
/* A definition list rather than paragraphs: someone opening a status page
   during an incident is scanning for one fact, not reading an essay. Each
   term is the question a reader actually arrives with. */

.method-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--sp-4) var(--sp-6);
  margin: var(--sp-4) 0 0;
}

.method-list > div {
  margin: 0;
}

.method-list dt {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-1);
}

.method-list dd {
  margin: 6px 0 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-2);
}

/* ============================================================ Support */

.support {
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line-1);
}

.support h2 {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

.support-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--sp-2) var(--sp-6);
  margin: var(--sp-4) 0 0;
  padding: 0;
  list-style: none;
}

.support-list li {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  font-size: 14px;
}

/* Fixed-width label column so the values line up into a readable second
   column instead of ragging against four different label lengths. */
.support-label {
  flex: none;
  width: 72px;
  font-size: 13px;
  color: var(--text-3);
}

.support-list a {
  color: var(--text-1);
  text-decoration: none;
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 1px;
}

.support-list a:hover {
  border-bottom-color: var(--accent-line);
}

.support-note {
  margin: var(--sp-4) 0 0;
  font-size: 13px;
  color: var(--text-3);
  max-width: 62ch;
}
