/* ==========================================================================
 * style.css — the Graffiti status page.
 * --------------------------------------------------------------------------
 * §1–§4 are MIRRORED BY HAND from Graffiti's dashboard/static/css/graffiti.css.
 * There is no build step and no shared package between the two repos, so the
 * tokens are copied rather than imported. If the brand changes there, re-copy
 * §1 and §2 here — nothing below §3 hardcodes a colour, so that is the whole
 * job. §7 onward is the only part unique to this page.
 *
 * THE FIVE RULES (from Graffiti's CLAUDE.md > Branding — not negotiable):
 *   1. Dark text on brand, never white. Brand fills carry --brand-ink.
 *   2. Pink never carries state alone. Decoration and emphasis only.
 *   3. Severity separates by treatment, not hue.
 *   4. Brand colour is not status colour. "Healthy" is --live, always.
 *      This page is entirely about status, so the rule does most of the work
 *      here: no monitor row, dot, bar or banner is ever brand-coloured.
 *   5. A brand FILL and brand TEXT are different tokens.
 * ========================================================================== */

/* ==========================================================================
 * §1  RAW PALETTE — the physical cans. Referenced only by §2.
 * ========================================================================== */

:root {
  /* Safety Orange — the brand */
  --o-300: #FFA37D;
  --o-400: #FF7A47;
  --o-500: #FF5A1F;
  --o-600: #E84711;
  --o-700: #AE3208;

  /* Fluoro Pink — the second can */
  --p-300: #FF8FC4;
  --p-400: #FF5FAD;
  --p-500: #FF2D95;
  --p-600: #E5117C;
  --p-700: #A80B59;

  /* Ink that sits ON a bright fill */
  --ink-on-brand: #1A0600;
  --ink-on-pink:  #2B0014;

  /* Neutral ground. Deliberately hue-neutral. */
  --n-0:   #FFFFFF;
  --n-50:  #F4F4F4;
  --n-100: #E8E8E8;
  --n-200: #DCDCDC;
  --n-300: #C4C4C4;
  --n-400: #A8A8A8;
  --n-500: #888888;
  --n-600: #656565;
  --n-700: #525252;
  --n-750: #313131;
  --n-800: #1F1F1F;
  --n-850: #161616;
  --n-900: #131313;
  --n-950: #0A0A0A;
  --n-1000: #050505;

  /* Status. Emerald survives with exactly one job. */
  --status-live:      #10B981;
  --status-live-soft: #34D399;
  --status-live-dark: #047354;

  /* Warning — pure yellow, remapped off amber. */
  --y-400: #FACC15;
  --y-500: #EAB308;
  --y-600: #CA8A04;
  --y-700: #915806;

  /* Danger */
  --r-400: #F87171;
  --r-500: #EF4444;
  --r-600: #DC2626;
  --r-700: #B91C1C;

  /* Discord's own blurple. Exempt from the palette. */
  --discord:       #5865F2;
  --discord-hover: #4752C4;
}

/* ==========================================================================
 * §2  SEMANTIC TOKENS + THEMES
 * --------------------------------------------------------------------------
 * Three states, and the order below is load-bearing:
 *   bare :root           -> DARK, the default.
 *   prefers-color-scheme -> light, but only when no explicit choice is stored.
 *   [data-theme=...]     -> an explicit choice, and it wins in both directions.
 * ========================================================================== */

