/* ---------------------------------------------------------------------------------------------
   Kahua Status Page.

   Three rules this file will not break:

   1. Status is never communicated by colour alone. Every indicator carries an icon, a label or a
      shape, so the page reads correctly for colour-blind users, in greyscale, and when printed.
   2. No third-party anything - no webfont, no icon CDN, no analytics. The one page that must stay
      up during someone else's bad day cannot depend on someone else's infrastructure. Everything
      here is system fonts and inline SVG.
   3. Nothing animates or moves on load. A visitor arriving mid-incident wants to read a sentence,
      not watch a page assemble itself.
   --------------------------------------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  /* Status palette, tuned for contrast against both surfaces rather than for vividness: ninety of
     these sit side by side, where saturated colour becomes noise. */
  --operational: #1f9d55;
  --degraded:    #d08320;
  /* Between amber and red on purpose: more serious than "slow", not yet "confirmed down". Paired
     with its own icon and its own word, so the state never rests on hue alone - a third warm colour
     is exactly the case where colour-only encoding fails. */
  --investigating: #e0662a;
  --outage:      #d1382b;
  --maintenance: #3b7dd8;
  --unknown:     #c3c9d1;

  --operational-soft: rgba(31, 157, 85, 0.11);
  --degraded-soft:    rgba(208, 131, 32, 0.13);
  --investigating-soft: rgba(224, 102, 42, 0.12);
  --outage-soft:      rgba(209, 56, 43, 0.11);
  --maintenance-soft: rgba(59, 125, 216, 0.11);

  --ink:       #151b24;
  --ink-soft:  #586473;
  --ink-faint: #8a94a1;
  --line:      #e4e8ed;
  --line-soft: #eff2f5;
  --surface:   #ffffff;
  --page:      #f5f7f9;

  --kahua-red: #e8542f;

  --radius:    10px;
  --radius-sm: 6px;
  --wrap:      1020px;

  --shadow-card: 0 1px 2px rgba(21, 27, 36, 0.05), 0 2px 8px rgba(21, 27, 36, 0.04);
  --shadow-pop:  0 6px 22px rgba(21, 27, 36, 0.18);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --operational: #35c172;
    --degraded:    #e2a03c;
    --investigating: #f2803f;
    --outage:      #ef5b4c;
    --maintenance: #5a9bf0;
    --unknown:     #414956;

    --operational-soft: rgba(53, 193, 114, 0.14);
    --degraded-soft:    rgba(226, 160, 60, 0.15);
    --investigating-soft: rgba(242, 128, 63, 0.15);
    --outage-soft:      rgba(239, 91, 76, 0.14);
    --maintenance-soft: rgba(90, 155, 240, 0.14);

    --ink:       #e7ebf1;
    --ink-soft:  #a0aab8;
    --ink-faint: #74808e;
    --line:      #29303a;
    --line-soft: #20262f;
    --surface:   #161b22;
    --page:      #0e1217;

    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.45);
    --shadow-pop:  0 8px 26px rgba(0, 0, 0, 0.6);
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }

a { color: var(--ink-soft); }

:focus-visible {
  outline: 2px solid var(--maintenance);
  outline-offset: 2px;
  border-radius: 3px;
}

/* ── masthead ─────────────────────────────────────────────────────────────── */

.masthead {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 20;
}

.masthead-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 60px;
}

.brand {
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--kahua-red);
}

.brand-sub { color: var(--ink-soft); font-weight: 500; }

.support-link {
  font-size: 0.86rem;
  font-weight: 500;
  text-decoration: none;
  padding: 6px 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  transition: color 0.15s, border-color 0.15s;
}

.support-link:hover { color: var(--ink); border-color: var(--ink-faint); }

main { padding: 30px 0 56px; }

/* ── the banner: the one thing most visitors read ─────────────────────────── */

.banner {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 20px 22px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  font-size: 1.18rem;
  font-weight: 620;
  letter-spacing: -0.01em;
}

/* The glyph is a shape first - tick, bang, cross, wrench, dash - so the banner still says which
   state it is in greyscale or with colour vision deficiency. */
.banner-icon {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--unknown);
  position: relative;
}

.banner-icon::after {
  content: "";
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 15px 15px;
}

.banner-operational .banner-icon { background: var(--operational); }
.banner-degraded    .banner-icon { background: var(--degraded); }
.banner-investigating .banner-icon { background: var(--investigating); }
.banner-outage      .banner-icon { background: var(--outage); }
.banner-maintenance .banner-icon { background: var(--maintenance); }

.banner-operational .banner-icon::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.4l3.3 3.3L13 5' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.banner-degraded .banner-icon::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3.4v5.3' stroke='white' stroke-width='2.2' stroke-linecap='round'/%3E%3Ccircle cx='8' cy='12.2' r='1.3' fill='white'/%3E%3C/svg%3E");
}
/* A magnifier, not another exclamation mark. The icon is the redundant channel that makes
   Investigating distinguishable from Degraded for anyone who cannot separate two warm hues. */
