/* ===========================================================================
   The page's only stylesheet, served from THIS origin so the CSP stays
   style-src 'self' with no unsafe-inline.

   EVERYTHING HERE IS SELF-HOSTED OR DRAWN. No @import, no CDN, no web font,
   no image fetched from another host. That is not tidiness — this page exists
   to be read when the estate it reports on is down, and an asset fetched from
   that estate would go missing at exactly the moment the page matters. The
   only binary it references is /nexuss-logo.png, copied into wwwroot and
   served from here.

   TYPEFACE. The stack below is copied verbatim from mynexuss.com. That site
   NAMES Inter but ships no @font-face and loads no font file — checked on
   2026-09-07, document.fonts was empty and the markup contains no font-face
   rule and no fonts.googleapis/gstatic link. It relies on Inter being present
   locally and otherwise falls through to Segoe UI / system-ui. Copying the
   stack therefore reproduces the brand's real rendering exactly, needs no
   font file, raises no licence question, and leaves font-src 'none' intact.
   =========================================================================== */

:root {
    color-scheme: light dark;

    /* Neutrals — the light counterpart. mynexuss.com publishes no light theme
       (its html is hard-coded data-theme="dark"), so these are derived to sit
       in the same family rather than copied. The brand hue below is NOT
       derived: #009ef7 is read straight off the site. */
    --bg: #ffffff;
    --bg-2: #f5f8fa;
    --panel: #ffffff;
    --ink: #181c32;
    --muted: #7e8299;
    --line: #e1e3ea;

    /* Brand — read from mynexuss.com's :root on 2026-09-07. */
    --brand: #009ef7;   /* --nx-primary */
    --accent: #7239ea;  /* --nx-accent  */

    /* The brand band is dark in BOTH themes; these never flip. */
    --band-from: #1e1e2d;   /* --nx-bg-2 */
    --band-to: #15151e;     /* --nx-bg   */
    --band-line: #2b2b40;   /* --nx-border */
    --band-ink: #e4e6ef;    /* --nx-text */
    --band-muted: #9899ac;  /* --nx-muted */

    --ok: #47be7d;
    --warn: #d99400;
    --bad: #d9214e;
    --maint: #0095e8;
    --unknown: #a1a5b7;

    /* THE TIMELINE BANDS (2026-09-25). A day that was partly disrupted and a
       day that was dead throughout are no longer the same colour — see
       IntervalSeverity for where the line is drawn and why. --partial is the
       orange Brad asked for; --major is the red the whole strip used to be. */
    --partial: #e8890c;
    --major: #d9214e;

    --radius: 12px;
    --radius-lg: 16px;
}

@media (prefers-color-scheme: dark) {
    :root {
        /* Read from mynexuss.com's :root, one for one. */
        --bg: #15151e;      /* --nx-bg     */
        --bg-2: #1e1e2d;    /* --nx-bg-2   */
        --panel: #1b1b29;   /* --nx-card   */
        --ink: #e4e6ef;     /* --nx-text   */
        --muted: #9899ac;   /* --nx-muted  */
        --line: #2b2b40;    /* --nx-border */

        --ok: #50cd89;
        --warn: #ffc700;
        --bad: #f1416c;
        --maint: #009ef7;
        --unknown: #6d6d80;

        --partial: #ffa73c;
        --major: #f1416c;
    }
}