:root {
  color-scheme: dark;

  --bg:          var(--n-950);
  --bg-raised:   var(--n-900);
  --bg-sunken:   var(--n-1000);
  --bg-inset:    var(--n-850);
  --bg-hover:    var(--n-800);

  --ink:         #EDEDED;
  --ink-muted:   var(--n-400);
  --ink-faint:   var(--n-500);
  --ink-invert:  var(--n-950);

  --line:        var(--n-800);
  --line-strong: var(--n-750);

  --brand:       var(--o-500);
  --brand-hover: var(--o-400);
  --brand-ink:   var(--ink-on-brand);
  --brand-text:  var(--o-400);
  --brand-wash:  rgba(255, 90, 31, 0.12);
  --brand-edge:  rgba(255, 90, 31, 0.32);

  --pink:        var(--p-500);
  --pink-ink:    var(--ink-on-pink);
  --pink-text:   var(--p-400);
  --pink-wash:   rgba(255, 45, 149, 0.12);

  --live:        var(--status-live-soft);
  --live-wash:   rgba(16, 185, 129, 0.14);
  --live-edge:   rgba(16, 185, 129, 0.30);

  --warn:        var(--y-400);
  --warn-wash:   rgba(250, 204, 21, 0.12);
  --warn-edge:   rgba(250, 204, 21, 0.30);

  --danger:      var(--r-600);
  --danger-text: var(--r-400);
  --danger-ink:  #FFFFFF;
  --danger-wash: rgba(239, 68, 68, 0.12);
  --danger-edge: rgba(239, 68, 68, 0.30);

  --focus:       var(--o-400);
  --selection:   rgba(255, 90, 31, 0.28);

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.55);
  --shadow-2: 0 10px 30px -12px rgba(0, 0, 0, 0.80);
  --shadow-3: 0 24px 60px -20px rgba(0, 0, 0, 0.90);

  --grain-opacity: 0.018;
  --grain-blend: overlay;

  /* Status-page additions. A day with no data is ground, not a state. */
  --tick-none: var(--line-strong);
}

/* Light theme, factored out so it is defined once and applied twice. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;

    --bg:          var(--n-50);
    --bg-raised:   var(--n-0);
    --bg-sunken:   var(--n-100);
    --bg-inset:    #EFEFEF;
    --bg-hover:    #E4E4E4;

    --ink:         #111111;
    --ink-muted:   var(--n-700);
    --ink-faint:   var(--n-600);
    --ink-invert:  var(--n-0);

    --line:        var(--n-200);
    --line-strong: var(--n-300);

    --brand-hover: var(--o-600);
    --brand-text:  var(--o-700);
    --brand-wash:  rgba(255, 90, 31, 0.06);
    --brand-edge:  rgba(194, 56, 11, 0.30);

    --pink-text:   var(--p-700);
    --pink-wash:   rgba(255, 45, 149, 0.09);

    --live:        var(--status-live-dark);
    --live-wash:   rgba(4, 120, 87, 0.10);
    --live-edge:   rgba(4, 120, 87, 0.26);

    --warn:        var(--y-700);
    --warn-wash:   rgba(161, 98, 7, 0.10);
    --warn-edge:   rgba(161, 98, 7, 0.26);

    --danger:      var(--r-600);
    --danger-text: var(--r-700);
    --danger-wash: rgba(220, 38, 38, 0.09);
    --danger-edge: rgba(220, 38, 38, 0.26);

    --focus:       var(--o-600);
    --selection:   rgba(255, 90, 31, 0.24);

    --shadow-1: 0 1px 2px rgba(16, 16, 16, 0.08);
    --shadow-2: 0 10px 30px -14px rgba(16, 16, 16, 0.22);
    --shadow-3: 0 24px 60px -22px rgba(16, 16, 16, 0.28);

    --grain-opacity: 0.024;
    --grain-blend: multiply;

    --tick-none: var(--n-300);
  }
}

:root[data-theme="light"] {
  color-scheme: light;

  --bg:          var(--n-50);
  --bg-raised:   var(--n-0);
  --bg-sunken:   var(--n-100);
  --bg-inset:    #EFEFEF;
  --bg-hover:    #E4E4E4;

  --ink:         #111111;
  --ink-muted:   var(--n-700);
  --ink-faint:   var(--n-600);
  --ink-invert:  var(--n-0);

  --line:        var(--n-200);
  --line-strong: var(--n-300);

  --brand-hover: var(--o-600);
  --brand-text:  var(--o-700);
  --brand-wash:  rgba(255, 90, 31, 0.06);
  --brand-edge:  rgba(194, 56, 11, 0.30);

  --pink-text:   var(--p-700);
  --pink-wash:   rgba(255, 45, 149, 0.09);

  --live:        var(--status-live-dark);
  --live-wash:   rgba(4, 120, 87, 0.10);
  --live-edge:   rgba(4, 120, 87, 0.26);

  --warn:        var(--y-700);
  --warn-wash:   rgba(161, 98, 7, 0.10);
  --warn-edge:   rgba(161, 98, 7, 0.26);

  --danger:      var(--r-600);
  --danger-text: var(--r-700);
  --danger-wash: rgba(220, 38, 38, 0.09);
  --danger-edge: rgba(220, 38, 38, 0.26);

  --focus:       var(--o-600);
  --selection:   rgba(255, 90, 31, 0.24);

  --shadow-1: 0 1px 2px rgba(16, 16, 16, 0.08);
  --shadow-2: 0 10px 30px -14px rgba(16, 16, 16, 0.22);
  --shadow-3: 0 24px 60px -22px rgba(16, 16, 16, 0.28);

  --grain-opacity: 0.024;
  --grain-blend: multiply;

  --tick-none: var(--n-300);
}

/* ==========================================================================
 * §3  TYPE, SPACE, MOTION
 * ========================================================================== */

