/* The board.
 *
 * The site's tokens, trimmed to the ones this page uses, so the status page and
 * thesubtitledb.org are the same object in the same colours rather than two
 * things that resemble each other. Both palettes are here for the same reason
 * the site carries both: the page follows the reader's system setting, and a
 * status page that is a white flash at three in the morning is a status page
 * read at three in the morning.
 *
 * Four state colours and they are used for one thing each, everywhere:
 *   ok    answering, inside its mark
 *   brass answering, over its mark. A delay, never an outage.
 *   bad   not answering, or answering wrongly
 *   line  no check was run. NOT a good day: the bars before this page existed
 *         are this colour, and so is a day the cron did not run. */

:root {
  --font: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --narrow: "Archivo Narrow", "Archivo", sans-serif;
  --mono: "Spline Sans Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --bg:          oklch(1 0 0);
  --surface:     oklch(0.976 0.004 240);
  --line:        oklch(0.905 0.008 240);
  --line-strong: oklch(0.845 0.012 240);

  --ink:         oklch(0.235 0.025 245);
  --ink-2:       oklch(0.425 0.022 245);
  --ink-3:       oklch(0.505 0.018 245);

  --chrome:      oklch(0.245 0.048 245);
  --chrome-ink:  oklch(0.985 0.004 245);
  --chrome-ink-2:oklch(0.780 0.020 245);
  --teal:        oklch(0.72 0.105 178);

  --brass:       oklch(0.585 0.115 66);
  --brass-ink:   var(--brass);
  --brass-wash:  oklch(0.955 0.036 76);
  --brass-line:  oklch(0.87 0.06 76);
  --ok:          oklch(0.525 0.115 152);
  --ok-ink:      var(--ok);
  --ok-wash:     oklch(0.955 0.03 152);
  --ok-line:     oklch(0.86 0.06 152);
  --bad:         oklch(0.52 0.19 22);
  --bad-ink:     var(--bad);
  --bad-wash:    oklch(0.97 0.02 22);
  --bad-line:    oklch(0.84 0.09 22);

  --r: 8px;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --bg:          oklch(0.175 0.020 245);
    --surface:     oklch(0.212 0.022 245);
    --line:        oklch(0.315 0.024 245);
    --line-strong: oklch(0.400 0.028 245);

    --ink:         oklch(0.955 0.008 245);
    --ink-2:       oklch(0.800 0.016 245);
    --ink-3:       oklch(0.680 0.018 245);

    --chrome:      oklch(0.285 0.045 245);
    --teal:        oklch(0.780 0.105 178);

    --brass:       oklch(0.795 0.105 76);
    --brass-ink:   oklch(0.880 0.075 76);
    --brass-wash:  oklch(0.300 0.045 76);
    --brass-line:  oklch(0.430 0.070 76);
    --ok:          oklch(0.755 0.130 152);
    --ok-ink:      oklch(0.860 0.090 152);
    --ok-wash:     oklch(0.285 0.050 152);
    --ok-line:     oklch(0.420 0.070 152);
    --bad:         oklch(0.740 0.150 22);
    --bad-ink:     oklch(0.860 0.090 22);
    --bad-wash:    oklch(0.285 0.060 22);
    --bad-line:    oklch(0.440 0.100 22);
  }
}

* { box-sizing: border-box; margin: 0; padding: 0 }

body {
  font-family: var(--font);
  color: var(--ink);
  background: var(--bg);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none }
a:hover { text-decoration: underline; text-underline-offset: 3px }
:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; border-radius: 3px }

.wrap { max-width: 1060px; margin: 0 auto; padding: 0 28px }

/* ------------------------------------------------------------ the bar
 *
 * The site's bar, rule for rule, not a smaller cousin of it: 64px tall, a
 * 26px gap, the wordmark at 30/800, and nav links as pills that take a
 * background on hover. Which page you are on is the lit pill, the site's own
 * idiom, rather than a slash and a word in a different colour.
 *
 * Not sticky, and that is the one deliberate difference. The site sticks its
 * bar because a reader scrolls through hundreds of results; this page is one
 * screen of six rows and a bar following it down would take 64px of it for
 * nothing. */