/* ===========================================================================
   THE COLOUR-BLIND PALETTE.

   Brad, 2026-09-25: "make a colour blind version with a button somewhere to
   switch it." The first attempt was rejected by him the same evening — "why is
   a good status bluer not green? also why is it now white?" — and he was right
   on both counts, plus a third fault neither of us saw by eye.

   WHAT WAS WRONG. That palette abandoned green entirely and made `ok` a pale
   sky blue. Three separate faults:

     1. OVER-APPLIED. The failure mode is red ADJACENT TO green, not green on
        its own. A green bar in isolation is perfectly readable to a deuteranope.
        Dropping green threw away the one status convention every viewer already
        knows and bought nothing.
     2. IT READ AS WHITE. Measured: that blue sat at relative luminance 0.557 on
        a white card, and its CIEDE2000 distance from the no-data grey was 11.7
        under deuteranopia. "Good" and "nothing recorded" were nearly the same
        colour. That is exactly what Brad saw.
     3. THE ONE NOBODY SAW: ok AND MAINTENANCE WERE BOTH BLUE. ok #8ecdf0
        against maint #0072b2 measured dE 12.9 in NORMAL vision and 10.5 under
        tritanopia. The two hardest states to tell apart had become the most
        common one and the one that changes the uptime arithmetic. The palette
        introduced a collision while solving a different one, and the note
        claiming severity was "monotonic in lightness" covered the three
        severity colours and silently left maintenance out of the ordering.

   WHAT THIS ONE DOES. Green stays green in BOTH palettes. Only the disruption
   colours move, and blue is reserved SOLELY for maintenance, so there is no
   green/blue duplication and no red anywhere — therefore no red/green pair to
   confuse in the first place. Partial is amber; major is a dark vermillion.

   MEASURED, NOT REASONED. Every pair is simulated under protanopia,
   deuteranopia and tritanopia (Machado et al. 2009, severity 1.0) and scored
   with CIEDE2000. The full matrix, not just the severity ladder:

     light  worst pair  ok/major     deuteranopia  dE 21.7
     dark   worst pair  ok/partial   deuteranopia  dE 18.9
     ok vs maintenance: dE 22.0 light, 21.4 dark   (was 10.5)

   Roughly double the separation of the palette Brad rejected, and the closest
   pair is now a severity pair rather than ok-versus-something. That is asserted
   by ColourDistinguishabilityTests, so a future collision fails a test instead
   of reaching him.

   HUE IS STILL NOT THE ONLY CHANNEL, in either palette: the day cell's fill
   HEIGHT is proportional, disruption is hatched, maintenance is striped,
   no-data is dotted, and an opened day states its hours in a sentence.

   THE DEFAULT PALETTE IS NOT TOUCHED. Brad, same evening: "for colour blind
   thats fine but for default keep the original colours." --ok and --maint above
   are byte-identical to what they were before any of this work.
   =========================================================================== */
:root[data-palette="cvd"] {
    --ok: #2e8b57;       /* GREEN. Good is green here too. */
    --partial: #ffb020;  /* amber                          */
    --major: #6b2100;    /* dark vermillion, not red       */
    --bad: #6b2100;
    --warn: #ffb020;
    --maint: #1b3f8f;    /* deep indigo — maintenance ONLY */
    --unknown: #a1a5b7;
}

@media (prefers-color-scheme: dark) {
    :root[data-palette="cvd"] {
        --ok: #82ebaa;
        --partial: #eb9b14;
        --major: #b03c12;
        --bad: #b03c12;
        --warn: #eb9b14;
        --maint: #5a8bf0;
        --unknown: #6d6d80;
    }
}

* { box-sizing: border-box; }

body {
    margin: 0;
    padding: 2rem 1rem 4rem;
    background: var(--bg);
    color: var(--ink);
    font: 16px/1.55 "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
}

main { max-width: 56rem; margin: 0 auto; }

/* ---------------------------------------------------------------------------
   The brand band.

   It is DARK IN BOTH THEMES, deliberately. The official wordmark is a
   two-ink PNG — #009ef7 and #ffffff, confirmed by counting its pixels — so
   more than a third of it is pure white and it simply disappears on a light
   background. mynexuss.com never has to solve this because it is dark-only.
   The alternatives were to recolour the mark (inventing a brand variant that
   nobody has approved) or to filter/invert it (which mangles the blue). A
   dark band uses the approved asset UNMODIFIED and keeps the page's own
   light/dark behaviour for everything below it.

   The gradient and the blue glow are lifted from mynexuss.com's own body
   treatment, so the band reads as the same surface the product sits on.
   --------------------------------------------------------------------------- */