:root {
  --font-display: 'Archivo', 'Inter', ui-sans-serif, system-ui, sans-serif;
  --font-body: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-mono: ui-monospace, 'SFMono-Regular', 'JetBrains Mono', Menlo, monospace;

  --text-xs:  clamp(0.75rem,  0.735rem + 0.07vw, 0.8125rem);
  --text-sm:  clamp(0.8125rem, 0.79rem + 0.11vw, 0.875rem);
  --text-base: clamp(0.9375rem, 0.91rem + 0.14vw, 1rem);
  --text-md:  clamp(1.0625rem, 1.01rem + 0.27vw, 1.1875rem);
  --text-lg:  clamp(1.1875rem, 1.10rem + 0.42vw, 1.4375rem);
  --text-xl:  clamp(1.4375rem, 1.28rem + 0.78vw, 1.9375rem);
  --text-2xl: clamp(1.75rem,  1.47rem + 1.40vw, 2.75rem);
  --text-3xl: clamp(2.25rem,  1.70rem + 2.75vw, 4rem);
  --text-4xl: clamp(2.75rem,  1.80rem + 4.75vw, 5.75rem);

  --sp-1: 0.25rem;  --sp-2: 0.5rem;   --sp-3: 0.75rem;  --sp-4: 1rem;
  --sp-5: 1.5rem;   --sp-6: 2rem;     --sp-7: 2.5rem;   --sp-8: 3rem;
  --sp-9: 4rem;     --sp-10: 5rem;    --sp-11: 6.5rem;  --sp-12: 8rem;

  --r-xs: 3px;  --r-sm: 5px;  --r-md: 8px;  --r-lg: 14px;  --r-pill: 999px;

  --wrap: 74rem;
  --wrap-narrow: 44rem;
  --wrap-wide: 88rem;
  --measure: 68ch;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 140ms;
  --dur: 260ms;
  --dur-slow: 560ms;

  --nav-h: 3.75rem;
}

/* ==========================================================================
 * §4  RESET + BASE
 * ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + var(--sp-5));
  /* The canvas colour comes from the root element. Colouring only <body>
     leaves the browser's own white canvas showing until first paint. */
  background-color: var(--bg);
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

::selection { background: var(--selection); color: var(--ink); }

img, svg, video, canvas { display: block; max-width: 100%; height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }

p { text-wrap: pretty; }

a { color: var(--brand-text); text-decoration-thickness: 1px; text-underline-offset: 0.18em; }
a:hover { color: var(--brand); }

code, pre, kbd, samp { font-family: var(--font-mono); font-size: 0.92em; }

hr { border: 0; border-top: 1px solid var(--line); }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}
:focus:not(:focus-visible) { outline: none; }

* { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: var(--r-pill); }
*::-webkit-scrollbar-thumb:hover { background: var(--ink-faint); }

[hidden] { display: none !important; }