.chrome { background: var(--chrome); color: var(--chrome-ink) }
/* The bar takes the site's measure, not the board's. The board is a narrow
   document and the bar is the site's furniture: at 1280 the site puts its
   wordmark 40px from the edge, and a reader crossing over should not watch it
   jump a hundred pixels inward. Measured against the built site at 1280 and
   390: same left edge in both. */
.chrome .wrap { max-width: 1400px; padding: 0 40px }
.chrome-in { display: flex; align-items: center; gap: 26px; height: 64px }
.mark { display: flex; align-items: center; gap: 9px; flex: 0 0 auto }
.mark-word { font-size: 30px; font-weight: 800; letter-spacing: .1em; color: inherit }
.mark-word:hover { text-decoration: none }
.mark-glyph { width: 28px; height: 28px; flex: 0 0 auto; display: block }
.mark-glyph svg { display: block; width: 28px; height: 28px }
.chrome .nav { display: flex; gap: 2px; align-items: center; flex: 1 1 auto }
.chrome .nav a {
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 600;
  color: var(--chrome-ink);
  transition: color .15s ease, background-color .15s ease;
}
.chrome .nav a:hover { text-decoration: none; background: oklch(1 0 0 / 0.09) }
.chrome .nav a[aria-current="page"] { background: oklch(1 0 0 / 0.12) }

/* ------------------------------------------------------- the verdict */

/* The one thing a reader came for, and the only band of colour on the page, so
   that a glance from across a room is already the answer. */
.state { border-bottom: 1px solid var(--ok-line); background: var(--ok-wash) }
.state.slow { border-color: var(--brass-line); background: var(--brass-wash) }
.state.down, .state.unknown { border-color: var(--bad-line); background: var(--bad-wash) }

.state-in { display: flex; align-items: center; gap: 16px; padding: 26px 0 }
.state .dot {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--ok);
  flex: 0 0 auto;
  display: grid;
  place-items: center;
}
.state.slow .dot { background: var(--brass) }
.state.down .dot, .state.unknown .dot { background: var(--bad) }
.state .dot svg { display: block }
.state h1 { font-size: 23px; font-weight: 600; letter-spacing: -0.01em; text-wrap: balance }
.state p { font-size: 13.5px; color: var(--ink-2); margin-top: 2px; max-width: 76ch }
.state .when {
  margin-left: auto;
  align-self: flex-start;
  padding-top: 4px;
  font-size: 13px;
  color: var(--ink-3);
  font-family: var(--mono);
  white-space: nowrap;
}

/* --------------------------------------------------------- the board */

.board { padding: 30px 0 6px }
.row { padding: 20px 0; border-bottom: 1px solid var(--line) }
.row:last-child { border-bottom: 0 }
.row-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap }
.row-head b { font-size: 16px; font-weight: 600 }
.row-head .host { font-family: var(--mono); font-size: 12px; color: var(--ink-3) }

.pill {
  margin-left: auto;
  font-size: 12px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 20px;
  white-space: nowrap;
  background: var(--ok-wash);
  color: var(--ok-ink);
  border: 1px solid var(--ok-line);
}
.pill.slow { background: var(--brass-wash); color: var(--brass-ink); border-color: var(--brass-line) }
.pill.down { background: var(--bad-wash); color: var(--bad-ink); border-color: var(--bad-line) }
.pill.unknown { background: var(--surface); color: var(--ink-3); border-color: var(--line-strong) }

.row .note { font-size: 13.5px; color: var(--ink-2); margin-top: 2px }
.row .why {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--bad-ink);
  margin-top: 6px;
  overflow-wrap: anywhere;
}
.row .why.slow { color: var(--brass-ink) }
.row .why.unknown { color: var(--ink-3) }

/* ------------------------------------------------- the two views
 *
 * One switch at the top of the board, and it moves all six rows at once. A
 * per-row control would let a reader build a page where two rows are measuring
 * different things, which is the one thing a status page must never look like.
 *
 * It is a checkbox and two labels, which is the whole mechanism: this page
 * ships no script and is not going to grow one for a control that CSS can hold
 * the state of by itself. The input is off-screen rather than display:none, so
 * it stays focusable and the switch works from the keyboard. */