.masthead {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1.25rem;
    padding: 1.15rem 1.4rem;
    margin-bottom: 1.75rem;
    border: 1px solid var(--band-line);
    border-radius: var(--radius-lg);
    background:
        radial-gradient(700px 220px at 18% -40%, rgba(0, 158, 247, 0.20), transparent 62%),
        linear-gradient(180deg, var(--band-from) 0%, var(--band-to) 100%);
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.24);
}

/* Intrinsic size attributes are on the <img>, so the band does not reflow
   while the logo decodes. */
.brand-logo {
    display: block;
    width: 160px;
    height: 40px;
    flex: none;
}

.masthead h1 {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--band-muted);
}

h2 { font-size: 1rem; font-weight: 620; margin: 0; }
h3 { font-size: 1rem; font-weight: 620; margin: 0 0 0.4rem; }

.banner {
    border: 1px solid var(--line);
    border-left-width: 4px;
    border-radius: var(--radius);
    padding: 1rem 1.15rem;
    margin-bottom: 1.75rem;
    background: var(--panel);
}

.banner-text { margin: 0; font-size: 1.1rem; font-weight: 600; }

.banner.ok      { border-left-color: var(--ok); }
.banner.warn    { border-left-color: var(--warn); }
.banner.bad     { border-left-color: var(--bad); }
.banner.maint   { border-left-color: var(--maint); }
.banner.unknown { border-left-color: var(--unknown); }

.component {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 1rem 1.15rem;
    margin-bottom: 0.85rem;
    background: var(--panel);
}

.component-head {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: space-between;
    align-items: flex-start;
}

.component-desc { margin: 0.2rem 0 0; color: var(--muted); font-size: 0.875rem; }

.component-state { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }

.pill {
    display: inline-block;
    font-size: 0.78rem;
    font-weight: 600;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    border: 1px solid currentColor;
    white-space: nowrap;
}

.pill.ok      { color: var(--ok); }
.pill.warn    { color: var(--warn); }
.pill.bad     { color: var(--bad); }
.pill.maint   { color: var(--maint); }
.pill.unknown { color: var(--unknown); }

/* ---------------------------------------------------------------------------
   THE 90-DAY STRIP.

   Bars shrink to fit rather than overflowing, so the page never scrolls
   sideways on a phone.

   A DAY IS NOW PART-FILLED (2026-09-25). The cell's base is the healthy
   colour and a cap is drawn from the top in the disruption colour, sized to
   how much of the day was bad. That makes severity legible through HEIGHT as
   well as hue, which is what keeps the strip readable for someone who cannot
   separate the hues at all — including someone who never finds the toggle
   under it. It is also simply more truthful: before this, "something happened
   today" and "nothing worked for two days" were the same picture.

   The cap's height comes from ONE OF 21 CLASSES rather than an inline style,
   because the CSP is style-src 'self' with no unsafe-inline and a bar is not
   worth weakening that for. Five-point steps are about a pixel on a 24px bar.
   --------------------------------------------------------------------------- */
.strip {
    display: flex;
    gap: 1px;
    margin-top: 0.9rem;
    height: 30px;
}

.day {
    position: relative;
    display: block;
    flex: 1 1 0;
    min-width: 1px;
    border-radius: 1px;
    background: var(--unknown);
    overflow: hidden;
}

/* A recorded day is a LINK into its own hourly panel, revealed by :target.
   It must not look like body copy. */
a.day { text-decoration: none; -webkit-tap-highlight-color: transparent; }

a.day:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
    z-index: 1;
}

/* Hover and keyboard focus lift the cell, so a reader can see which day they
   are about to open in a row of ninety. */
a.day:hover { filter: brightness(1.25); }

/* The BASE is what the day was when nothing was wrong with it. The disruption
   and the maintenance are drawn ON it, in proportion, from opposite edges. */
.day.ok      { background: var(--ok); }
.day.partial { background: var(--ok); }
.day.major   { background: var(--ok); }
.day.maint   { background: var(--ok); }
.day.unknown { background: var(--unknown); opacity: 0.35; }

/* THE DISRUPTION CAP, drawn from the top down. */
.day-bad {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 0;
}

.day.partial .day-bad { background: var(--partial); }
.day.major .day-bad   { background: var(--major); }