/* ==========================================================================
 * §5  UTILITIES — a deliberately tiny set. Not a utility framework.
 * ========================================================================== */

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; top: 0; left: 0; z-index: 100;
  transform: translateY(-120%);
  background: var(--brand); color: var(--brand-ink);
  font-weight: 700; padding: var(--sp-3) var(--sp-5);
  border-radius: 0 0 var(--r-md) 0;
  transition: transform var(--dur-fast) var(--ease);
}
.skip-link:focus { transform: translateY(0); color: var(--brand-ink); }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--sp-5); }
.wrap-narrow { max-width: var(--wrap-narrow); }
@media (min-width: 48rem) { .wrap { padding-inline: var(--sp-6); } }

.measure { max-width: var(--measure); }
.tabular { font-variant-numeric: tabular-nums; }
.no-wrap { white-space: nowrap; }

.section { padding-block: var(--sp-9); }
@media (min-width: 48rem) { .section { padding-block: var(--sp-11); } }
.section--tight { padding-block: var(--sp-8); }
.section--sunken { background: var(--bg-sunken); }
.section--edged { border-block: 1px solid var(--line); }

.stack > * + * { margin-top: var(--sp-4); }
.stack-sm > * + * { margin-top: var(--sp-2); }
.stack-lg > * + * { margin-top: var(--sp-6); }

.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.cluster--between { justify-content: space-between; }

.text-muted { color: var(--ink-muted); }
.text-faint { color: var(--ink-faint); }
.text-brand { color: var(--brand-text); }
.text-live { color: var(--live); }
.text-warn { color: var(--warn); }
.text-danger { color: var(--danger-text); }

/* ==========================================================================
 * §6  BRAND TREATMENTS
 * ========================================================================== */

.mark-fill {
  background: linear-gradient(135deg, var(--o-400) 0%, var(--o-500) 38%, var(--p-500) 100%);
  color: var(--ink-on-brand);
}

/* Sticker slap — a mark applied by hand, not a centred favicon. */
.slap { transform: rotate(-4deg); }
.slap-hover { transition: transform var(--dur) var(--ease); }
a:hover > .slap-hover { transform: rotate(-4deg) scale(1.06); }

/* Marker swipe behind a headline word. Replaces gradient text. */
.swipe {
  display: inline-block;
  background: linear-gradient(100deg, var(--o-500) 0%, var(--p-500) 100%);
  color: var(--ink-on-brand);
  padding: 0 0.12em;
  transform: rotate(-1.4deg) skewX(-5deg);
}
.swipe > * { display: inline-block; transform: skewX(5deg); }

/* Sticker / tape label — a physical mark, used for eyebrows and badges. */
.sticker {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.4em 0.8em;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  background: var(--bg-raised);
  color: var(--ink-muted);
}
.sticker--wash { background: var(--brand-wash); color: var(--brand-text); border-color: var(--brand-edge); }
.sticker--live { background: var(--live-wash); color: var(--live); border-color: var(--live-edge); }
.sticker--warn { background: var(--warn-wash); color: var(--warn); border-color: var(--warn-edge); }
.sticker--danger { background: var(--danger-wash); color: var(--danger-text); border-color: var(--danger-edge); }
.sticker--tilt { transform: rotate(-2deg); }

/* Grain — a fine paper tooth over a section. ~400 bytes, no image request. */
.grain { position: relative; isolation: isolate; }
.grain::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: var(--grain-blend);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.9' numOctaves='1' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}

.rule-mark {
  height: 3px;
  width: 3.5rem;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--o-500), var(--p-500));
}

/* ==========================================================================
 * §7  BUTTONS
 * ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 650;
  line-height: 1.2;
  padding: 0.72rem 1.15rem;
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: none;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
.btn:disabled:active, .btn[aria-disabled="true"]:active { transform: none; }
.btn svg { width: 1.05em; height: 1.05em; flex: none; }

/* Rule 1: dark ink on brand, never white. */
.btn--brand { background: var(--brand); color: var(--brand-ink); }
.btn--brand:hover { background: var(--brand-hover); color: var(--brand-ink); }