.vswitch { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none }
.viewbar { display: flex; align-items: center; gap: 16px; margin: 0 0 4px }
.viewbar h2.sec { margin: 0; flex: 1 1 auto }
.views {
  display: inline-flex;
  padding: 2px;
  gap: 2px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: var(--surface);
}
.seg {
  padding: 4px 11px;
  border-radius: 5px;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.seg:hover { color: var(--ink) }
/* Uptime is the view the page opens on, so its segment is the lit one until
   the checkbox says otherwise, and then they swap. */
.seg.a { background: var(--bg); color: var(--ink); box-shadow: 0 1px 2px oklch(0 0 0 / 0.06) }
.vswitch:checked ~ .viewbar .seg.a { background: none; color: var(--ink-3); box-shadow: none }
.vswitch:checked ~ .viewbar .seg.b {
  background: var(--bg);
  color: var(--ink);
  box-shadow: 0 1px 2px oklch(0 0 0 / 0.06);
}
.vswitch:focus-visible ~ .viewbar .views { outline: 2px solid var(--teal); outline-offset: 2px }

/* Both views occupy the same block, one of them drawn at a time, with the hover
   strip lying over whichever it is. */
.graph { position: relative; margin-top: 14px }
.line { display: none }
.vswitch:checked ~ .row .bars { display: none }
.vswitch:checked ~ .row .line { display: block }
/* The axis label belongs to a view that is not on screen yet. */
.scale .axis { display: none }
.vswitch:checked ~ .row .scale .axis { display: block }

/* Thirty days, one bar each, and no gaps in the row: a missing day is a bar in
   the no-check colour, never an absence, because a shorter strip would read as
   a better record. */
.bars { display: flex; gap: 2px; height: 32px; align-items: stretch }
.bars i { flex: 1; border-radius: 2px; background: var(--line) }
.bars i.up { background: var(--ok) }
.bars i.slow { background: var(--brass) }
.bars i.down { background: var(--bad) }
/* Today is not a finished day. Half height so the strip does not end on a claim
   it cannot make yet. */
.bars i.partial { align-self: flex-end; height: 60% }

/* ------------------------------------------- the response-time view */

.plot { display: block; overflow: visible }
.plot .lat {
  fill: none;
  stroke: var(--teal);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
/* A single day has no line, so it gets a tick at its height. */
.plot .dot { stroke: var(--teal); stroke-width: 3; stroke-linecap: round; vector-effect: non-scaling-stroke }
.plot .mark {
  stroke: var(--line-strong);
  stroke-width: 1;
  stroke-dasharray: 4 4;
  vector-effect: non-scaling-stroke;
}
.plot .b-down { fill: var(--bad-wash) }
.plot .b-slow { fill: var(--brass-wash) }

.legend {
  font-size: 12px;
  color: var(--ink-3);
  max-width: 70ch;
  margin-top: 16px;
  display: none;
}
.vswitch:checked ~ .legend { display: block }

/* -------------------------------------------------- pointing at a day */

.hits { position: absolute; inset: 0; display: flex; gap: 2px }
.hit { flex: 1; position: relative }
.tip {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: none;
  flex-direction: column;
  gap: 1px;
  padding: 8px 11px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--bg);
  box-shadow: 0 6px 20px oklch(0 0 0 / 0.13);
  font-size: 12px;
  line-height: 1.45;
  color: var(--ink-2);
  white-space: nowrap;
}
.hit:hover .tip { display: flex }
.tip .t-day { font-family: var(--mono); font-size: 11px; color: var(--ink-3) }
.tip b { font-size: 13px; font-weight: 600; color: var(--ink) }
.tip .t-ms { font-family: var(--mono) }
.tip .t-ok { color: var(--ok-ink) }
.tip .t-slow { color: var(--brass-ink) }
.tip .t-bad { color: var(--bad-ink) }
/* A card centred on the first or last day hangs off the side of the column, so
   near the ends it anchors to its edge instead. */
.hit:nth-child(-n+4) .tip { left: 0; transform: none }
.hit:nth-last-child(-n+4) .tip { left: auto; right: 0; transform: none }
/* The day being pointed at, in both views. */
.hit:hover::after {
  content: "";
  position: absolute;
  inset: -3px -1px;
  border-radius: 3px;
  background: oklch(0.5 0.02 245 / 0.16);
}

.scale {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 7px;
  font-size: 11.5px;
  color: var(--ink-3);
}
.scale b { font-weight: 600; color: var(--ink-2) }
.scale .axis { text-align: center; font-family: var(--mono) }

/* -------------------------------------------------------- the record */

h2.sec {
  font-family: var(--narrow);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-size: 12px;
  color: var(--ink-3);
  margin: 38px 0 14px;
}
.inc { border-left: 2px solid var(--line); padding: 0 0 22px 18px; position: relative }
/* The rail is a thread through the list, so it stops with the list rather than
   running on into the rule the footer draws. */
.inc:last-of-type { padding-bottom: 6px }
.inc::before {
  content: "";
  position: absolute;
  left: -5px;
  top: 7px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--line-strong);
}
.inc.down::before { background: var(--bad) }
.inc.degraded::before { background: var(--brass) }
.inc.planned::before { background: var(--ok) }
.inc .day { font-family: var(--mono); font-size: 12px; color: var(--ink-3) }
.inc h3 { font-size: 15.5px; font-weight: 600; margin-top: 2px }
.inc p { font-size: 14px; color: var(--ink-2); margin-top: 4px; max-width: 74ch }
.inc p + p { margin-top: 8px }