/* PLANNED MAINTENANCE, drawn from the BOTTOM and in proportion.
   A fifteen-minute deploy — the hard cap on a deploy window, and the
   commonest kind there is — used to paint a whole day blue, which is the same
   yes/no question Brad objected to wearing a different colour. Anchored to the
   opposite edge from the disruption cap so a day that held both shows both. */
.day-maint {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 0;
    background: var(--maint);
}

/* PATTERN, NOT ONLY HUE. A hatch over the disruption cap so that a fully-down
   day — which is a solid bar of one colour, with no height difference left to
   read — is still distinguishable from a fully-healthy one in greyscale and
   under any form of colour blindness. Three-pixel pitch, so it registers even
   on a cell three pixels wide. */
.day.partial .day-bad,
.day.major .day-bad {
    background-image: repeating-linear-gradient(
        45deg,
        rgba(0, 0, 0, 0.28) 0, rgba(0, 0, 0, 0.28) 1px,
        transparent 1px, transparent 3px);
}

/* A day nobody recorded is DOTTED as well as pale. */
.day.unknown {
    background-image: repeating-linear-gradient(
        90deg,
        rgba(0, 0, 0, 0.25) 0, rgba(0, 0, 0, 0.25) 1px,
        transparent 1px, transparent 3px);
}

/* Planned maintenance is STRIPED, horizontally — a different axis from the
   disruption hatch, so the two cannot be confused with each other. */
.day-maint,
.hour.maint,
.swatch.maint {
    background-image: repeating-linear-gradient(
        0deg,
        rgba(255, 255, 255, 0.45) 0, rgba(255, 255, 255, 0.45) 1px,
        transparent 1px, transparent 3px);
}

.day.fill-0 .day-bad { height: 0; }
.day.fill-5 .day-bad { height: 5%; min-height: 3px; }
.day.fill-10 .day-bad { height: 10%; min-height: 3px; }
.day.fill-15 .day-bad { height: 15%; min-height: 3px; }
.day.fill-20 .day-bad { height: 20%; min-height: 3px; }
.day.fill-25 .day-bad { height: 25%; min-height: 3px; }
.day.fill-30 .day-bad { height: 30%; min-height: 3px; }
.day.fill-35 .day-bad { height: 35%; min-height: 3px; }
.day.fill-40 .day-bad { height: 40%; min-height: 3px; }
.day.fill-45 .day-bad { height: 45%; min-height: 3px; }
.day.fill-50 .day-bad { height: 50%; min-height: 3px; }
.day.fill-55 .day-bad { height: 55%; min-height: 3px; }
.day.fill-60 .day-bad { height: 60%; min-height: 3px; }
.day.fill-65 .day-bad { height: 65%; min-height: 3px; }
.day.fill-70 .day-bad { height: 70%; min-height: 3px; }
.day.fill-75 .day-bad { height: 75%; min-height: 3px; }
.day.fill-80 .day-bad { height: 80%; min-height: 3px; }
.day.fill-85 .day-bad { height: 85%; min-height: 3px; }
.day.fill-90 .day-bad { height: 90%; min-height: 3px; }
.day.fill-95 .day-bad { height: 95%; min-height: 3px; }
.day.fill-100 .day-bad { height: 100%; min-height: 3px; }

.day.maint-0 .day-maint { height: 0; }
.day.maint-5 .day-maint { height: 5%; min-height: 3px; }
.day.maint-10 .day-maint { height: 10%; min-height: 3px; }
.day.maint-15 .day-maint { height: 15%; min-height: 3px; }
.day.maint-20 .day-maint { height: 20%; min-height: 3px; }
.day.maint-25 .day-maint { height: 25%; min-height: 3px; }
.day.maint-30 .day-maint { height: 30%; min-height: 3px; }
.day.maint-35 .day-maint { height: 35%; min-height: 3px; }
.day.maint-40 .day-maint { height: 40%; min-height: 3px; }
.day.maint-45 .day-maint { height: 45%; min-height: 3px; }
.day.maint-50 .day-maint { height: 50%; min-height: 3px; }
.day.maint-55 .day-maint { height: 55%; min-height: 3px; }
.day.maint-60 .day-maint { height: 60%; min-height: 3px; }
.day.maint-65 .day-maint { height: 65%; min-height: 3px; }
.day.maint-70 .day-maint { height: 70%; min-height: 3px; }
.day.maint-75 .day-maint { height: 75%; min-height: 3px; }
.day.maint-80 .day-maint { height: 80%; min-height: 3px; }
.day.maint-85 .day-maint { height: 85%; min-height: 3px; }
.day.maint-90 .day-maint { height: 90%; min-height: 3px; }
.day.maint-95 .day-maint { height: 95%; min-height: 3px; }
.day.maint-100 .day-maint { height: 100%; min-height: 3px; }