.banner-investigating .banner-icon::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='7' cy='7' r='3.6' fill='none' stroke='white' stroke-width='1.9'/%3E%3Cpath d='M9.8 9.8l2.6 2.6' stroke='white' stroke-width='2.1' stroke-linecap='round'/%3E%3C/svg%3E");
}
.banner-outage .banner-icon::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.6 4.6l6.8 6.8M11.4 4.6l-6.8 6.8' stroke='white' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
}
.banner-maintenance .banner-icon::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='4.6' fill='none' stroke='white' stroke-width='1.7'/%3E%3Cpath d='M8 5.2V8l2 1.4' fill='none' stroke='white' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E");
}
.banner-unknown .banner-icon::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.6 8h6.8' stroke='white' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
}

.banner-operational { background: linear-gradient(var(--operational-soft), var(--operational-soft)), var(--surface); }
.banner-degraded    { background: linear-gradient(var(--degraded-soft), var(--degraded-soft)), var(--surface); }
.banner-investigating { background: linear-gradient(var(--investigating-soft), var(--investigating-soft)), var(--surface); }
.banner-outage      { background: linear-gradient(var(--outage-soft), var(--outage-soft)), var(--surface); }
.banner-maintenance { background: linear-gradient(var(--maintenance-soft), var(--maintenance-soft)), var(--surface); }

.staleness {
  margin-top: 12px;
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--degraded);
  background: var(--degraded-soft);
  font-size: 0.9rem;
}

/* ── legend ───────────────────────────────────────────────────────────────── */

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 26px 0 14px;
  padding: 0;
}

.legend li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.79rem;
  font-weight: 500;
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 11px 4px 9px;
}

.dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 3px;
  background: var(--unknown);
}

.dot-operational { background: var(--operational); }
.dot-degraded    { background: var(--degraded); }
/* The ring is a third channel: it reads as "not settled" next to the solid dots around it. */
.dot-investigating {
  background: var(--investigating);
  box-shadow: 0 0 0 3px var(--investigating-soft);
}
.dot-outage      { background: var(--outage); }
.dot-maintenance { background: var(--maintenance); }
.dot-unknown     { background: var(--unknown); }

/* ── networks ─────────────────────────────────────────────────────────────── */
/* Kahua runs a Commercial network and a Government network. The heading is the point: a customer
   of one has no interest in the other, and a single flat list makes them do that filtering by
   reading environment codes. */

.network { margin-bottom: 28px; }
.network:last-child { margin-bottom: 8px; }

.network-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  padding: 0 2px 8px;
  margin-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

.network-name {
  font-size: 15.5px;
  font-weight: 650;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--ink);
}

.network-desc { font-size: 12.5px; color: var(--ink-faint); }

/* Pushed right so the eye can run down one column of network verdicts without reading the names. */
.network-status {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--ink-soft);
}

/* ── environment cards ────────────────────────────────────────────────────── */

.env-desc {
  font-size: 12px;
  color: var(--ink-faint);
  font-weight: 400;
}

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

/* The head is a button: the whole row is the target, not just the caret. */
.env-head {
  appearance: none;
  width: 100%;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 15px 20px;
  transition: background 0.13s;
}

.env-head:hover { background: var(--line-soft); }

.env-caret {
  flex: 0 0 auto;
  font-size: 0.66rem;
  color: var(--ink-faint);
  transition: transform 0.16s ease;
  display: inline-block;
}

.env-head[aria-expanded="true"] .env-caret { transform: rotate(90deg); }

.env-name {
  font-weight: 640;
  letter-spacing: -0.01em;
  font-size: 1rem;
}

.env-status {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
}

.env-uptime {
  flex: 0 0 auto;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  min-width: 12ch;
  text-align: right;
}

.env-body { padding: 4px 20px 18px; }

.components {
  margin-top: 16px;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.components strong { font-weight: 600; color: var(--ink-soft); }

.component-chip {
  display: inline-block;
  background: var(--line-soft);
  border-radius: var(--radius-sm);
  padding: 2px 9px;
  margin: 0 4px 4px 0;
  font-size: 0.78rem;
}

.components-note {
  margin-top: 6px;
  font-size: 0.75rem;
  color: var(--ink-faint);
  line-height: 1.5;
}

/* ── the 90-day bar ───────────────────────────────────────────────────────── */

.bar {
  display: flex;
  gap: 2px;
  height: 38px;
  align-items: stretch;
}

.seg {
  flex: 1 1 0;
  min-width: 0;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: var(--unknown);
  cursor: pointer;
  transition: transform 0.12s ease, filter 0.12s ease;
}

.seg-operational { background: var(--operational); }
.seg-degraded    { background: var(--degraded); }
.seg-outage      { background: var(--outage); }
.seg-maintenance { background: var(--maintenance); }

/* No data is a texture, not a fifth colour: hatching survives greyscale and reads as "nothing
   here" rather than as a status we are asserting. */
.seg-unknown {
  background-color: var(--line-soft);
  background-image: repeating-linear-gradient(45deg,
    var(--unknown) 0 2px, transparent 2px 5px);
}

.seg:hover,
.seg:focus-visible {
  transform: scaleY(1.16);
  filter: saturate(1.12);
}

/* A day holding more than one state gets a hairline, so the boundary between two slices is
   legible even where the colours are close in value. */
.seg-mixed { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.07); }

