/* ============================================================
   91-status.css — the public portal-status page.

   CASCADE POSITION: 91 sorts after 90-polish.css (the last app part).
   The status page is a standalone surface.  Its rules must not be
   overridden by the app's screens, and must not override them.  Both
   constraints are satisfied by scoping every rule here under .sp-page
   (the status page's root element) rather than targeting body/html —
   so this file is safe to load on every page via css_parts(), which
   it is, and still has no side-effects outside its own surface.

   SELF-CONTAINED: The status page loads only this file.  The app's
   pages load it via css_parts() as well; neither path has side-effects
   on the other because all layout rules are inside .sp-page.

   TOKEN POLICY
   ·  Border-radius: var(--radius-*), defined below so the file
      works standalone; the same values live in 00-tokens.css.
   ·  Font-size:     var(--type-*), same dual-definition approach.
   ·  Custom props prefixed --sp-* are new; no conflict with the app.
   ============================================================ */

/* ── Token copy ── (must track 00-tokens.css for consistency) ─────────────
   These are NOT the authoritative definitions — 00-tokens.css owns that.
   They are here so the status page is self-contained when loaded without
   the app's cascade.  On the home page, 00-tokens.css (00 < 91) wins the
   same values first; redefining them here at the same value is a no-op.   */
:root {
    /* Surfaces */
    --sp-canvas:        #ffffff;
    --sp-canvas-soft:   #fafafa;
    --sp-canvas-soft-2: #f5f5f5;

    /* Text */
    --sp-ink:    #171717;
    --sp-body:   #4d4d4d;
    --sp-mute:   #6f6f6f;

    /* Lines */
    --sp-hairline: #ebebeb;

    /* Accent + semantic */
    --sp-link:          #0070f3;
    --sp-success:       #0a7d3e;
    --sp-success-soft:  #e6f4ec;
    --sp-warning:       #f5a623;
    --sp-warning-soft:  #ffefcf;
    --sp-error:         #cc0000;
    --sp-error-soft:    #f7d4d6;
    --sp-blue-soft:     #dbeafe;
    --sp-blue:          #1d4ed8;

    /* Typography */
    --sp-font: 'Geist', system-ui, -apple-system, BlinkMacSystemFont,
               'Segoe UI', sans-serif;

    /* Layout */
    --sp-max-w: 860px;
}

/* ── The shared ladders, SCOPED ────────────────────────────────────────────
   `--radius-*` and `--type-*` belong to `00-tokens.css`. This page needs them
   to stand alone, but they are declared on `.sp-page` and NOT on `:root`,
   because this file sorts at 91 and `css_parts()` loads it on every page: a
   `:root` copy would override the app's own ladder everywhere the cascade
   reaches.

   Today the eleven values are byte-identical to `00-tokens.css` — verified
   token by token — so the override would be a no-op. That is exactly what
   makes it dangerous: the next person to retune a radius or a type step edits
   `00-tokens.css`, sees the app ignore it, and has no reason to suspect the
   status page. Scoping costs nothing and removes the trap.                */
.sp-page {
    /* Radius ladder — mirrors 00-tokens.css */
    --radius-2xs:  2px;
    --radius-xs:   4px;
    --radius-sm:   6px;
    --radius-md:   8px;
    --radius-full: 9999px;

    /* Type ladder — mirrors 00-tokens.css */
    --type-72:  0.72rem;
    --type-75:  0.75rem;
    --type-80:  0.8rem;
    --type-90:  0.9rem;
    --type-95:  0.95rem;
    --type-100: 1rem;
}

/* ── Scoped reset ──────────────────────────────────────────────────────────
   Scoped under .sp-page so the reset does not touch the app's shell when
   this file is loaded by the home page via css_parts().               */
.sp-page *, .sp-page *::before, .sp-page *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

/* ── Layout wrapper ───────────────────────────────────────────────────────
   Merges what would have been `html` and `body` rules into the root
   wrapper, keeping them scoped and avoiding any conflict with the app. */
.sp-page {
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    font-family: var(--sp-font);
    font-size: 0.9375rem;   /* 15px — not tokenised (0.9375 ∉ TYPE_TOKENS) */
    line-height: 1.5;
    color: var(--sp-body);
    background: var(--sp-canvas-soft);
    -webkit-font-smoothing: antialiased;
}