/* Where the "skip the timeline" link lands. */
.strip-anchor { display: block; height: 0; }

/* Visually hidden until focused. It costs a sighted reader nothing and saves a
   keyboard reader ninety tab stops per component. */
.skip-strip {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.skip-strip:focus {
    position: static;
    width: auto;
    height: auto;
    margin: 0 0 0.35rem;
    clip: auto;
    display: inline-block;
    font-size: 0.78rem;
    color: var(--brand);
}

.strip-legend {
    display: flex;
    justify-content: space-between;
    font-size: 0.75rem;
    color: var(--muted);
    margin-top: 0.35rem;
}

.strip-legend .uptime { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   THE HOURLY DRILL-DOWN — Brad's 24 segments, at a scale where they can be
   read.

   Hidden, and shown by :target — the day cell links to its own panel and the
   fragment does the work. No JavaScript, so it works with script blocked; it
   is keyboard-operable for nothing; and the CSP does not change. Only one
   panel can be open at a time, which is what a reader wants anyway.

   IT SITS BELOW THE STRIP, not inside it. Twenty-four segments inside one
   day's three pixels would be sub-pixel and unreadable, which is exactly why
   the 24 segments are not on the strip itself.
   --------------------------------------------------------------------------- */
.hour-panel { display: none; }

.hour-panel:target {
    display: block;
    margin-top: 0.75rem;
    padding: 0.75rem 0.85rem 0.6rem;
    border: 1px solid var(--line);
    border-left: 3px solid var(--brand);
    border-radius: var(--radius);
    background: var(--bg-2);
}

.hour-panel-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.75rem;
    margin: 0 0 0.5rem;
    font-size: 0.8rem;
    font-weight: 600;
}

.hour-close { color: var(--brand); font-weight: 500; text-decoration: none; }
.hour-close:hover { text-decoration: underline; }

.hours {
    display: flex;
    gap: 2px;
    height: 34px;
}

.hour {
    flex: 1 1 0;
    min-width: 2px;
    border-radius: 2px;
    background: var(--unknown);
}

.hour.ok      { background: var(--ok); }
.hour.partial { background: var(--partial); }
.hour.major   { background: var(--major); }
.hour.maint   { background: var(--maint); }

/* Same two pattern axes as the strip, at a pitch that reads at this size. */
.hour.partial {
    background-image: repeating-linear-gradient(
        45deg,
        rgba(0, 0, 0, 0.22) 0, rgba(0, 0, 0, 0.22) 2px,
        transparent 2px, transparent 6px);
}

.hour.major {
    background-image: repeating-linear-gradient(
        45deg,
        rgba(0, 0, 0, 0.34) 0, rgba(0, 0, 0, 0.34) 2px,
        transparent 2px, transparent 4px);
}

/* No record, and not-yet, are both drawn as absence and neither as green. The
   future is fainter still: it is not a gap in the record, it has not happened.
   Which one it is, is in the tooltip. */
.hour.unknown,
.hour.future {
    background: var(--unknown);
    background-image: repeating-linear-gradient(
        45deg,
        rgba(0, 0, 0, 0.22) 0, rgba(0, 0, 0, 0.22) 1px,
        transparent 1px, transparent 4px);
    opacity: 0.4;
}

.hour.future { opacity: 0.18; }

.hours-scale {
    display: flex;
    justify-content: space-between;
    margin: 0.3rem 0 0;
    font-size: 0.68rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

/* The same thing in words — the only form a screen reader can use, and the
   fastest check for a sighted reader that they read the colours right. */
.hours-text {
    margin: 0.45rem 0 0;
    font-size: 0.75rem;
    color: var(--muted);
}

/* ---------------------------------------------------------------------------
   THE KEY, and the colour-blind toggle beside it.

   The key is where a reader goes when a colour is not telling them anything,
   so it is where the toggle belongs. The toggle is TEXT and carries no colour
   of its own — an icon or a swatch would be the obvious joke, since the person
   who needs it is the person who cannot read a coloured hint.
   --------------------------------------------------------------------------- */
.strip-key-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin: 0.9rem 0 0;
}

.strip-key {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    margin: 0;
    font-size: 0.75rem;
    color: var(--muted);
}

.strip-key .key { display: inline-flex; align-items: center; gap: 0.35rem; }

.swatch {
    display: inline-block;
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 2px;
    background: var(--unknown);
}

.swatch.ok      { background: var(--ok); }
.swatch.partial { background: var(--partial); }
.swatch.major   { background: var(--major); }
.swatch.bad     { background: var(--bad); }
.swatch.maint   { background: var(--maint); }
.swatch.unknown { background: var(--unknown); opacity: 0.35; }

/* The key's swatches carry the same patterns the cells do, or the key would
   explain the colours and not the thing the reader is actually looking at. */
.swatch.partial {
    background-image: repeating-linear-gradient(
        45deg,
        rgba(0, 0, 0, 0.22) 0, rgba(0, 0, 0, 0.22) 1px,
        transparent 1px, transparent 3px);
}

.swatch.major {
    background-image: repeating-linear-gradient(
        45deg,
        rgba(0, 0, 0, 0.34) 0, rgba(0, 0, 0, 0.34) 1px,
        transparent 1px, transparent 2px);
}

.swatch.unknown {
    background-image: repeating-linear-gradient(
        90deg,
        rgba(0, 0, 0, 0.25) 0, rgba(0, 0, 0, 0.25) 1px,
        transparent 1px, transparent 3px);
}

.palette-toggle {
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--panel);
    color: var(--muted);
    font: inherit;
    font-size: 0.72rem;
    padding: 0.28rem 0.7rem;
    cursor: pointer;
    white-space: nowrap;
}