.btn--ghost { border-color: var(--line-strong); color: var(--ink); }
.btn--ghost:hover { background: var(--bg-inset); border-color: var(--ink-faint); color: var(--ink); }

.btn--quiet { color: var(--ink-muted); }
.btn--quiet:hover { background: var(--bg-inset); color: var(--ink); }

.btn--lg { font-size: var(--text-md); padding: 0.95rem 1.6rem; border-radius: var(--r-lg); }
.btn--sm { font-size: var(--text-xs); padding: 0.45rem 0.75rem; }
.btn--icon { padding: 0.55rem; border-radius: var(--r-md); }

/* ==========================================================================
 * §8  SURFACES
 * ========================================================================== */

.card {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
}
.card--inset { background: var(--bg-inset); }
.card--pad-sm { padding: var(--sp-4); }

.panel {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Wraps rather than clips: the panel is `overflow: hidden`, so a control
     that outgrows the header row (the six-button period switcher, on a
     phone) would lose its last button silently. */
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
  background: var(--bg-inset);
}
.panel__title {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 800;
  letter-spacing: -0.01em;
}
.panel__body { padding: var(--sp-5); }
.panel__body--flush { padding: 0; }

.status-dot {
  /* inline-block, not inline: an inline box ignores width/height and paints
     as a thin coloured rectangle outside a flex container. */
  display: inline-block;
  vertical-align: middle;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: var(--r-pill);
  background: var(--ink-faint);
  flex: none;
}
.status-dot--live { background: var(--live); box-shadow: 0 0 0 3px var(--live-wash); }
.status-dot--warn { background: var(--warn); box-shadow: 0 0 0 3px var(--warn-wash); }
.status-dot--danger { background: var(--danger); box-shadow: 0 0 0 3px var(--danger-wash); }
.status-dot--lg { width: 0.7rem; height: 0.7rem; }

/* ==========================================================================
 * §9  SITE CHROME — nav + footer
 * ========================================================================== */

.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
@supports not (backdrop-filter: blur(1px)) { .nav { background: var(--bg); } }

.nav__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: var(--nav-h);
}

.nav__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  text-decoration: none;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-right: auto;
}
.nav__glyph {
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: var(--r-sm);
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 1.05rem;
  box-shadow: var(--shadow-1);
  flex: none;
}
/* The wordmark carries "Status" as a quiet suffix, so the page identifies
   itself without a second logo. */
.nav__suffix { color: var(--ink-faint); font-weight: 700; }

.nav__links { display: none; align-items: center; gap: var(--sp-1); }
@media (min-width: 60rem) { .nav__links { display: flex; } }

.nav__link {
  display: inline-block;
  padding: 0.45rem 0.7rem;
  border-radius: var(--r-sm);
  font-size: var(--text-sm);
  font-weight: 550;
  color: var(--ink-muted);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.nav__link:hover { color: var(--ink); background: var(--bg-inset); }
.nav__link[aria-current="page"] { color: var(--ink); }
.nav__link[aria-current="page"]::after {
  content: "";
  display: block;
  height: 2px;
  margin-top: 3px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--o-500), var(--p-500));
}

.nav__actions { display: flex; align-items: center; gap: var(--sp-2); }
.nav__cta { display: none; }
@media (min-width: 30rem) { .nav__cta { display: inline-flex; } }

.nav__toggle { display: inline-flex; }
@media (min-width: 60rem) { .nav__toggle { display: none; } }

.nav__mobile {
  display: none;
  border-top: 1px solid var(--line);
  background: var(--bg);
  padding-block: var(--sp-3);
}
.nav__mobile[data-open="true"] { display: block; }
@media (min-width: 60rem) { .nav__mobile { display: none !important; } }
.nav__mobile .nav__link {
  display: block;
  padding: var(--sp-3) var(--sp-2);
  font-size: var(--text-md);
  font-weight: 600;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
}
.nav__mobile .nav__link:last-of-type { border-bottom: 0; }