/* ── Layout ───────────────────────────────────────────────────────────────── */
.sp-content {
    flex: 1;
    width: 100%;
    max-width: var(--sp-max-w);
    margin: 0 auto;
    padding: 0 16px 48px;
}

/* ── Header ───────────────────────────────────────────────────────────────── */
.sp-header {
    background: var(--sp-canvas);
    border-bottom: 1px solid var(--sp-hairline);
    padding: 0 16px;
}

.sp-header-inner {
    max-width: var(--sp-max-w);
    margin: 0 auto;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.sp-wordmark {
    font-size: 1.125rem;   /* 18px — not tokenised (1.125 ∉ TYPE_TOKENS) */
    font-weight: 700;
    color: var(--sp-ink);
    text-decoration: none;
    letter-spacing: -0.02em;
}

.sp-wordmark:hover { color: var(--sp-link); }

.sp-back-link {
    font-size: 0.8125rem;  /* 13px — not tokenised (0.8125 ∉ TYPE_TOKENS) */
    color: var(--sp-mute);
    text-decoration: none;
    display: flex;
    align-items: center;
    gap: 4px;
}

.sp-back-link:hover { color: var(--sp-link); }

/* ── Overall banner ───────────────────────────────────────────────────────── */
.sp-banner {
    border-radius: var(--radius-md);
    border: 1px solid var(--sp-hairline);
    padding: 20px 24px;
    margin-top: 24px;
    display: flex;
    align-items: flex-start;
    gap: 14px;
    background: var(--sp-canvas);
}

.sp-banner--operational { border-left: 4px solid var(--sp-success); }
.sp-banner--degraded    { border-left: 4px solid var(--sp-warning); }
.sp-banner--down        { border-left: 4px solid var(--sp-error); }
.sp-banner--maintenance { border-left: 4px solid var(--sp-blue); }
.sp-banner--unknown     { border-left: 4px solid var(--sp-hairline); }
.sp-banner--stale       { border-left: 4px solid var(--sp-mute); }

.sp-banner-dot {
    width: 10px;
    height: 10px;
    border-radius: var(--radius-full);
    flex-shrink: 0;
    margin-top: 5px;
}

.sp-banner-dot--operational { background: var(--sp-success); }
.sp-banner-dot--degraded    { background: var(--sp-warning); }
.sp-banner-dot--down        { background: var(--sp-error); }
.sp-banner-dot--maintenance { background: var(--sp-blue); }
.sp-banner-dot--unknown,
.sp-banner-dot--stale       { background: var(--sp-mute); }

.sp-banner-text { flex: 1; }

.sp-banner-title {
    font-size: 1.0625rem;  /* 17px — not tokenised (1.0625 ∉ TYPE_TOKENS) */
    font-weight: 600;
    color: var(--sp-ink);
}

.sp-banner-sub {
    font-size: 0.8125rem;  /* 13px — not tokenised */
    color: var(--sp-mute);
    margin-top: 2px;
}

/* ── Section ──────────────────────────────────────────────────────────────── */
.sp-section {
    margin-top: 32px;
}

.sp-section-title {
    font-size: var(--type-72);   /* was 0.72rem — now uses token */
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--sp-mute);
    margin-bottom: 12px;
}

.sp-card {
    background: var(--sp-canvas);
    border: 1px solid var(--sp-hairline);
    border-radius: var(--radius-md);
    overflow: hidden;
}

/* ── Status pill ──────────────────────────────────────────────────────────── */
.sp-pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px;
    border-radius: var(--radius-full);
    font-size: var(--type-75);   /* was 0.75rem — now uses token */
    font-weight: 600;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.sp-pill--operational  { background: var(--sp-success-soft); color: var(--sp-success); }