.palette-toggle[hidden] { display: none; }
.palette-toggle:hover { color: var(--ink); border-color: var(--muted); }
.palette-toggle:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.palette-toggle[aria-pressed="true"] { color: var(--ink); border-color: var(--brand); }

.incidents { margin-top: 2.25rem; }
.incidents > h2 { margin-bottom: 0.85rem; }

.incident {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 1rem 1.15rem;
    margin-bottom: 0.85rem;
    background: var(--panel);
}

.incident-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    align-items: center;
    margin: 0 0 0.75rem;
    font-size: 0.8rem;
    color: var(--muted);
}

.update { border-top: 1px solid var(--line); padding-top: 0.7rem; margin-top: 0.7rem; }
.update-meta { margin: 0 0 0.3rem; font-size: 0.8rem; color: var(--muted); display: flex; gap: 0.6rem; }
.update-meta strong { color: var(--ink); }

/* Authored copy is stored as plain text. Newlines are honoured here rather than
   by allowing markup through. */
.incident-body { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }

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

footer {
    margin-top: 2.5rem;
    padding-top: 1.1rem;
    border-top: 1px solid var(--line);
    font-size: 0.82rem;
    color: var(--muted);
}

footer p { margin: 0.3rem 0; }

/* The provenance sentence. Set apart, because it is a caveat on every number
   above it rather than another footer line. */
.provenance {
    border-left: 3px solid var(--line);
    padding-left: 0.7rem;
    margin: 0.65rem 0 !important;
}
footer a { color: var(--brand); text-decoration-color: color-mix(in srgb, var(--brand) 45%, transparent); }