/* Theme toggle — one button, two icons, CSS decides which is visible. */
.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: none;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.theme-toggle:hover { color: var(--ink); border-color: var(--line-strong); }
.theme-toggle svg { grid-area: 1 / 1; width: 1.05rem; height: 1.05rem; }
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .theme-toggle .icon-sun { display: block; }
  :root:not([data-theme="dark"]) .theme-toggle .icon-moon { display: none; }
}
:root[data-theme="light"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: block; }

/* Footer */
.footer {
  margin-top: auto;
  border-top: 1px solid var(--line);
  background: var(--bg-sunken);
  padding-block: var(--sp-8) var(--sp-6);
}
.footer__grid {
  display: grid;
  gap: var(--sp-7);
  grid-template-columns: 1fr;
}
@media (min-width: 40rem) { .footer__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 64rem) { .footer__grid { grid-template-columns: 2fr 1fr 1fr 1fr; gap: var(--sp-6); } }

.footer__col-title {
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: var(--sp-3);
}
.footer__link {
  display: block;
  padding-block: 0.3rem;
  font-size: var(--text-sm);
  color: var(--ink-muted);
  text-decoration: none;
}
.footer__link:hover { color: var(--brand-text); }
.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
  font-size: var(--text-xs);
  color: var(--ink-faint);
}

/* ==========================================================================
 * §10  STAT STRIP
 * ========================================================================== */

.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
@media (min-width: 48rem) { .stats { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* Five stats divide into two columns and into five, but never into three or
   four without stranding an empty cell. So: two columns with the fifth
   spanning the pair, straight to five once there is room. */
.stats--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.stats--5 .stat:nth-child(5) { grid-column: span 2; }
@media (min-width: 48rem) {
  .stats--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .stats--5 .stat:nth-child(5) { grid-column: auto; }
}

.stat { background: var(--bg-raised); padding: var(--sp-5) var(--sp-4); text-align: center; }
.stat__value {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.stat__label {
  display: block;
  margin-top: var(--sp-2);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
}

/* ==========================================================================
 * §11  STATUS BANNER — the one thing a visitor came for.
 * --------------------------------------------------------------------------
 * Rule 4 governs this whole section: brand colour is never status colour.
 * Healthy is --live, trouble is --warn / --danger, and a state we cannot
 * determine is neutral ink. Orange appears nowhere below.
 * ========================================================================== */

.banner {
  border: 1px solid var(--line);
  border-left: 4px solid var(--ink-faint);
  border-radius: var(--r-lg);
  background: var(--bg-raised);
  padding: var(--sp-6) var(--sp-5);
  box-shadow: var(--shadow-2);
}
@media (min-width: 48rem) { .banner { padding: var(--sp-7) var(--sp-6); } }

.banner[data-state="operational"] { border-left-color: var(--live); background: linear-gradient(90deg, var(--live-wash), transparent 42%), var(--bg-raised); }
.banner[data-state="degraded"]    { border-left-color: var(--warn); background: linear-gradient(90deg, var(--warn-wash), transparent 42%), var(--bg-raised); }
.banner[data-state="partial_outage"],
.banner[data-state="major_outage"] { border-left-color: var(--danger); background: linear-gradient(90deg, var(--danger-wash), transparent 42%), var(--bg-raised); }
.banner[data-state="maintenance"] { border-left-color: var(--ink-faint); }
.banner[data-state="unknown"],
.banner[data-state="monitoring_unavailable"] { border-left-color: var(--line-strong); }

.banner__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 900;
  letter-spacing: -0.03em;
  line-height: 1.04;
}
.banner__note { margin-top: var(--sp-3); color: var(--ink-muted); font-size: var(--text-md); max-width: 56ch; }
.banner__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  margin-top: var(--sp-5);
  font-size: var(--text-xs);
  color: var(--ink-faint);
}
.banner__meta .sep { opacity: 0.45; }

/* The pulse marks a live reading, and only a live one. It is suppressed the
   moment the data goes stale, so a frozen page never looks like a fresh one. */
.pulse { position: relative; display: inline-flex; }
.pulse::before {
  content: "";
  position: absolute;
  inset: -0.25rem;
  border-radius: var(--r-pill);
  background: currentColor;
  opacity: 0.4;
  animation: pulse 2.4s var(--ease) infinite;
}
@keyframes pulse {
  0%   { transform: scale(0.6); opacity: 0.45; }
  70%  { transform: scale(1.5); opacity: 0; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* ==========================================================================
 * §12  SERVICE ROWS
 * ========================================================================== */

.svc-list { display: grid; }
.svc {
  display: grid;
  gap: var(--sp-4);
  padding: var(--sp-5);
  border-bottom: 1px solid var(--line);
}
.svc:last-child { border-bottom: 0; }

.svc__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
}
.svc__name {
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 800;
  letter-spacing: -0.01em;
}
.svc__desc { margin-top: 0.15rem; font-size: var(--text-sm); color: var(--ink-muted); }
.svc__state {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--text-sm);
  font-weight: 650;
  white-space: nowrap;
}
.svc__state[data-state="operational"] { color: var(--live); }
.svc__state[data-state="degraded"]    { color: var(--warn); }
.svc__state[data-state="down"]        { color: var(--danger-text); }
.svc__state[data-state="paused"],
.svc__state[data-state="unknown"]     { color: var(--ink-faint); }

/* Uptime figures. Tabular so the decimal points line up down the column. */
.uptimes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3) var(--sp-4);
}
/* Six windows, so the column count has to divide six: 2, then 3, then 6.
   Five columns would leave "All time" stranded on a row of its own. */