.sp-pill--degraded     { background: var(--sp-warning-soft); color: #7c3a00; }
.sp-pill--down         { background: var(--sp-error-soft);   color: var(--sp-error); }
.sp-pill--maintenance  { background: var(--sp-blue-soft);    color: var(--sp-blue); }
.sp-pill--unknown      { background: var(--sp-canvas-soft-2); color: var(--sp-mute); }
.sp-pill--investigating { background: #fff3cd; color: #7c5800; }
.sp-pill--identified   { background: var(--sp-warning-soft); color: #7c3a00; }
.sp-pill--monitoring   { background: var(--sp-blue-soft);    color: var(--sp-blue); }
.sp-pill--resolved     { background: var(--sp-success-soft); color: var(--sp-success); }
.sp-pill--scheduled    { background: var(--sp-blue-soft);    color: var(--sp-blue); }
.sp-pill--minor        { background: var(--sp-warning-soft); color: #7c3a00; }
.sp-pill--major        { background: var(--sp-error-soft);   color: #900; }
.sp-pill--critical     { background: var(--sp-error-soft);   color: var(--sp-error); font-weight: 700; }
.sp-pill--none         { background: var(--sp-canvas-soft-2); color: var(--sp-mute); }

/* ── Incidents ────────────────────────────────────────────────────────────── */
.sp-incident {
    padding: 16px 20px;
    border-bottom: 1px solid var(--sp-hairline);
}

.sp-incident:last-child { border-bottom: none; }

.sp-incident-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.sp-incident-title {
    font-size: 0.9375rem;  /* 15px — not tokenised */
    font-weight: 600;
    color: var(--sp-ink);
    flex: 1;
    min-width: 0;
}

.sp-incident-pills {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
    flex-shrink: 0;
}

.sp-incident-portals {
    font-size: 0.8125rem;  /* 13px — not tokenised */
    color: var(--sp-mute);
    margin-top: 4px;
}

/* Update timeline */
.sp-timeline {
    margin-top: 12px;
    border-left: 2px solid var(--sp-hairline);
    padding-left: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.sp-timeline-entry { position: relative; }

.sp-timeline-entry::before {
    content: '';
    position: absolute;
    left: -19px;
    top: 5px;
    width: 6px;
    height: 6px;
    border-radius: var(--radius-full);
    background: var(--sp-hairline);
    border: 2px solid var(--sp-canvas);
}

.sp-timeline-when {
    font-size: var(--type-75);   /* was 0.75rem */
    color: var(--sp-mute);
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 3px;
}

.sp-timeline-body {
    font-size: 0.875rem;   /* 14px — not tokenised (0.875 ∉ TYPE_TOKENS) */
    color: var(--sp-body);
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── Components ───────────────────────────────────────────────────────────── */
.sp-component {
    padding: 14px 20px;
    border-bottom: 1px solid var(--sp-hairline);
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 8px 16px;
    align-items: start;
}

.sp-component:last-child { border-bottom: none; }

.sp-component-label {
    font-weight: 600;
    font-size: 0.9375rem;  /* 15px — not tokenised */
    color: var(--sp-ink);
}

.sp-component-services {
    font-size: 0.8125rem;  /* 13px — not tokenised */
    color: var(--sp-mute);
    margin-top: 2px;
}

.sp-component-right {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
}

/* The 90-bar strip.  FLEX, no wrap — bars must compress, never wrap.
   At 340px × 90 bars, bars are ~1.5px wide; that still reads as a sparkline.
   Measured: 90 bars × 4px + 89 × 2px gap = 538px — wraps at any phone width.
   The responsive rule at 599.98px below cuts bar/gap widths to fit. */
.sp-bar-strip {
    display: flex;
    flex-direction: row;
    align-items: flex-end;
    gap: 2px;
    height: 24px;
    min-width: 0;
    overflow: hidden;
}

/* .sb = "status bar".  Short class name on purpose: each bar element is
   emitted 90 × 11 = 990 times.  Verbose names (`sp-bar bar--operational`)
   cost 43 KB for the bar section alone; short names cost ~25 KB.
   The status is carried by a second class: ok / dg / dn / mt.
   No second class = unknown/hollow (the default is the honest null state). */
.sb {
    flex: 0 0 auto;
    width: 4px;
    min-width: 1px;
    height: 20px;
    border-radius: var(--radius-2xs);
    transition: height 0.15s;
    /* default = unknown: hollow, not green */
    background: var(--sp-canvas-soft-2);
    box-shadow: inset 0 0 0 1px var(--sp-hairline);
}

.sb.ok { background: var(--sp-success); box-shadow: none; }
.sb.dg { background: var(--sp-warning); box-shadow: none; }
.sb.dn { background: var(--sp-error);   box-shadow: none; }
.sb.mt { background: var(--sp-blue);    box-shadow: none; }

.sp-uptime-pct {
    font-size: var(--type-75);   /* was 0.75rem */
    color: var(--sp-mute);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ── Incident history by month ────────────────────────────────────────────── */
.sp-month-group { margin-bottom: 20px; }

.sp-month-label {
    font-size: 0.8125rem;  /* 13px — not tokenised */
    font-weight: 600;
    color: var(--sp-mute);
    padding: 6px 0;
    letter-spacing: 0.03em;
}

/* ── Stale note ───────────────────────────────────────────────────────────── */
/* Fixed, outside .sp-page.  Shown only on poll failure; must not obscure
   content.  Font stack inlined because it is outside the .sp-page scope. */
.sp-stale-note {
    position: fixed;
    bottom: 16px;
    left: 50%;
    transform: translateX(-50%);
    background: var(--sp-ink);
    color: #fff;
    font-family: var(--sp-font);
    font-size: 0.8125rem;  /* 13px — not tokenised */
    padding: 8px 16px;
    border-radius: var(--radius-full);
    box-shadow: 0 4px 12px rgba(0,0,0,0.2);
    pointer-events: none;
    z-index: 100;
}

.sp-stale-note[hidden] { display: none; }

/* ── Footer ───────────────────────────────────────────────────────────────── */
.sp-footer {
    border-top: 1px solid var(--sp-hairline);
    background: var(--sp-canvas);
    padding: 24px 16px;
    margin-top: 40px;
}

.sp-footer-inner {
    max-width: var(--sp-max-w);
    margin: 0 auto;
    font-size: 0.8125rem;  /* 13px — not tokenised */
    color: var(--sp-mute);
}

.sp-footer-links {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

.sp-footer-links a { color: var(--sp-link); text-decoration: none; }
.sp-footer-links a:hover { text-decoration: underline; }

/* LEGAL DISCLAIMER — this box must remain prominent.
   We report on government portals we do not operate.  Mistaking this page for
   an official government page could lead someone to rely on it for statutory
   deadlines.  The box is visually distinct (soft background, left border)
   so it reads at a glance. */
.sp-disclaimer {
    background: var(--sp-canvas-soft-2);
    border-left: 3px solid var(--sp-hairline);
    border-radius: var(--radius-xs);
    padding: 10px 14px;
    font-size: 0.8125rem;  /* 13px — not tokenised */
    color: var(--sp-mute);
    line-height: 1.5;
    margin-top: 12px;
}

/* ── Screen-reader only ───────────────────────────────────────────────────── */
/* .sr-only is defined in 90-polish.css for the app; redefined here because
   the status page does not load that file in isolation.  Duplicate on
   purpose: the status page must be self-contained. */
.sp-page .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ── Monitor-error state ──────────────────────────────────────────────────── */
.sp-monitor-error {
    background: var(--sp-canvas-soft-2);
    border: 1px solid var(--sp-hairline);
    border-radius: var(--radius-md);
    padding: 20px 24px;
    margin-top: 24px;
    font-size: 0.9375rem;  /* 15px — not tokenised */
    color: var(--sp-body);
}

.sp-monitor-error strong { color: var(--sp-ink); }

/* ── Empty state ──────────────────────────────────────────────────────────── */
.sp-empty {
    padding: 20px;
    text-align: center;
    color: var(--sp-mute);
    font-size: 0.875rem;   /* 14px — not tokenised (0.875 ∉ TYPE_TOKENS) */
}

/* ── Checked-at line ──────────────────────────────────────────────────────── */
.sp-checked-at {
    font-size: var(--type-75);   /* was 0.75rem */
    color: var(--sp-mute);
    margin-top: 6px;
    text-align: right;
}

/* ── Responsive: 340 – 599px ──────────────────────────────────────────────── */
@media (max-width: 599.98px) {
    .sp-component {
        grid-template-columns: 1fr;
    }

    .sp-component-right {
        align-items: flex-start;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 8px;
    }

    /* At 340px: 90 bars × 4px + 89 × 2px = 538px — won't fit.
       2px bar + 1px gap: 90 × 2 + 89 × 1 = 269px — fits at 340px.
       The bars look like a thin sparkline; the hollow/green distinction holds. */
    .sp-bar-strip { gap: 1px; }
    .sb           { width: 2px; min-width: 1px; }

    .sp-banner  { padding: 14px 16px; }
    .sp-incident { padding: 12px 16px; }
}