@media (max-width: 30rem) {
    .strip { height: 24px; }
    .component-head { flex-direction: column; }
    .masthead { justify-content: center; text-align: center; }

    /* A THUMB, not a mouse pointer. Ninety cells across a phone is about three
       pixels each, which is fine to READ and hopeless to hit, so the row gets
       taller: the target is the full height of the strip and 30px of height is
       a reachable target even where the width is not. The hours are the thing
       being tapped THROUGH to, and they get more height still — 24 segments
       across a 320px screen is about 11px each, which is a comfortable thumb
       target in the axis that matters. */
    .strip { height: 30px; }
    .hours { height: 44px; gap: 1px; }
    .hour-panel:target { padding: 0.7rem 0.6rem 0.55rem; }
    .hours-scale { font-size: 0.62rem; }
    .strip-key-row { flex-direction: column; align-items: flex-start; }
    .strip-key { gap: 0.2rem 0.75rem; }
}

/* ------------------------------------------------------------------
   THE REFRESH CONTROL (2026-09-25)

   Lives in the dark masthead, right-aligned, sharing the strip with the
   word "Status" — the space Brad circled. Muted to match the band: it is
   a utility, not a call to action, and it must not compete with the
   banner beneath it, which is the thing a reader came for.

   Hidden until the script shows it. Without JavaScript the meta refresh
   in the head does the work and no dead buttons are drawn.
   ------------------------------------------------------------------ */
.refresh {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
    margin-right: 14px;
}

.refresh[hidden] { display: none; }

.refresh-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 9px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.06);
    color: #b6bcd4;
    font: inherit;
    font-size: 0.82rem;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    cursor: pointer;
}

.refresh-btn:hover { background: rgba(255, 255, 255, 0.12); color: #e6e9f5; }
.refresh-btn:focus-visible { outline: 2px solid #4a7dff; outline-offset: 2px; }

/* The pause button carries the accent, as in the design Brad supplied. */
#refresh-pause { color: #7b93ff; }

.icon-pause,
.icon-play,
.icon-refresh { display: inline-block; width: 13px; height: 13px; }

.icon-pause {
    border-left: 4px solid currentColor;
    border-right: 4px solid currentColor;
    width: 12px;
    box-sizing: border-box;
}

.icon-play {
    display: none;
    width: 0;
    height: 0;
    border-left: 9px solid currentColor;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
}

/* Paused: the pause bars become a play triangle, so the button says what it
   will DO rather than what state it is in. */
.refresh[data-paused="true"] .icon-pause { display: none; }
.refresh[data-paused="true"] .icon-play { display: inline-block; }

/* Circular arrows, drawn in CSS so the page still loads no extra asset. */
.icon-refresh {
    position: relative;
    width: 13px;
    height: 13px;
    border: 2px solid currentColor;
    border-radius: 50%;
    border-top-color: transparent;
}

.icon-refresh::after {
    content: "";
    position: absolute;
    top: -2px;
    right: -1px;
    border-left: 4px solid currentColor;
    border-top: 3px solid transparent;
    border-bottom: 3px solid transparent;
}

/* The page has stopped learning and says so. Amber, not red: the services
   may well be fine — what is unknown is whether they still are. */
.stale {
    color: #8a6d1f;
    background: #fdf6e3;
    border-left: 3px solid #d9a441;
    padding: 8px 12px;
    border-radius: 4px;
}

/* Declared maintenance, above the components: a reader who cannot sign in
   needs the explanation before they read a red pill, not after. */
.maintenance-notices { display: grid; gap: 0.75rem; margin-bottom: 1.25rem; }

.maintenance-notice {
    border: 1px solid var(--line);
    border-left: 3px solid var(--maint);
    border-radius: var(--radius-lg);
    background: var(--card);
    padding: 0.9rem 1.1rem;
}

.maintenance-head { display: flex; align-items: center; gap: 0.6rem; margin: 0 0 0.35rem; }
.maintenance-scope { color: var(--muted); font-size: 0.85rem; }
.maintenance-when { color: var(--muted); font-size: 0.85rem; margin: 0 0 0.4rem; }