@media (min-width: 34rem) { .uptimes { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 60rem) { .uptimes { grid-template-columns: repeat(6, minmax(0, 1fr)); } }

.uptime__value {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.uptime__value[data-unknown="true"] { color: var(--ink-faint); font-weight: 700; }
.uptime__label {
  display: block;
  margin-top: 0.3rem;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ==========================================================================
 * §13  TIMELINE — the uptime history bars.
 * --------------------------------------------------------------------------
 * One element per bucket, flex-sized so the row always fills its container
 * whatever the bucket count. Older buckets are dropped by CSS at narrow
 * widths rather than by re-rendering, so a resize costs nothing.
 * ========================================================================== */

.timeline {
  display: flex;
  gap: 2px;
  height: 2.25rem;
  align-items: stretch;
}
@media (min-width: 48rem) { .timeline { height: 2.6rem; } }

.tick {
  flex: 1 1 0;
  min-width: 0;
  border: 0;
  padding: 0;
  border-radius: 2px;
  background: var(--tick-none);
  cursor: default;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.tick[data-state="operational"] { background: var(--live); }
.tick[data-state="degraded"]    { background: var(--warn); }
.tick[data-state="down"]        { background: var(--danger); }
.tick[data-state="unknown"]     { background: var(--tick-none); }
.tick:hover, .tick:focus-visible { opacity: 0.72; transform: scaleY(1.08); }

/* 90 buckets do not fit on a phone. Hide the oldest instead of shrinking them
   below the point where a single bad day stops being visible. */
@media (max-width: 34rem)   { .timeline[data-buckets="many"] .tick:nth-last-child(n+31) { display: none; } }
@media (min-width: 34.0625rem) and (max-width: 48rem) {
  .timeline[data-buckets="many"] .tick:nth-last-child(n+61) { display: none; }
}

.timeline__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-2);
  font-size: var(--text-xs);
  color: var(--ink-faint);
}
.timeline__rule { flex: 1 1 auto; height: 1px; background: var(--line); }

/* Tooltip. A single shared node moved into place, not one per bucket. */
.tip {
  position: fixed;
  z-index: 60;
  pointer-events: none;
  max-width: 16rem;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-md);
  background: var(--bg-raised);
  color: var(--ink);
  box-shadow: var(--shadow-3);
  font-size: var(--text-xs);
  line-height: 1.45;
  transform: translate(-50%, -100%);
}
.tip__day { font-weight: 700; font-family: var(--font-display); letter-spacing: -0.01em; }
.tip__line { color: var(--ink-muted); font-variant-numeric: tabular-nums; }

/* Segmented period control */
.seg {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--bg-inset);
}
.seg__btn {
  border: 0;
  background: none;
  padding: 0.35rem 0.6rem;
  border-radius: var(--r-sm);
  font-size: var(--text-xs);
  font-weight: 650;
  color: var(--ink-muted);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.seg__btn:hover { color: var(--ink); }
/* Rule 1 again: the selected segment is a brand fill, so it takes brand ink. */
.seg__btn[aria-pressed="true"] { background: var(--brand); color: var(--brand-ink); }

/* Legend */
.legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); font-size: var(--text-xs); color: var(--ink-faint); }
.legend__item { display: inline-flex; align-items: center; gap: var(--sp-2); }
.legend__swatch { width: 0.7rem; height: 0.7rem; border-radius: 2px; background: var(--tick-none); flex: none; }
.legend__swatch[data-state="operational"] { background: var(--live); }
.legend__swatch[data-state="degraded"] { background: var(--warn); }
.legend__swatch[data-state="down"] { background: var(--danger); }