.bar-scale {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
  font-size: 0.73rem;
  color: var(--ink-faint);
}

.empty { font-size: 0.85rem; color: var(--ink-faint); margin: 4px 0 0; }

/* Tooltip. One element, positioned by app.js, reused for all ninety segments - rather than ninety
   nodes waiting in the DOM for a hover that never comes. */
.tip {
  position: fixed;
  z-index: 40;
  max-width: 300px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  background: var(--ink);
  color: var(--page);
  font-size: 0.78rem;
  font-weight: 500;
  line-height: 1.5;
  white-space: pre-line;
  box-shadow: var(--shadow-pop);
  pointer-events: none;
}

/* ── announcements ────────────────────────────────────────────────────────── */

.announcements { margin-top: 34px; }

.tabs {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 16px;
}

.tab {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  font-size: 0.89rem;
  font-weight: 550;
  color: var(--ink-faint);
  padding: 9px 14px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.15s, border-color 0.15s;
}

.tab:hover { color: var(--ink-soft); }
.tab-active { color: var(--ink); border-bottom-color: var(--kahua-red); }

.ann {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--ink-faint);
  border-radius: var(--radius-sm);
  padding: 14px 18px;
  margin-bottom: 10px;
}

.ann-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }

.ann-title { font-weight: 640; font-size: 0.95rem; }

/* Incident vs maintenance, told apart at a glance.
   The markup has asked for `pill pill-incident` / `pill pill-maintenance` since the first version
   and there was never a rule for either, so both rendered as plain grey text and the two kinds of
   notice looked identical. That is the one distinction this page exists to make: planned work
   announced in advance is not an outage, and a customer scanning the history should not have to
   read the title to tell which they are looking at. Colours are the status palette's own, so these
   agree with the legend dots and follow the dark theme without a second rule. */
.pill {
  flex: none;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 680;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}

.pill-incident    { background: var(--outage-soft);      color: var(--outage); }
.pill-maintenance { background: var(--maintenance-soft); color: var(--maintenance); }

/* Where a maintenance window sits in time. Deliberately quieter than the pill: the kind of notice
   matters more than its phase, and this sits beside a date range that already says the same thing
   in full. */
.ann-phase {
  flex: none;
  padding: 1px 7px;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--ink-faint);
  white-space: nowrap;
}

.ann-when {
  margin-top: 3px;
  font-size: 0.78rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.ann-body {
  margin: 8px 0 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
  white-space: pre-line;
}

.ann-affected { margin-top: 9px; font-size: 0.78rem; color: var(--ink-faint); }

/* ── footer ───────────────────────────────────────────────────────────────── */

.footer {
  border-top: 1px solid var(--line);
  background: var(--surface);
  padding: 22px 0 34px;
}

.footer-note { margin: 0 0 6px; font-size: 0.8rem; color: var(--ink-faint); }
.footer-updated { font-variant-numeric: tabular-nums; }

/* ── responsive ───────────────────────────────────────────────────────────── */

@media (max-width: 700px) {
  .wrap { padding: 0 16px; }
  .banner { font-size: 1.04rem; padding: 17px 18px; }
  .env-head { flex-wrap: wrap; gap: 8px 10px; }
  .env-status { margin-left: 0; }
  /* Same reason as .env-status: margin-left:auto on a wrapped row pushes the verdict onto its own
     line, miles from the name it belongs to. */
  .network-status { margin-left: 0; }
  .network-head { gap: 4px 10px; }
  .env-uptime { min-width: 0; text-align: left; }
  .bar { height: 30px; gap: 1px; }
}

/* Below this width ninety segments are under 3px each; the gaps turn the bar into a dotted line,
   so they go. */
@media (max-width: 430px) {
  .bar { gap: 0; }
  .seg { border-radius: 1px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .seg:hover, .seg:focus-visible { transform: none; }
  .env-head[aria-expanded="true"] .env-caret { transition: none; }
}

/* ── print ────────────────────────────────────────────────────────────────── */

@media print {
  .masthead, .footer, .tabs, .support-link, .tip { display: none; }
  .env, .banner, .ann { box-shadow: none; break-inside: avoid; }
  .env-body { display: block !important; }
}