/* An incident the checks opened and nobody has written up yet. It is on the
   page from the minute it opened, which is the point of the page; this says so
   rather than leaving a heading with nothing under it. */

.tag {
  display: inline-block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 1px 6px;
  border-radius: 4px;
  margin-left: 8px;
  vertical-align: 1px;
  border: 1px solid var(--line-strong);
  color: var(--ink-3);
}
.tag.open { border-color: var(--bad-line); background: var(--bad-wash); color: var(--bad-ink) }

.quiet { font-size: 14px; color: var(--ink-3); padding: 2px 0 30px }

footer {
  border-top: 1px solid var(--line);
  margin-top: 30px;
  padding: 20px 0 46px;
  font-size: 13px;
  color: var(--ink-3);
  display: flex;
  gap: 8px 22px;
  flex-wrap: wrap;
}
footer a { border-bottom: 1px solid var(--line-strong) }
footer a:hover { text-decoration: none; border-color: currentColor }

/* --------------------------------------------------------- on a phone */

@media (max-width: 720px) {
  .wrap, .chrome .wrap { padding: 0 16px }
  /* Three links and a wordmark is all that fits. The one that goes is the
     site, because the wordmark to its left is already that link: keeping it
     wrapped the bar onto a second line and pushed the last word off the
     right edge. */
  .chrome-in { gap: 14px }
  .chrome .nav { white-space: nowrap }
  .chrome .nav a { padding: 8px 8px }
  .chrome .nav a.dup { display: none }
  .state-in { flex-wrap: wrap; padding: 20px 0 }
  .state h1 { font-size: 20px }
  /* The timestamp drops under the verdict rather than squeezing it. */
  .state .when { margin-left: 46px; padding-top: 0; flex-basis: 100% }
  .row-head .pill { margin-left: 0; order: 3 }
  .row-head .host { flex-basis: 100%; margin-top: -2px }
  /* Thirty bars in a 358px phone is about 10px each, so the whole strip fits
     and the rule that used to hide the older sixty is gone with the days it
     was hiding. */
  .bars { height: 26px; gap: 1px }
  .hits { gap: 1px }
  .viewbar { flex-wrap: wrap; gap: 8px 12px }
  .seg { padding: 4px 9px }
  /* A card is wider than a thirtieth of a phone, so near the ends it anchors to
     the edge of the strip over a wider span than it does on a desktop. */
  .hit:nth-child(-n+8) .tip { left: 0; right: auto; transform: none }
  .hit:nth-last-child(-n+8) .tip { left: auto; right: 0; transform: none }
}

/* A pointer is what this strip is built for. Where there is none, the card
   cannot be reached at all, so nothing pretends otherwise: the graph keeps its
   label, the record underneath is prose, and /v1/summary has every number. */
@media (hover: none) {
  .tip { display: none !important }
  .hit:hover::after { background: none }
}

@media (prefers-reduced-motion: no-preference) {
  .pill, .bars i { transition: background .15s ease }
}