/* ==========================================================================
 * §14  INCIDENTS
 * ========================================================================== */

.incident {
  display: grid;
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
  border-left: 3px solid transparent;
}
.incident:last-child { border-bottom: 0; }
.incident[data-severity="down"] { border-left-color: var(--danger); }
.incident[data-severity="degraded"] { border-left-color: var(--warn); }
.incident[data-status="ongoing"] { background: var(--danger-wash); }
.incident[data-status="ongoing"][data-severity="degraded"] { background: var(--warn-wash); }

.incident__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
}
.incident__title { font-family: var(--font-display); font-weight: 800; font-size: var(--text-base); }
.incident__meta { font-size: var(--text-xs); color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.incident__reason { font-size: var(--text-sm); color: var(--ink-muted); }

/* ==========================================================================
 * §15  LOADING, EMPTY AND ERROR STATES
 * --------------------------------------------------------------------------
 * A status page that cannot reach its own API has to say so plainly — an
 * empty page reads as "everything is fine", which is the one wrong answer.
 * ========================================================================== */

.notice {
  display: grid;
  gap: var(--sp-3);
  justify-items: start;
  padding: var(--sp-6) var(--sp-5);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-lg);
  background: var(--bg-raised);
}
.notice__title { font-family: var(--font-display); font-weight: 800; font-size: var(--text-md); }
.notice__body { color: var(--ink-muted); font-size: var(--text-sm); max-width: 60ch; }
.notice--danger { border-color: var(--danger-edge); background: var(--danger-wash); }
.notice--warn { border-color: var(--warn-edge); background: var(--warn-wash); }

.skeleton {
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--bg-inset) 0%, var(--bg-hover) 40%, var(--bg-inset) 80%);
  background-size: 200% 100%;
  animation: sweep 1.4s linear infinite;
  color: transparent !important;
  user-select: none;
}
@keyframes sweep { from { background-position: 160% 0; } to { background-position: -60% 0; } }

.skeleton--line { height: 0.8rem; width: 100%; }
.skeleton--title { height: 1.4rem; width: 12rem; }
.skeleton--bar { height: 2.25rem; width: 100%; border-radius: var(--r-sm); }

/* A stale banner sits above the content rather than replacing it: the numbers
   underneath are still true, they are just no longer current. */
.stale-note {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--warn-edge);
  background: var(--warn-wash);
  color: var(--warn);
  border-radius: var(--r-md);
  font-size: var(--text-sm);
  font-weight: 600;
}

/* ==========================================================================
 * §16  MOTION
 * --------------------------------------------------------------------------
 * Everything here is an enhancement, and the block at the bottom is the one
 * switch that turns all of it off.
 * ========================================================================== */

@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes spin { to { transform: rotate(360deg); } }

.reveal { animation: rise var(--dur-slow) var(--ease) both; }
.reveal-1 { animation-delay: 60ms; }
.reveal-2 { animation-delay: 140ms; }
.reveal-3 { animation-delay: 220ms; }

.spin { animation: spin 1s linear infinite; }

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